21 #include "config_auto.h"
94 ColPartition* neighbour;
141 bool any_done =
false;
143 bool merge_done =
false;
153 if (!box_cb->
Run(part, &box))
156 ColPartition_CLIST merge_candidates;
157 FindMergeCandidates(part, box, debug, &merge_candidates);
159 int overlap_increase;
163 if (neighbour !=
NULL && overlap_increase <= 0) {
165 tprintf(
"Merging:hoverlap=%d, voverlap=%d, OLI=%d\n",
178 }
else if (neighbour !=
NULL) {
180 tprintf(
"Overlapped when merged with increase %d: ", overlap_increase);
184 tprintf(
"No candidate neighbour returned\n");
186 }
while (merge_done);
199 if (candidate == part)
206 tprintf(
"Examining merge candidate:");
214 tprintf(
"Too far away: h_dist = %d\n", h_dist);
222 tprintf(
"Too far away: v_dist = %d\n", v_dist);
231 tprintf(
"Candidate fails overlap and diacritic tests!\n");
243 static int IncreaseInOverlap(
const ColPartition* merge1,
244 const ColPartition* merge2,
246 ColPartition_CLIST* parts) {
249 ColPartition_C_IT it(parts);
250 TBOX merged_box(merge1->bounding_box());
251 merged_box += merge2->bounding_box();
252 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
253 ColPartition* part = it.data();
254 if (part == merge1 || part == merge2)
256 TBOX part_box = part->bounding_box();
259 if (overlap_area > 0 && !part->OKMergeOverlap(*merge1, *merge2,
260 ok_overlap,
false)) {
261 total_area += overlap_area;
263 overlap_area = part_box.
intersection(merge1->bounding_box()).area();
264 if (overlap_area > 0)
265 total_area -= overlap_area;
267 overlap_area = intersection_box.
area();
268 if (overlap_area > 0) {
269 total_area -= overlap_area;
271 intersection_box &= merge1->bounding_box();
272 overlap_area = intersection_box.
area();
273 if (overlap_area > 0)
274 total_area += overlap_area;
302 static bool TestCompatibleCandidates(
const ColPartition& part,
bool debug,
303 ColPartition_CLIST* candidates) {
304 ColPartition_C_IT it(candidates);
305 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
306 ColPartition* candidate = it.data();
307 if (!candidate->OKDiacriticMerge(part,
false)) {
308 ColPartition_C_IT it2(it);
309 for (it2.mark_cycle_pt(); !it2.cycled_list(); it2.forward()) {
310 ColPartition* candidate2 = it2.data();
311 if (candidate2 != candidate &&
312 !OKMergeCandidate(candidate, candidate2,
false)) {
314 tprintf(
"NC overlap failed:Candidate:");
315 candidate2->bounding_box().print();
316 tprintf(
"fails to be a good merge with:");
317 candidate->bounding_box().print();
331 int total_overlap = 0;
337 ColPartition_CLIST neighbors;
340 ColPartition_C_IT n_it(&neighbors);
341 bool any_part_overlap =
false;
342 for (n_it.mark_cycle_pt(); !n_it.cycled_list(); n_it.forward()) {
343 const TBOX& n_box = n_it.data()->bounding_box();
345 if (overlap > 0 && overlap_grid !=
NULL) {
346 if (*overlap_grid ==
NULL) {
349 (*overlap_grid)->InsertBBox(
true,
true, n_it.data()->ShallowCopy());
350 if (!any_part_overlap) {
351 (*overlap_grid)->InsertBBox(
true,
true, part->
ShallowCopy());
354 any_part_overlap =
true;
355 total_overlap += overlap;
358 return total_overlap;
366 ColPartition_CLIST* parts) {
371 if (part != not_this)
372 parts->add_sorted(SortByBoxLeft<ColPartition>,
true, part);
418 const ColPartition* part, ColPartition_CLIST* candidates,
bool debug,
420 int* overlap_increase) {
421 if (overlap_increase !=
NULL)
422 *overlap_increase = 0;
423 if (candidates->empty())
426 static_cast<int>(kTinyEnoughTextlineOverlapFraction *
gridsize() + 0.5);
432 ColPartition_C_IT it(candidates);
435 TBOX full_box(part_box);
436 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
441 ColPartition_CLIST neighbours;
446 tprintf(
"Finding best merge candidate from %d, %d neighbours for box:",
447 candidates->length(), neighbours.length());
455 ColPartition_CLIST non_candidate_neighbours;
456 non_candidate_neighbours.set_subtract(SortByBoxLeft<ColPartition>,
true,
457 &neighbours, candidates);
458 int worst_nc_increase = 0;
461 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
463 if (confirm_cb !=
NULL && !confirm_cb->
Run(part, candidate)) {
465 tprintf(
"Candidate not confirmed:");
470 int increase = IncreaseInOverlap(part, candidate, ok_overlap, &neighbours);
472 if (best_candidate ==
NULL || increase < best_increase) {
473 best_candidate = candidate;
474 best_increase = increase;
477 tprintf(
"New best merge candidate has increase %d, area %d, over box:",
478 increase, best_area);
482 }
else if (increase == best_increase) {
484 if (area < best_area) {
486 best_candidate = candidate;
489 increase = IncreaseInOverlap(part, candidate, ok_overlap,
490 &non_candidate_neighbours);
491 if (increase > worst_nc_increase)
492 worst_nc_increase = increase;
494 if (best_increase > 0) {
501 if (worst_nc_increase < best_increase &&
502 TestCompatibleCandidates(*part, debug, candidates)) {
503 best_increase = worst_nc_increase;
506 if (overlap_increase !=
NULL)
507 *overlap_increase = best_increase;
508 return best_candidate;
514 ColPartition_LIST* part_list) {
527 ColPartition_LIST* big_parts) {
529 static_cast<int>(kTinyEnoughTextlineOverlapFraction *
gridsize() + 0.5);
540 int unresolved_overlaps = 0;
544 if (neighbour == part)
558 if (!shrunken.
overlap(neighbour_box) &&
560 kBigPartSizeRatio * shrunken.
height()) {
563 RemoveBadBox(excluded, part, big_parts);
568 }
else if (box.
contains(neighbour_box)) {
569 ++unresolved_overlaps;
577 kBigPartSizeRatio * shrunken.
height()) {
580 RemoveBadBox(excluded, neighbour, big_parts);
589 if (neighbour_overlap_count <= part_overlap_count ||
593 if (split_blob !=
NULL) {
602 if (split_blob !=
NULL) {
609 if (right_part !=
NULL) {
616 if (unresolved_overlaps > 2 && part->
IsSingleton()) {
619 ColPartition_IT big_it(big_parts);
621 big_it.add_to_end(part);
644 bool any_changed =
false;
650 if (SmoothRegionType(nontext_map, im_box, rotation, debug, part))
660 const FCOORD& rerotation) {
661 if (scaled_color ==
NULL)
663 Pix* color_map1 =
NULL;
664 Pix* color_map2 =
NULL;
667 int width = pixGetWidth(scaled_color);
668 int height = pixGetHeight(scaled_color);
669 color_map1 = pixCreate(width, height, 32);
670 color_map2 = pixCreate(width, height, 32);
671 rms_map = pixCreate(width, height, 8);
682 color_map1, color_map2, rms_map,
685 if (color_map1 !=
NULL) {
686 pixWrite(
"swcolorinput.png", scaled_color, IFF_PNG);
687 pixWrite(
"swcolor1.png", color_map1, IFF_PNG);
688 pixWrite(
"swcolor2.png", color_map2, IFF_PNG);
689 pixWrite(
"swrms.png", rms_map, IFF_PNG);
690 pixDestroy(&color_map1);
691 pixDestroy(&color_map2);
692 pixDestroy(&rms_map);
699 ColPartition_LIST parts;
700 ColPartition_IT part_it(&parts);
706 part_it.add_after_then_move(part);
713 for (part_it.move_to_first(); !part_it.empty(); part_it.forward()) {
714 part = part_it.extract();
727 TO_BLOCK_LIST* to_blocks) {
728 TO_BLOCK_IT to_block_it(to_blocks);
729 BLOCK_IT block_it(blocks);
731 ColPartition_LIST parts;
732 ColPartition_IT part_it(&parts);
738 part_it.add_after_then_move(part);
760 TO_ROW_IT row_it(to_block->
get_rows());
761 row_it.add_after_then_move(row);
765 to_block->
line_size =
static_cast<float>(median_width);
769 to_block->
line_size =
static_cast<float>(median_height);
773 block_it.add_to_end(block);
774 to_block_it.add_to_end(to_block);
787 ColPartition_LIST parts;
788 ColPartition_IT part_it(&parts);
794 part_it.add_after_then_move(part);
802 for (part_it.move_to_first(); !part_it.empty(); part_it.forward()) {
803 part = part_it.extract();
835 ColPartition_LIST* part_lists =
new ColPartition_LIST[
gridheight()];
842 bool any_parts_found =
false;
850 ColPartition_IT part_it(&part_lists[grid_y]);
851 part_it.add_to_end(part);
852 any_parts_found =
true;
855 if (any_parts_found) {
856 for (
int grid_y = 0; grid_y <
gridheight(); ++grid_y) {
858 if (!part_lists[grid_y].empty()) {
864 delete [] part_lists;
865 return any_parts_found;
889 if (single_column_part ==
NULL) {
893 single_column_part->
CopyLeftTab(*single_column_part,
false);
894 single_column_part->
CopyRightTab(*single_column_part,
false);
904 if (single_column_part !=
NULL) {
928 BLOBNBOX_IT im_blob_it(im_blobs);
929 ColPartition_LIST dead_parts;
930 ColPartition_IT dead_part_it(&dead_parts);
938 bool any_blobs_moved =
false;
940 BLOBNBOX_C_IT blob_it(part->
boxes());
941 for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
943 im_blob_it.add_after_then_move(blob);
947 BLOBNBOX_C_IT blob_it(part->
boxes());
948 for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
956 any_blobs_moved =
true;
965 BLOBNBOX_C_IT blob_it(part->
boxes());
967 dead_part_it.add_to_end(part);
969 for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
973 delete blob->
cblob();
977 }
else if (any_blobs_moved) {
992 ColPartition_LIST saved_parts;
993 ColPartition_IT part_it(&saved_parts);
999 part_it.add_to_end(part);
1002 Init(gridsize, bleft, tright);
1004 for (part_it.move_to_first(); !part_it.empty(); part_it.forward()) {
1005 part = part_it.extract();
1025 ? best_columns[gsearch.
GridY()]
1027 FindPartitionMargins(columns, part);
1030 tprintf(
"Computed margins for part:");
1042 ColPartition_LIST* parts) {
1043 ColPartition_IT part_it(parts);
1044 for (part_it.mark_cycle_pt(); !part_it.cycled_list(); part_it.forward()) {
1047 if (best_columns !=
NULL) {
1052 columns = best_columns[grid_y];
1054 FindPartitionMargins(columns, part);
1060 ColPartition_LIST dead_parts;
1061 ColPartition_IT dead_it(&dead_parts);
1067 dead_it.add_to_end(part);
1126 for (
int upper = 0; upper < 2; ++upper) {
1130 for (partner_it.mark_cycle_pt(); !partner_it.cycled_list();
1131 partner_it.forward()) {
1137 if (!partner_it.cycled_list())
continue;
1139 for (partner_it.mark_cycle_pt(); !partner_it.cycled_list();
1140 partner_it.forward()) {
1145 tprintf(
"Finding figure captions for image part:");
1147 tprintf(
"Considering partner:");
1148 partner_box.
print();
1150 if (partner_box.
left() >= part_box.
left() &&
1152 int dist = partner_box.
y_gap(part_box);
1153 if (best_caption ==
NULL || dist < best_dist) {
1155 best_caption = partner;
1161 if (best_caption !=
NULL) {
1163 tprintf(
"Best caption candidate:");
1164 best_caption->bounding_box().print();
1170 int biggest_gap = 0;
1172 int total_height = 0;
1173 int mean_height = 0;
1178 partner = next_partner) {
1179 if (!partner->IsTextType()) {
1180 end_partner = partner;
1186 if (next_partner !=
NULL) {
1189 if (gap > biggest_gap) {
1191 end_partner = next_partner;
1192 mean_height = total_height / line_count;
1193 }
else if (gap < smallest_gap) {
1198 if (biggest_gap > mean_height * kMinCaptionGapHeightRatio &&
1199 biggest_gap > smallest_gap * kMinCaptionGapRatio)
1204 tprintf(
"Line count=%d, biggest gap %d, smallest%d, mean height %d\n",
1205 line_count, biggest_gap, smallest_gap, mean_height);
1206 if (end_partner !=
NULL) {
1211 if (next_partner ==
NULL && line_count <= kMaxCaptionLines)
1213 if (line_count <= kMaxCaptionLines) {
1216 partner != end_partner;
1217 partner = next_partner) {
1219 partner->SetBlobTypes();
1221 tprintf(
"Set caption type for partition:");
1222 partner->bounding_box().print();
1259 int height = top - bottom;
1260 int mid_y = (bottom + top) / 2;
1268 if (neighbour == part || neighbour->
type() ==
PT_NOISE)
1272 int neighbour_y = (neighbour_bottom + neighbour_top) / 2;
1273 if (upper != (neighbour_y > mid_y))
1278 if (best_neighbour ==
NULL)
1279 best_neighbour = neighbour;
1282 int dist = upper ? neighbour_bottom - top : bottom - neighbour_top;
1283 if (dist <= kMaxPartitionSpacing * height) {
1284 if (dist < best_dist) {
1286 best_neighbour = neighbour;
1292 if (best_neighbour !=
NULL)
1305 int width = right - left;
1306 int mid_x = (left + right) / 2;
1314 if (neighbour == part || neighbour->
type() ==
PT_NOISE)
1318 int neighbour_x = (neighbour_left + neighbour_right) / 2;
1319 if (to_the_left != (neighbour_x < mid_x))
1325 int dist = to_the_left ? left - neighbour_right : neighbour_left - right;
1326 if (dist <= kMaxPartitionSpacing * width) {
1327 if (dist < best_dist || best_neighbour ==
NULL) {
1329 best_neighbour = neighbour;
1337 if (best_neighbour !=
NULL)
1338 part->
AddPartner(to_the_left, best_neighbour);
1354 get_desperate,
this);
1367 void ColPartitionGrid::FindMergeCandidates(
const ColPartition* part,
1368 const TBOX& search_box,
bool debug,
1369 ColPartition_CLIST* candidates) {
1371 static_cast<int>(kTinyEnoughTextlineOverlapFraction *
gridsize() + 0.5);
1375 rsearch.SetUniqueMode(
true);
1376 rsearch.StartRectSearch(search_box);
1378 while ((candidate = rsearch.NextRectSearch()) !=
NULL) {
1379 if (!OKMergeCandidate(part, candidate, debug))
1396 TBOX merged_box(part_box);
1397 merged_box += c_box;
1399 msearch.SetUniqueMode(
true);
1400 msearch.StartRectSearch(merged_box);
1402 while ((neighbour = msearch.NextRectSearch()) !=
NULL) {
1403 if (neighbour == part || neighbour == candidate)
1405 if (neighbour->
OKMergeOverlap(*part, *candidate, ok_overlap,
false))
1412 !OKMergeCandidate(part, neighbour,
false) &&
1413 !OKMergeCandidate(candidate, neighbour,
false))
1416 if (neighbour !=
NULL) {
1418 tprintf(
"Combined box overlaps another that is not OK despite"
1419 " allowance of %d:", ok_overlap);
1422 OKMergeCandidate(part, neighbour,
true);
1424 OKMergeCandidate(candidate, neighbour,
true);
1436 candidates->add_sorted(SortByBoxLeft<ColPartition>,
true, candidate);
1451 bool ColPartitionGrid::SmoothRegionType(Pix* nontext_map,
1453 const FCOORD& rerotation,
1455 ColPartition* part) {
1456 const TBOX& part_box = part->bounding_box();
1458 tprintf(
"Smooothing part at:");
1464 max_dist =
MAX(max_dist * kMaxNeighbourDistFactor,
gridsize() * 2);
1466 bool any_image =
false;
1467 bool all_image =
true;
1471 BlobRegionType type = SmoothInOneDirection(dir, nontext_map, im_box,
1472 rerotation, debug, *part,
1475 tprintf(
"Result in dir %d = %d at dist %d\n", dir, type, dist);
1486 if (best_dist > max_dist)
1493 if (best_type ==
BRT_TEXT && !any_image) {
1503 if (new_type != part->blob_type() || new_flow != part->flow()) {
1504 part->set_flow(new_flow);
1505 part->set_blob_type(new_type);
1506 part->SetBlobTypes();
1521 const TBOX& part_box,
1525 *search_box = part_box;
1529 padding =
MAX(padding, min_padding);
1531 search_box->
pad(padding, padding);
1534 switch (direction) {
1537 *dist_scaling =
ICOORD(2, 1);
1541 *dist_scaling =
ICOORD(1, 2);
1545 *dist_scaling =
ICOORD(2, 1);
1549 *dist_scaling =
ICOORD(1, 2);
1577 const TBOX& im_box,
const FCOORD& rerotation,
1578 bool debug,
const ColPartition& part,
int* best_distance) {
1580 TBOX part_box = part.bounding_box();
1583 ComputeSearchBoxAndScaling(direction, part_box,
gridsize(),
1584 &search_box, &dist_scaling);
1589 AccumulatePartDistances(part, dist_scaling, search_box,
1590 nontext_map, im_box, rerotation, debug, dists);
1595 memset(counts, 0,
sizeof(counts[0]) *
NPT_COUNT);
1597 int image_bias = image_region ? kSmoothDecisionMargin / 2 : 0;
1605 if (counts[i] < dists[i].size() && dists[i][counts[i]] < min_dist)
1606 min_dist = dists[i][counts[i]];
1610 while (counts[i] < dists[i].size() && dists[i][counts[i]] <= min_dist)
1613 *best_distance = min_dist;
1615 tprintf(
"Totals: htext=%d+%d, vtext=%d+%d, image=%d+%d, at dist=%d\n",
1618 counts[
NPT_IMAGE], image_bias, min_dist);
1626 if (image_count > 0 &&
1627 image_bias - htext_score >= kSmoothDecisionMargin &&
1628 image_bias - vtext_score >= kSmoothDecisionMargin) {
1658 void ColPartitionGrid::AccumulatePartDistances(
const ColPartition& base_part,
1659 const ICOORD& dist_scaling,
1660 const TBOX& search_box,
1663 const FCOORD& rerotation,
1666 const TBOX& part_box = base_part.bounding_box();
1668 rsearch.SetUniqueMode(
true);
1669 rsearch.StartRectSearch(search_box);
1670 ColPartition* neighbour;
1673 while ((neighbour = rsearch.NextRectSearch()) !=
NULL) {
1674 if (neighbour->IsUnMergeableType() ||
1675 !base_part.ConfirmNoTabViolation(*neighbour) ||
1676 neighbour == &base_part)
1678 TBOX nbox = neighbour->bounding_box();
1686 int x_gap =
MAX(part_box.
x_gap(nbox), 0);
1687 int y_gap =
MAX(part_box.
y_gap(nbox), 0);
1688 int n_dist = x_gap * dist_scaling.
x() + y_gap* dist_scaling.
y();
1690 tprintf(
"Part has x-gap=%d, y=%d, dist=%d at:",
1691 x_gap, y_gap, n_dist);
1713 if (debug)
tprintf(
"Weak %d\n", n_boxes);
1716 if (debug)
tprintf(
"Image %d\n", n_boxes);
1718 if (count_vector !=
NULL) {
1719 for (
int i = 0; i < n_boxes; ++i)
1734 void ColPartitionGrid::FindPartitionMargins(ColPartitionSet* columns,
1735 ColPartition* part) {
1738 int y = part->MidY();
1740 int left_margin =
bleft().
x();
1741 int right_margin =
tright().
x();
1742 if (columns !=
NULL) {
1743 ColPartition* column = columns->ColumnContaining(box.
left(), y);
1745 left_margin = column->LeftAtY(y);
1746 column = columns->ColumnContaining(box.
right(), y);
1748 right_margin = column->RightAtY(y);
1753 left_margin = FindMargin(box.
left() + box.
height(),
true, left_margin,
1755 part->set_left_margin(left_margin);
1757 right_margin = FindMargin(box.
right() - box.
height(),
false, right_margin,
1759 part->set_right_margin(right_margin);
1765 int ColPartitionGrid::FindMargin(
int x,
bool right_to_left,
int x_limit,
1766 int y_bottom,
int y_top,
1767 const ColPartition* not_this) {
1768 int height = y_top - y_bottom;
1771 side_search.SetUniqueMode(
true);
1772 side_search.StartSideSearch(x, y_bottom, y_top);
1774 while ((part = side_search.NextSideSearch(right_to_left)) !=
NULL) {
1776 if (part == not_this)
1780 TBOX box = part->bounding_box();
1781 int min_overlap =
MIN(height, box.
height());
1782 min_overlap =
static_cast<int>(min_overlap * kMarginOverlapFraction + 0.5);
1784 if (y_overlap < min_overlap)
1787 int x_edge = right_to_left ? box.
right() : box.
left();
1788 if ((x_edge < x) != right_to_left)
1791 if ((x_edge < x_limit) == right_to_left)
void RefinePartners(PolyBlockType type, bool get_desparate, ColPartitionGrid *grid)
void Init(int gridsize, const ICOORD &bleft, const ICOORD &tright)
bool IsVerticalType() const
bool ReleaseNonLeaderBoxes()
static bool WithinTestRegion(int detail_level, int x, int y)
const ICOORD & botleft() const
static int CountPixelsInRotatedBox(TBOX box, const TBOX &im_box, const FCOORD &rotation, Pix *pix)
ColPartition * ShallowCopy() const
ColPartition_CLIST * upper_partners()
void ExtractPartitionsAsBlocks(BLOCK_LIST *blocks, TO_BLOCK_LIST *to_blocks)
void set_poly_block(POLY_BLOCK *blk)
set the poly block
bool GridSmoothNeighbours(BlobTextFlowType source_type, Pix *nontext_map, const TBOX &im_box, const FCOORD &rerotation)
void CopyRightTab(const ColPartition &src, bool take_box)
BBC * NextVerticalSearch(bool top_to_bottom)
void SetRightTab(const TabVector *tab_vector)
void FindVPartitionPartners(bool to_the_left, ColPartition *part)
const TBOX & bounding_box() const
void set_owner(tesseract::ColPartition *new_owner)
void SetTabStops(TabFind *tabgrid)
int direction(EDGEPT *point)
void RepositionIterator()
static void ComputeRectangleColors(const TBOX &rect, Pix *pix, int factor, Pix *color_map1, Pix *color_map2, Pix *rms_map, uinT8 *color1, uinT8 *color2)
#define BOOL_VAR(name, val, comment)
BlobRegionType blob_type() const
void SetLeftTab(const TabVector *tab_vector)
void FindOverlappingPartitions(const TBOX &box, const ColPartition *not_this, ColPartition_CLIST *parts)
BLOBNBOX * OverlapSplitBlob(const TBOX &box)
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
void DeleteNonLeaderParts()
BBC * NextSideSearch(bool right_to_left)
void GridFindMargins(ColPartitionSet **best_columns)
void rotate_large(const FCOORD &vec)
int HCoreOverlap(const ColPartition &other) const
void set_flow(BlobTextFlowType value)
void ComputePartitionColors(Pix *scaled_color, int scaled_factor, const FCOORD &rerotation)
void pad(int xpad, int ypad)
bool HOverlaps(const ColPartition &other) const
int median_bottom() const
const double kStrokeWidthFractionTolerance
void InsertBBox(bool h_spread, bool v_spread, ColPartition *bbox)
TabVector * RightTabForBox(const TBOX &box, bool crossing, bool extended)
TBOX BoundsWithoutBox(BLOBNBOX *box)
void SplitOverlappingPartitions(ColPartition_LIST *big_parts)
void DeleteUnownedNoise()
void CopyLeftTab(const ColPartition &src, bool take_box)
void SetUniqueMode(bool mode)
void StartRadSearch(int x, int y, int max_radius)
bool OKMergeOverlap(const ColPartition &merge1, const ColPartition &merge2, int ok_box_overlap, bool debug)
inT16 y() const
access_function
const int kMaxCaptionLines
void DeleteUnknownParts(TO_BLOCK *block)
ColPartition * SingletonPartner(bool upper)
const double kTinyEnoughTextlineOverlapFraction
int y_gap(const TBOX &box) const
BlobTextFlowType flow() const
const double kMarginOverlapFraction
BlobRegionType region_type() const
bool WithinSameMargins(const ColPartition &other) const
static bool IsLineType(BlobRegionType type)
const double kMinCaptionGapRatio
bool VOverlaps(const ColPartition &other) const
void Deskew(const FCOORD &deskew)
TBOX bounding_union(const TBOX &box) const
ColPartition * SplitAtBlob(BLOBNBOX *split_blob)
void HandleClick(int x, int y)
void RecomputeBounds(int gridsize, const ICOORD &bleft, const ICOORD &tright, const ICOORD &vertical)
const ICOORD & bleft() const
void FindPartitionPartners()
const int kMaxNeighbourDistFactor
int ComputeTotalOverlap(ColPartitionGrid **overlap_grid)
const double kBigPartSizeRatio
void ReTypeBlobs(BLOBNBOX_LIST *im_blobs)
bool TypesMatch(const ColPartition &other) const
void set_blob_type(BlobRegionType t)
bool textord_tabfind_show_color_fit
ColPartitionSet * MakeSingleColumnSet(WidthCallback *cb)
ColPartition_CLIST * lower_partners()
void set_vertical(const ICOORD &v)
PolyBlockType type() const
void Merges(TessResultCallback2< bool, ColPartition *, TBOX * > *box_cb, TessResultCallback2< bool, const ColPartition *, const ColPartition * > *confirm_cb)
void StartSideSearch(int x, int ymin, int ymax)
const double kMaxPartitionSpacing
void Absorb(ColPartition *other, WidthCallback *cb)
void StartRectSearch(const TBOX &rect)
TBOX intersection(const TBOX &box) const
void ListFindMargins(ColPartitionSet **best_columns, ColPartition_LIST *parts)
void set_flow(BlobTextFlowType f)
int x_gap(const TBOX &box) const
void set_block_owned(bool owned)
virtual ~ColPartitionGrid()
const int kMaxRMSColorNoise
inT16 x() const
access function
void set_region_type(BlobRegionType new_type)
bool IsUnMergeableType() const
WidthCallback * WidthCB()
const int kHorzStrongTextlineCount
static ColPartition * MakeBigPartition(BLOBNBOX *box, ColPartition_LIST *big_part_list)
bool contains(const FCOORD pt) const
int VCoreOverlap(const ColPartition &other) const
const ICOORD & tright() const
void SetColumnGoodness(WidthCallback *cb)
const double kMinCaptionGapHeightRatio
static bool IsTextType(BlobRegionType type)
const ICOORD & topright() const
const TBOX & bounding_box() const
void FindFigureCaptions()
TabVector * LeftTabForBox(const TBOX &box, bool crossing, bool extended)
const int kColumnWidthFactor
void RemoveBBox(ColPartition *bbox)
int CountOverlappingBoxes(const TBOX &box)
bool OKDiacriticMerge(const ColPartition &candidate, bool debug) const
ColPartition * BestMergeCandidate(const ColPartition *part, ColPartition_CLIST *candidates, bool debug, TessResultCallback2< bool, const ColPartition *, const ColPartition * > *confirm_cb, int *overlap_increase)
bool MergePart(TessResultCallback2< bool, ColPartition *, TBOX * > *box_cb, TessResultCallback2< bool, const ColPartition *, const ColPartition * > *confirm_cb, ColPartition *part)
BlobTextFlowType flow() const
bool MakeColPartSets(PartSetVector *part_sets)
static bool BlankImageInBetween(const TBOX &box1, const TBOX &box2, const TBOX &im_box, const FCOORD &rotation, Pix *pix)
void AddPartner(bool upper, ColPartition *partner)
bool overlap(const TBOX &box) const
bool VSignificantCoreOverlap(const ColPartition &other) const
void RemoveBox(BLOBNBOX *box)
const int kSmoothDecisionMargin
void GridCoords(int x, int y, int *grid_x, int *grid_y) const
const double kStrokeWidthConstantTolerance
void RefinePartitionPartners(bool get_desperate)
void StartVerticalSearch(int xmin, int xmax, int y)