Tesseract 3.02

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Macros | Functions
seam.cpp File Reference
`#include "seam.h"`
`#include "blobs.h"`
`#include "callcpp.h"`
`#include "structures.h"`

Go to the source code of this file.

## Macros
#define | NUM_STARTING_SEAMS 20

## Functions
| makestructure (newseam, free_seam, SEAM)
point_in_split
Check to see if either of these points are present in the current split. Returns: TRUE if one of them is split.
bool | point_in_split (SPLIT *split, EDGEPT *point1, EDGEPT *point2)
point_in_seam
Check to see if either of these points are present in the current seam. Returns: TRUE if one of them is.
bool | point_in_seam (SEAM *seam, SPLIT *split)
point_used_by_split
Return whether this particular EDGEPT * is used in a given split. Returns: TRUE if the edgept is used by the split.
bool | point_used_by_split (SPLIT *split, EDGEPT *point)
point_used_by_seam
Return whether this particular EDGEPT * is used in a given seam. Returns: TRUE if the edgept is used by the seam.
bool | point_used_by_seam (SEAM *seam, EDGEPT *point)
add_seam
Add another seam to a collection of seams.
SEAMS | add_seam (SEAMS seam_list, SEAM *seam)
combine_seam
Combine two seam records into a single seam. Move the split references from the second seam to the first one. The argument convention is patterned after strcpy.
void | combine_seams (SEAM *dest_seam, SEAM *source_seam)
delete_seam
Free this seam record and the splits that are attached to it.
void | delete_seam (void *arg)
start_seam_list
Initialize a list of seams that match the original number of blobs present in the starting segmentation. Each of the seams created by this routine have location information only.
SEAMS | start_seam_list (TBLOB *blobs)
free_seam_list
Free all the seams that have been allocated in this list. Reclaim the memory for each of the splits as well.
void | free_seam_list (SEAMS seam_list)
test_insert_seam
Returns: true if insert_seam will succeed.
bool | test_insert_seam (SEAMS seam_list, int index, TBLOB *left_blob, TBLOB *first_blob)
insert_seam
Add another seam to a collection of seams at a particular location in the seam array.
SEAMS | insert_seam (SEAMS seam_list, int index, SEAM *seam, TBLOB *left_blob, TBLOB *first_blob)
account_splits_right
Account for all the splits by looking to the right. in the blob list.
int | account_splits_right (SEAM *seam, TBLOB *blob)
account_splits_left
Account for all the splits by looking to the left. in the blob list.
int | account_splits_left (SEAM *seam, TBLOB *blob, TBLOB *end_blob)
void | account_splits_left_helper (SEAM *seam, TBLOB *blob, TBLOB *end_blob, inT32 *depth, inT8 *width, inT8 *found_em)
find_split_in_blob
Returns: TRUE if the split is somewhere in this blob.
bool | find_split_in_blob (SPLIT *split, TBLOB *blob)
join_two_seams
Merge these two seams into a new seam. Duplicate the split records in both of the input seams. Return the resultant seam.
SEAM * | join_two_seams (SEAM *seam1, SEAM *seam2)
new_seam
Create a structure for a "seam" between two blobs. This data structure may actually hold up to three different splits. Initailization of this record is done by this routine.
SEAM * | new_seam (PRIORITY priority, const TPOINT &location, SPLIT *split1, SPLIT *split2, SPLIT *split3)
new_seam_list
Create a collection of seam records in an array.
SEAMS | new_seam_list ()
print_seam
Print a list of splits. Show the coordinates of both points in each split.
void | print_seam (const char *label, SEAM *seam)
print_seams
Print a list of splits. Show the coordinates of both points in each split.
void | print_seams (const char *label, SEAMS seams)
shared_split_points
Check these two seams to make sure that neither of them have two points in common. Return TRUE if any of the same points are present in any of the splits of both seams.
int | shared_split_points (SEAM *seam1, SEAM *seam2)
void | break_pieces (TBLOB *blobs, SEAMS seams, inT16 start, inT16 end)
void | join_pieces (TBLOB *piece_blobs, SEAMS seams, inT16 start, inT16 end)
void | hide_seam (SEAM *seam)
void | hide_edge_pair (EDGEPT *pt1, EDGEPT *pt2)
void | reveal_seam (SEAM *seam)
void | reveal_edge_pair (EDGEPT *pt1, EDGEPT *pt2)

## Macro Definition Documentation

#define NUM_STARTING_SEAMS 20

Definition at line 40 of file seam.cpp.

## Function Documentation

int account_splits_left | ( | SEAM * | seam,
|  | TBLOB * | blob,
|  | TBLOB * | end_blob
| ) |  |

Definition at line 334 of file seam.cpp.

{
inT32 depth = 0;
inT8 width = 0;
inT8 found_em[3];
account_splits_left_helper(seam, blob, end_blob, &depth, &width, found_em);
return width;
}

void account_splits_left_helper | ( | SEAM * | seam,
|  | TBLOB * | blob,
|  | TBLOB * | end_blob,
|  | inT32 * | depth,
|  | inT8 * | width,
|  | inT8 * | found_em
| ) |  |

Definition at line 342 of file seam.cpp.

{
if (blob != end_blob) {
(*depth)++;
account_splits_left_helper(seam, blob->next, end_blob,
depth, width, found_em);
(*depth)--;
} else {
found_em[0] = seam->split1 == NULL;
found_em[1] = seam->split2 == NULL;
found_em[2] = seam->split3 == NULL;
*width = 0;
}
if (!found_em[0])
found_em[0] = find_split_in_blob(seam->split1, blob);
if (!found_em[1])
found_em[1] = find_split_in_blob(seam->split2, blob);
if (!found_em[2])
found_em[2] = find_split_in_blob(seam->split3, blob);
if (!found_em[0] || !found_em[1] || !found_em[2]) {
(*width)++;
if (*depth == 0) {
*width = -1;
}
}
}

int account_splits_right | ( | SEAM * | seam,
|  | TBLOB * | blob
| ) |  |

Definition at line 301 of file seam.cpp.

{
inT8 found_em[3];
inT8 width;
found_em[0] = seam->split1 == NULL;
found_em[1] = seam->split2 == NULL;
found_em[2] = seam->split3 == NULL;
if (found_em[0] && found_em[1] && found_em[2])
return 0;
width = 0;
do {
if (!found_em[0])
found_em[0] = find_split_in_blob(seam->split1, blob);
if (!found_em[1])
found_em[1] = find_split_in_blob(seam->split2, blob);
if (!found_em[2])
found_em[2] = find_split_in_blob(seam->split3, blob);
if (found_em[0] && found_em[1] && found_em[2]) {
return width;
}
width++;
blob = blob->next;
} while (blob != NULL);
return -1;
}

SEAMS add_seam | ( | SEAMS | seam_list,
|  | SEAM * | seam
| ) |  |

Definition at line 104 of file seam.cpp.

{
return (array_push (seam_list, seam));
}

void break_pieces | ( | TBLOB * | blobs,
|  | SEAMS | seams,
|  | inT16 | start,
|  | inT16 | end
| ) |  |

Definition at line 535 of file seam.cpp.

{
TESSLINE *outline = blobs->outlines;
TBLOB *next_blob;
inT16 x;
for (x = start; x < end; x++)
reveal_seam ((SEAM *) array_value (seams, x));
next_blob = blobs->next;
while (outline && next_blob) {
if (outline->next == next_blob->outlines) {
outline->next = NULL;
outline = next_blob->outlines;
next_blob = next_blob->next;
}
else {
outline = outline->next;
}
}
}

void combine_seams | ( | SEAM * | dest_seam,
|  | SEAM * | source_seam
| ) |  |

Definition at line 116 of file seam.cpp.

{
dest_seam->priority += source_seam->priority;
dest_seam->location += source_seam->location;
dest_seam->location /= 2;
if (source_seam->split1) {
if (!dest_seam->split1)
dest_seam->split1 = source_seam->split1;
else if (!dest_seam->split2)
dest_seam->split2 = source_seam->split1;
else if (!dest_seam->split3)
dest_seam->split3 = source_seam->split1;
else
cprintf("combine_seam: Seam is too crowded, can't be combined !\n");
}
if (source_seam->split2) {
if (!dest_seam->split2)
dest_seam->split2 = source_seam->split2;
else if (!dest_seam->split3)
dest_seam->split3 = source_seam->split2;
else
cprintf("combine_seam: Seam is too crowded, can't be combined !\n");
}
if (source_seam->split3) {
if (!dest_seam->split3)
dest_seam->split3 = source_seam->split3;
else
cprintf("combine_seam: Seam is too crowded, can't be combined !\n");
}
free_seam(source_seam);
}

void delete_seam | ( | void * | arg | ) |

Definition at line 154 of file seam.cpp.

{ //SEAM *seam)
SEAM *seam = (SEAM *) arg;
if (seam) {
if (seam->split1)
delete_split(seam->split1);
if (seam->split2)
delete_split(seam->split2);
if (seam->split3)
delete_split(seam->split3);
free_seam(seam);
}
}

bool find_split_in_blob | ( | SPLIT * | split,
|  | TBLOB * | blob
| ) |  |

Definition at line 375 of file seam.cpp.

{
TESSLINE *outline;
for (outline = blob->outlines; outline != NULL; outline = outline->next)
if (outline->Contains(split->point1->pos))
break;
if (outline == NULL)
return FALSE;
for (outline = blob->outlines; outline != NULL; outline = outline->next)
if (outline->Contains(split->point2->pos))
return TRUE;
return FALSE;
}

void free_seam_list | ( | SEAMS | seam_list | ) |

Definition at line 200 of file seam.cpp.

{
int x;
array_loop(seam_list, x) delete_seam(array_value (seam_list, x));
array_free(seam_list);
}

void hide_edge_pair | ( | EDGEPT * | pt1,
|  | EDGEPT * | pt2
| ) |  |

Definition at line 619 of file seam.cpp.

{
EDGEPT *edgept;
edgept = pt1;
do {
edgept->Hide();
edgept = edgept->next;
}
while (!exact_point (edgept, pt2) && edgept != pt1);
if (edgept == pt1) {
/* cprintf("Hid entire outline at (%d,%d)!!\n",
edgept->pos.x,edgept->pos.y); */
}
edgept = pt2;
do {
edgept->Hide();
edgept = edgept->next;
}
while (!exact_point (edgept, pt1) && edgept != pt2);
if (edgept == pt2) {
/* cprintf("Hid entire outline at (%d,%d)!!\n",
edgept->pos.x,edgept->pos.y); */
}
}

void hide_seam | ( | SEAM * | seam | ) |

Definition at line 598 of file seam.cpp.

{
if (seam == NULL || seam->split1 == NULL)
return;
hide_edge_pair (seam->split1->point1, seam->split1->point2);
if (seam->split2 == NULL)
return;
hide_edge_pair (seam->split2->point1, seam->split2->point2);
if (seam->split3 == NULL)
return;
hide_edge_pair (seam->split3->point1, seam->split3->point2);
}

SEAMS insert_seam | ( | SEAMS | seam_list,
|  | int | index,
|  | SEAM * | seam,
|  | TBLOB * | left_blob,
|  | TBLOB * | first_blob
| ) |  |

Definition at line 250 of file seam.cpp.

{
SEAM *test_seam;
TBLOB *blob;
int test_index;
int list_length;
list_length = array_count(seam_list);
for (test_index=0, blob=first_blob->next;
test_index < index;
test_index++, blob=blob->next) {
test_seam = (SEAM *) array_value(seam_list, test_index);
if (test_index + test_seam->widthp >= index) {
test_seam->widthp++; /*got in the way */
} else if (test_seam->widthp + test_index == index - 1) {
test_seam->widthp = account_splits_right(test_seam, blob);
if (test_seam->widthp < 0) {
cprintf("Failed to find any right blob for a split!\n");
print_seam("New dud seam", seam);
print_seam("Failed seam", test_seam);
}
}
}
for (test_index=index, blob=left_blob->next;
test_index < list_length;
test_index++, blob=blob->next) {
test_seam = (SEAM *) array_value(seam_list, test_index);
if (test_index - test_seam->widthn < index) {
test_seam->widthn++; /*got in the way */
} else if (test_index - test_seam->widthn == index) {
test_seam->widthn = account_splits_left(test_seam, first_blob, blob);
if (test_seam->widthn < 0) {
cprintf("Failed to find any left blob for a split!\n");
print_seam("New dud seam", seam);
print_seam("Failed seam", test_seam);
}
}
}
return (array_insert (seam_list, index, seam));
}

void join_pieces | ( | TBLOB * | piece_blobs,
|  | SEAMS | seams,
|  | inT16 | start,
|  | inT16 | end
| ) |  |

Definition at line 564 of file seam.cpp.

{
TBLOB *next_blob;
TBLOB *blob;
inT16 x;
TESSLINE *outline;
SEAM *seam;
for (x = 0, blob = piece_blobs; x < start; x++)
blob = blob->next;
next_blob = blob->next;
outline = blob->outlines;
if (!outline)
return;
while (x < end) {
seam = (SEAM *) array_value (seams, x);
if (x - seam->widthn >= start && x + seam->widthp < end)
hide_seam(seam);
while (outline->next)
outline = outline->next;
outline->next = next_blob->outlines;
next_blob = next_blob->next;
x++;
}
}

SEAM* join_two_seams | ( | SEAM * | seam1,
|  | SEAM * | seam2
| ) |  |

Definition at line 396 of file seam.cpp.

{
SEAM *result = NULL;
SEAM *temp;
assert(seam1 &&seam2);
if (((seam1->split3 == NULL && seam2->split2 == NULL) ||
(seam1->split2 == NULL && seam2->split3 == NULL) ||
seam1->split1 == NULL || seam2->split1 == NULL) &&
(!shared_split_points(seam1, seam2))) {
clone_seam(result, seam1);
clone_seam(temp, seam2);
combine_seams(result, temp);
}
return (result);
}

makestructure | ( | newseam | ,
|  | free_seam | ,
|  | SEAM |
| ) |  |

SEAM* new_seam | ( | PRIORITY | priority,
|  | const TPOINT & | location,
|  | SPLIT * | split1,
|  | SPLIT * | split2,
|  | SPLIT * | split3
| ) |  |

Definition at line 421 of file seam.cpp.

{
SEAM *seam;
seam = newseam ();
seam->priority = priority;
seam->location = location;
seam->widthp = 0;
seam->widthn = 0;
seam->split1 = split1;
seam->split2 = split2;
seam->split3 = split3;
return (seam);
}

SEAMS new_seam_list | ( |  | ) |

Definition at line 447 of file seam.cpp.

{
return (array_new (NUM_STARTING_SEAMS));
}

bool point_in_seam | ( | SEAM * | seam,
|  | SPLIT * | split
| ) |  |

Definition at line 69 of file seam.cpp.

{
return (point_in_split(seam->split1, split->point1, split->point2) ||
point_in_split(seam->split2, split->point1, split->point2) ||
point_in_split(seam->split3, split->point1, split->point2));
}

bool point_in_split | ( | SPLIT * | split,
|  | EDGEPT * | point1,
|  | EDGEPT * | point2
| ) |  |

Definition at line 53 of file seam.cpp.

{
return ((split) ? ((exact_point (split->point1, point1) ||
exact_point (split->point1, point2) ||
exact_point (split->point2, point1) ||
exact_point (split->point2, point2)) ? TRUE : FALSE)
: FALSE);
}

bool point_used_by_seam | ( | SEAM * | seam,
|  | EDGEPT * | point
| ) |  |

Definition at line 92 of file seam.cpp.

{
if (seam == NULL) return false;
return point_used_by_split(seam->split1, point) ||
point_used_by_split(seam->split2, point) ||
point_used_by_split(seam->split3, point);
}

bool point_used_by_split | ( | SPLIT * | split,
|  | EDGEPT * | point
| ) |  |

Definition at line 81 of file seam.cpp.

{
if (split == NULL) return false;
return point == split->point1 || point == split->point2;
}

void print_seam | ( | const char * | label,
|  | SEAM * | seam
| ) |  |

Definition at line 458 of file seam.cpp.

{
if (seam) {
cprintf(label);
cprintf(" %6.2f @ (%d,%d), p=%d, n=%d ",
seam->priority, seam->location.x, seam->location.y,
seam->widthp, seam->widthn);
print_split(seam->split1);
if (seam->split2) {
cprintf(", ");
print_split (seam->split2);
if (seam->split3) {
cprintf(", ");
print_split (seam->split3);
}
}
cprintf ("\n");
}
}

void print_seams | ( | const char * | label,
|  | SEAMS | seams
| ) |  |

Definition at line 485 of file seam.cpp.

{
int x;
char number[CHARS_PER_LINE];
if (seams) {
cprintf("%s\n", label);
array_loop(seams, x) {
sprintf(number, "%2d: ", x);
print_seam(number, (SEAM *) array_value(seams, x));
}
cprintf("\n");
}
}

void reveal_edge_pair | ( | EDGEPT * | pt1,
|  | EDGEPT * | pt2
| ) |  |

Definition at line 672 of file seam.cpp.

{
EDGEPT *edgept;
edgept = pt1;
do {
edgept->Reveal();
edgept = edgept->next;
}
while (!exact_point (edgept, pt2) && edgept != pt1);
if (edgept == pt1) {
/* cprintf("Hid entire outline at (%d,%d)!!\n",
edgept->pos.x,edgept->pos.y); */
}
edgept = pt2;
do {
edgept->Reveal();
edgept = edgept->next;
}
while (!exact_point (edgept, pt1) && edgept != pt2);
if (edgept == pt2) {
/* cprintf("Hid entire outline at (%d,%d)!!\n",
edgept->pos.x,edgept->pos.y); */
}
}

void reveal_seam | ( | SEAM * | seam | ) |

Definition at line 651 of file seam.cpp.

{
if (seam == NULL || seam->split1 == NULL)
return;
reveal_edge_pair (seam->split1->point1, seam->split1->point2);
if (seam->split2 == NULL)
return;
reveal_edge_pair (seam->split2->point1, seam->split2->point2);
if (seam->split3 == NULL)
return;
reveal_edge_pair (seam->split3->point1, seam->split3->point2);
}

int shared_split_points | ( | SEAM * | seam1,
|  | SEAM * | seam2
| ) |  |

Definition at line 507 of file seam.cpp.

{
if (seam1 == NULL || seam2 == NULL)
return (FALSE);
if (seam2->split1 == NULL)
return (FALSE);
if (point_in_seam(seam1, seam2->split1))
return (TRUE);
if (seam2->split2 == NULL)
return (FALSE);
if (point_in_seam(seam1, seam2->split2))
return (TRUE);
if (seam2->split3 == NULL)
return (FALSE);
if (point_in_seam(seam1, seam2->split3))
return (TRUE);
return (FALSE);
}

SEAMS start_seam_list | ( | TBLOB * | blobs | ) |

Definition at line 175 of file seam.cpp.

{
TBLOB *blob;
SEAMS seam_list;
TPOINT location;
/* Seam slot per char */
seam_list = new_seam_list ();
for (blob = blobs; blob->next != NULL; blob = blob->next) {
TBOX bbox = blob->bounding_box();
TBOX nbox = blob->next->bounding_box();
location.x = (bbox.right() + nbox.left()) / 2;
location.y = (bbox.bottom() + bbox.top() + nbox.bottom() + nbox.top()) / 4;
seam_list = add_seam(seam_list,
new_seam(0.0, location, NULL, NULL, NULL));
}
return seam_list;
}

bool test_insert_seam | ( | SEAMS | seam_list,
|  | int | index,
|  | TBLOB * | left_blob,
|  | TBLOB * | first_blob
| ) |  |

Definition at line 213 of file seam.cpp.

{
SEAM *test_seam;
TBLOB *blob;
int test_index;
int list_length;
list_length = array_count (seam_list);
for (test_index=0, blob=first_blob->next;
test_index < index;
test_index++, blob=blob->next) {
test_seam = (SEAM *) array_value(seam_list, test_index);
if (test_index + test_seam->widthp < index &&
test_seam->widthp + test_index == index - 1 &&
account_splits_right(test_seam, blob) < 0)
return false;
}
for (test_index=index, blob=left_blob->next;
test_index < list_length;
test_index++, blob=blob->next) {
test_seam = (SEAM *) array_value(seam_list, test_index);
if (test_index - test_seam->widthn >= index &&
test_index - test_seam->widthn == index &&
account_splits_left(test_seam, first_blob, blob) < 0)
return false;
}
return true;
}