Tesseract  3.02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
tesseract::ColPartitionGrid Class Reference

#include <colpartitiongrid.h>

Inheritance diagram for tesseract::ColPartitionGrid:
tesseract::BBGrid< ColPartition, ColPartition_CLIST, ColPartition_C_IT > tesseract::GridBase

Public Member Functions

 ColPartitionGrid ()
 
 ColPartitionGrid (int gridsize, const ICOORD &bleft, const ICOORD &tright)
 
virtual ~ColPartitionGrid ()
 
void HandleClick (int x, int y)
 
void Merges (TessResultCallback2< bool, ColPartition *, TBOX * > *box_cb, TessResultCallback2< bool, const ColPartition *, const ColPartition * > *confirm_cb)
 
bool MergePart (TessResultCallback2< bool, ColPartition *, TBOX * > *box_cb, TessResultCallback2< bool, const ColPartition *, const ColPartition * > *confirm_cb, ColPartition *part)
 
void FindOverlappingPartitions (const TBOX &box, const ColPartition *not_this, ColPartition_CLIST *parts)
 
ColPartitionBestMergeCandidate (const ColPartition *part, ColPartition_CLIST *candidates, bool debug, TessResultCallback2< bool, const ColPartition *, const ColPartition * > *confirm_cb, int *overlap_increase)
 
void SplitOverlappingPartitions (ColPartition_LIST *big_parts)
 
bool GridSmoothNeighbours (BlobTextFlowType source_type, Pix *nontext_map, const TBOX &im_box, const FCOORD &rerotation)
 
void ComputePartitionColors (Pix *scaled_color, int scaled_factor, const FCOORD &rerotation)
 
void ReflectInYAxis ()
 
void Deskew (const FCOORD &deskew)
 
void SetTabStops (TabFind *tabgrid)
 
bool MakeColPartSets (PartSetVector *part_sets)
 
ColPartitionSetMakeSingleColumnSet (WidthCallback *cb)
 
void ClaimBoxes ()
 
void ReTypeBlobs (BLOBNBOX_LIST *im_blobs)
 
void RecomputeBounds (int gridsize, const ICOORD &bleft, const ICOORD &tright, const ICOORD &vertical)
 
void GridFindMargins (ColPartitionSet **best_columns)
 
void ListFindMargins (ColPartitionSet **best_columns, ColPartition_LIST *parts)
 
void DeleteParts ()
 
void DeleteUnknownParts (TO_BLOCK *block)
 
void FindFigureCaptions ()
 
void FindPartitionPartners ()
 
void FindPartitionPartners (bool upper, ColPartition *part)
 
void FindVPartitionPartners (bool to_the_left, ColPartition *part)
 
void RefinePartitionPartners (bool get_desperate)
 
- Public Member Functions inherited from tesseract::BBGrid< ColPartition, ColPartition_CLIST, ColPartition_C_IT >
 BBGrid ()
 
 BBGrid (int gridsize, const ICOORD &bleft, const ICOORD &tright)
 
virtual ~BBGrid ()
 
void Init (int gridsize, const ICOORD &bleft, const ICOORD &tright)
 
void Clear ()
 
void ClearGridData (void(*free_method)(ColPartition *))
 
void InsertBBox (bool h_spread, bool v_spread, ColPartition *bbox)
 
void InsertPixPtBBox (int left, int bottom, Pix *pix, ColPartition *bbox)
 
void RemoveBBox (ColPartition *bbox)
 
bool RectangleEmpty (const TBOX &rect)
 
IntGridCountCellElements ()
 
ScrollViewMakeWindow (int x, int y, const char *window_name)
 
void DisplayBoxes (ScrollView *window)
 
void AssertNoDuplicates ()
 
- Public Member Functions inherited from tesseract::GridBase
 GridBase ()
 
 GridBase (int gridsize, const ICOORD &bleft, const ICOORD &tright)
 
virtual ~GridBase ()
 
void Init (int gridsize, const ICOORD &bleft, const ICOORD &tright)
 
int gridsize () const
 
int gridwidth () const
 
int gridheight () const
 
const ICOORDbleft () const
 
const ICOORDtright () const
 
void GridCoords (int x, int y, int *grid_x, int *grid_y) const
 
void ClipGridCoords (int *x, int *y) const
 

Additional Inherited Members

- Protected Attributes inherited from tesseract::BBGrid< ColPartition, ColPartition_CLIST, ColPartition_C_IT >
ColPartition_CLIST * grid_
 
- Protected Attributes inherited from tesseract::GridBase
int gridsize_
 
int gridwidth_
 
int gridheight_
 
int gridbuckets_
 
ICOORD bleft_
 
ICOORD tright_
 

Detailed Description

Definition at line 33 of file colpartitiongrid.h.

Constructor & Destructor Documentation

tesseract::ColPartitionGrid::ColPartitionGrid ( )

Definition at line 71 of file colpartitiongrid.cpp.

71  {
72 }
tesseract::ColPartitionGrid::ColPartitionGrid ( int  gridsize,
const ICOORD bleft,
const ICOORD tright 
)

Definition at line 73 of file colpartitiongrid.cpp.

75  : BBGrid<ColPartition, ColPartition_CLIST, ColPartition_C_IT>(gridsize,
76  bleft, tright) {
77 }
int gridsize() const
Definition: bbgrid.h:68
const ICOORD & tright() const
Definition: bbgrid.h:80
const ICOORD & bleft() const
Definition: bbgrid.h:77
tesseract::ColPartitionGrid::~ColPartitionGrid ( )
virtual

Definition at line 79 of file colpartitiongrid.cpp.

79  {
80 }

Member Function Documentation

ColPartition * tesseract::ColPartitionGrid::BestMergeCandidate ( const ColPartition part,
ColPartition_CLIST *  candidates,
bool  debug,
TessResultCallback2< bool, const ColPartition *, const ColPartition * > *  confirm_cb,
int *  overlap_increase 
)

Definition at line 379 of file colpartitiongrid.cpp.

382  {
383  if (overlap_increase != NULL)
384  *overlap_increase = 0;
385  if (candidates->empty())
386  return NULL;
387  int ok_overlap =
388  static_cast<int>(kTinyEnoughTextlineOverlapFraction * gridsize() + 0.5);
389  // The best neighbour to merge with is the one that causes least
390  // total pairwise overlap among all the neighbours.
391  // If more than one offers the same total overlap, choose the one
392  // with the least total area.
393  const TBOX& part_box = part->bounding_box();
394  ColPartition_C_IT it(candidates);
395  ColPartition* best_candidate = NULL;
396  // Find the total combined box of all candidates and the original.
397  TBOX full_box(part_box);
398  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
399  ColPartition* candidate = it.data();
400  full_box += candidate->bounding_box();
401  }
402  // Keep valid neighbours in a list.
403  ColPartition_CLIST neighbours;
404  // Now run a rect search of the merged box for overlapping neighbours, as
405  // we need anything that might be overlapped by the merged box.
406  FindOverlappingPartitions(full_box, part, &neighbours);
407  if (debug) {
408  tprintf("Finding best merge candidate from %d, %d neighbours for box:",
409  candidates->length(), neighbours.length());
410  part_box.print();
411  }
412  // If the best increase in overlap is positive, then we also check the
413  // worst non-candidate overlap. This catches the case of multiple good
414  // candidates that overlap each other when merged. If the worst
415  // non-candidate overlap is better than the best overlap, then return
416  // the worst non-candidate overlap instead.
417  ColPartition_CLIST non_candidate_neighbours;
418  non_candidate_neighbours.set_subtract(SortByBoxLeft<ColPartition>, true,
419  &neighbours, candidates);
420  int worst_nc_increase = 0;
421  int best_increase = MAX_INT32;
422  int best_area = 0;
423  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
424  ColPartition* candidate = it.data();
425  if (confirm_cb != NULL && !confirm_cb->Run(part, candidate)) {
426  if (debug) {
427  tprintf("Candidate not confirmed:");
428  candidate->bounding_box().print();
429  }
430  continue;
431  }
432  int increase = IncreaseInOverlap(part, candidate, ok_overlap, &neighbours);
433  const TBOX& cand_box = candidate->bounding_box();
434  if (best_candidate == NULL || increase < best_increase) {
435  best_candidate = candidate;
436  best_increase = increase;
437  best_area = cand_box.bounding_union(part_box).area() - cand_box.area();
438  if (debug) {
439  tprintf("New best merge candidate has increase %d, area %d, over box:",
440  increase, best_area);
441  full_box.print();
442  candidate->Print();
443  }
444  } else if (increase == best_increase) {
445  int area = cand_box.bounding_union(part_box).area() - cand_box.area();
446  if (area < best_area) {
447  best_area = area;
448  best_candidate = candidate;
449  }
450  }
451  increase = IncreaseInOverlap(part, candidate, ok_overlap,
452  &non_candidate_neighbours);
453  if (increase > worst_nc_increase)
454  worst_nc_increase = increase;
455  }
456  if (best_increase > 0) {
457  // If the worst non-candidate increase is less than the best increase
458  // including the candidates, then all the candidates can merge together
459  // and the increase in outside overlap would be less, so use that result,
460  // but only if each candidate is either a good diacritic merge with part,
461  // or an ok merge candidate with all the others.
462  // See TestCompatibleCandidates for more explanation and a picture.
463  if (worst_nc_increase < best_increase &&
464  TestCompatibleCandidates(*part, debug, candidates)) {
465  best_increase = worst_nc_increase;
466  }
467  }
468  if (overlap_increase != NULL)
469  *overlap_increase = best_increase;
470  return best_candidate;
471 }
TBOX bounding_union(const TBOX &box) const
Definition: rect.cpp:130
inT32 area() const
Definition: rect.h:111
int gridsize() const
Definition: bbgrid.h:68
#define NULL
Definition: host.h:144
virtual R Run(A1, A2)=0
Definition: rect.h:29
#define MAX_INT32
Definition: host.h:120
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:41
void FindOverlappingPartitions(const TBOX &box, const ColPartition *not_this, ColPartition_CLIST *parts)
void print() const
Definition: rect.h:263
const double kTinyEnoughTextlineOverlapFraction
void tesseract::ColPartitionGrid::ClaimBoxes ( )

Definition at line 812 of file colpartitiongrid.cpp.

812  {
813  // Iterate the ColPartitions in the grid.
814  ColPartitionGridSearch gsearch(this);
815  gsearch.StartFullSearch();
816  ColPartition* part;
817  while ((part = gsearch.NextFullSearch()) != NULL) {
818  part->ClaimBoxes();
819  }
820 }
#define NULL
Definition: host.h:144
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
void tesseract::ColPartitionGrid::ComputePartitionColors ( Pix *  scaled_color,
int  scaled_factor,
const FCOORD rerotation 
)

Definition at line 620 of file colpartitiongrid.cpp.

622  {
623  if (scaled_color == NULL)
624  return;
625  Pix* color_map1 = NULL;
626  Pix* color_map2 = NULL;
627  Pix* rms_map = NULL;
629  int width = pixGetWidth(scaled_color);
630  int height = pixGetHeight(scaled_color);
631  color_map1 = pixCreate(width, height, 32);
632  color_map2 = pixCreate(width, height, 32);
633  rms_map = pixCreate(width, height, 8);
634  }
635  // Iterate the ColPartitions in the grid.
636  ColPartitionGridSearch gsearch(this);
637  gsearch.StartFullSearch();
638  ColPartition* part;
639  while ((part = gsearch.NextFullSearch()) != NULL) {
640  TBOX part_box = part->bounding_box();
641  part_box.rotate_large(rerotation);
642  ImageFind::ComputeRectangleColors(part_box, scaled_color,
643  scaled_factor,
644  color_map1, color_map2, rms_map,
645  part->color1(), part->color2());
646  }
647  if (color_map1 != NULL) {
648  pixWrite("swcolorinput.png", scaled_color, IFF_PNG);
649  pixWrite("swcolor1.png", color_map1, IFF_PNG);
650  pixWrite("swcolor2.png", color_map2, IFF_PNG);
651  pixWrite("swrms.png", rms_map, IFF_PNG);
652  pixDestroy(&color_map1);
653  pixDestroy(&color_map2);
654  pixDestroy(&rms_map);
655  }
656 }
static void ComputeRectangleColors(const TBOX &rect, Pix *pix, int factor, Pix *color_map1, Pix *color_map2, Pix *rms_map, uinT8 *color1, uinT8 *color2)
Definition: imagefind.cpp:391
#define NULL
Definition: host.h:144
void rotate_large(const FCOORD &vec)
Definition: rect.cpp:73
Definition: rect.h:29
bool textord_tabfind_show_color_fit
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
void tesseract::ColPartitionGrid::DeleteParts ( )

Definition at line 950 of file colpartitiongrid.cpp.

950  {
951  ColPartition_LIST dead_parts;
952  ColPartition_IT dead_it(&dead_parts);
953  ColPartitionGridSearch gsearch(this);
954  gsearch.StartFullSearch();
955  ColPartition* part;
956  while ((part = gsearch.NextFullSearch()) != NULL) {
957  part->DisownBoxes();
958  dead_it.add_to_end(part); // Parts will be deleted on return.
959  }
960  Clear();
961 }
#define NULL
Definition: host.h:144
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
void tesseract::ColPartitionGrid::DeleteUnknownParts ( TO_BLOCK block)

Definition at line 965 of file colpartitiongrid.cpp.

965  {
966  ColPartitionGridSearch gsearch(this);
967  gsearch.StartFullSearch();
968  ColPartition* part;
969  while ((part = gsearch.NextFullSearch()) != NULL) {
970  if (part->blob_type() == BRT_UNKNOWN) {
971  gsearch.RemoveBBox();
972  // Once marked, the blobs will be swept up by DeleteUnownedNoise.
973  part->set_flow(BTFT_NONTEXT);
974  part->set_blob_type(BRT_NOISE);
975  part->SetBlobTypes();
976  part->DisownBoxes();
977  delete part;
978  }
979  }
980  block->DeleteUnownedNoise();
981 }
#define NULL
Definition: host.h:144
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
void DeleteUnownedNoise()
Definition: blobbox.cpp:978
void tesseract::ColPartitionGrid::Deskew ( const FCOORD deskew)

Definition at line 684 of file colpartitiongrid.cpp.

684  {
685  ColPartition_LIST parts;
686  ColPartition_IT part_it(&parts);
687  // Iterate the ColPartitions in the grid to extract them.
688  ColPartitionGridSearch gsearch(this);
689  gsearch.StartFullSearch();
690  ColPartition* part;
691  while ((part = gsearch.NextFullSearch()) != NULL) {
692  part_it.add_after_then_move(part);
693  }
694  // Rebuild the grid to the new size.
695  TBOX grid_box(bleft_, tright_);
696  grid_box.rotate_large(deskew);
697  Init(gridsize(), grid_box.botleft(), grid_box.topright());
698  // Reinitializing the grid with rotated coords also clears all the
699  // pointers, so parts will now own the ColPartitions. (Briefly).
700  for (part_it.move_to_first(); !part_it.empty(); part_it.forward()) {
701  part = part_it.extract();
702  part->ComputeLimits();
703  InsertBBox(true, true, part);
704  }
705 }
int gridsize() const
Definition: bbgrid.h:68
#define NULL
Definition: host.h:144
Definition: rect.h:29
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
ICOORD tright_
Definition: bbgrid.h:96
void InsertBBox(bool h_spread, bool v_spread, ColPartition *bbox)
void Init(int gridsize, const ICOORD &bleft, const ICOORD &tright)
void tesseract::ColPartitionGrid::FindFigureCaptions ( )

Definition at line 984 of file colpartitiongrid.cpp.

984  {
985  // For each image region find its best candidate text caption region,
986  // if any and mark it as such.
987  ColPartitionGridSearch gsearch(this);
988  gsearch.StartFullSearch();
989  ColPartition* part;
990  while ((part = gsearch.NextFullSearch()) != NULL) {
991  if (part->IsImageType()) {
992  const TBOX& part_box = part->bounding_box();
993  bool debug = AlignedBlob::WithinTestRegion(2, part_box.left(),
994  part_box.bottom());
995  ColPartition* best_caption = NULL;
996  int best_dist = 0; // Distance to best_caption.
997  int best_upper = 0; // Direction of best_caption.
998  // Handle both lower and upper directions.
999  for (int upper = 0; upper < 2; ++upper) {
1000  ColPartition_C_IT partner_it(upper ? part->upper_partners()
1001  : part->lower_partners());
1002  // If there are no image partners, then this direction is ok.
1003  for (partner_it.mark_cycle_pt(); !partner_it.cycled_list();
1004  partner_it.forward()) {
1005  ColPartition* partner = partner_it.data();
1006  if (partner->IsImageType()) {
1007  break;
1008  }
1009  }
1010  if (!partner_it.cycled_list()) continue;
1011  // Find the nearest totally overlapping text partner.
1012  for (partner_it.mark_cycle_pt(); !partner_it.cycled_list();
1013  partner_it.forward()) {
1014  ColPartition* partner = partner_it.data();
1015  if (!partner->IsTextType()) continue;
1016  const TBOX& partner_box = partner->bounding_box();
1017  if (debug) {
1018  tprintf("Finding figure captions for image part:");
1019  part_box.print();
1020  tprintf("Considering partner:");
1021  partner_box.print();
1022  }
1023  if (partner_box.left() >= part_box.left() &&
1024  partner_box.right() <= part_box.right()) {
1025  int dist = partner_box.y_gap(part_box);
1026  if (best_caption == NULL || dist < best_dist) {
1027  best_dist = dist;
1028  best_caption = partner;
1029  best_upper = upper;
1030  }
1031  }
1032  }
1033  }
1034  if (best_caption != NULL) {
1035  if (debug) {
1036  tprintf("Best caption candidate:");
1037  best_caption->bounding_box().print();
1038  }
1039  // We have a candidate caption. Qualify it as being separable from
1040  // any body text. We are looking for either a small number of lines
1041  // or a big gap that indicates a separation from the body text.
1042  int line_count = 0;
1043  int biggest_gap = 0;
1044  int smallest_gap = MAX_INT16;
1045  int total_height = 0;
1046  int mean_height = 0;
1047  ColPartition* end_partner = NULL;
1048  ColPartition* next_partner = NULL;
1049  for (ColPartition* partner = best_caption; partner != NULL &&
1050  line_count <= kMaxCaptionLines;
1051  partner = next_partner) {
1052  if (!partner->IsTextType()) {
1053  end_partner = partner;
1054  break;
1055  }
1056  ++line_count;
1057  total_height += partner->bounding_box().height();
1058  next_partner = partner->SingletonPartner(best_upper);
1059  if (next_partner != NULL) {
1060  int gap = partner->bounding_box().y_gap(
1061  next_partner->bounding_box());
1062  if (gap > biggest_gap) {
1063  biggest_gap = gap;
1064  end_partner = next_partner;
1065  mean_height = total_height / line_count;
1066  } else if (gap < smallest_gap) {
1067  smallest_gap = gap;
1068  }
1069  // If the gap looks big compared to the text size and the smallest
1070  // gap seen so far, then we can stop.
1071  if (biggest_gap > mean_height * kMinCaptionGapHeightRatio &&
1072  biggest_gap > smallest_gap * kMinCaptionGapRatio)
1073  break;
1074  }
1075  }
1076  if (debug) {
1077  tprintf("Line count=%d, biggest gap %d, smallest%d, mean height %d\n",
1078  line_count, biggest_gap, smallest_gap, mean_height);
1079  if (end_partner != NULL) {
1080  tprintf("End partner:");
1081  end_partner->bounding_box().print();
1082  }
1083  }
1084  if (next_partner == NULL && line_count <= kMaxCaptionLines)
1085  end_partner = NULL; // No gap, but line count is small.
1086  if (line_count <= kMaxCaptionLines) {
1087  // This is a qualified caption. Mark the text as caption.
1088  for (ColPartition* partner = best_caption; partner != NULL &&
1089  partner != end_partner;
1090  partner = next_partner) {
1091  partner->set_type(PT_CAPTION_TEXT);
1092  partner->SetBlobTypes();
1093  if (debug) {
1094  tprintf("Set caption type for partition:");
1095  partner->bounding_box().print();
1096  }
1097  next_partner = partner->SingletonPartner(best_upper);
1098  }
1099  }
1100  }
1101  }
1102  }
1103 }
const int kMaxCaptionLines
#define NULL
Definition: host.h:144
inT16 left() const
Definition: rect.h:67
Definition: rect.h:29
const double kMinCaptionGapRatio
inT16 right() const
Definition: rect.h:74
const double kMinCaptionGapHeightRatio
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
int y_gap(const TBOX &box) const
Definition: rect.h:218
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:41
#define MAX_INT16
Definition: host.h:119
static bool WithinTestRegion(int detail_level, int x, int y)
void print() const
Definition: rect.h:263
inT16 bottom() const
Definition: rect.h:60
void tesseract::ColPartitionGrid::FindOverlappingPartitions ( const TBOX box,
const ColPartition not_this,
ColPartition_CLIST *  parts 
)

Definition at line 326 of file colpartitiongrid.cpp.

328  {
329  ColPartitionGridSearch rsearch(this);
330  rsearch.StartRectSearch(box);
331  ColPartition* part;
332  while ((part = rsearch.NextRectSearch()) != NULL) {
333  if (part != not_this)
334  parts->add_sorted(SortByBoxLeft<ColPartition>, true, part);
335  }
336 }
#define NULL
Definition: host.h:144
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
void tesseract::ColPartitionGrid::FindPartitionPartners ( )

Definition at line 1109 of file colpartitiongrid.cpp.

1109  {
1110  ColPartitionGridSearch gsearch(this);
1111  gsearch.StartFullSearch();
1112  ColPartition* part;
1113  while ((part = gsearch.NextFullSearch()) != NULL) {
1114  if (part->IsVerticalType()) {
1115  FindVPartitionPartners(true, part);
1116  FindVPartitionPartners(false, part);
1117  } else {
1118  FindPartitionPartners(true, part);
1119  FindPartitionPartners(false, part);
1120  }
1121  }
1122 }
void FindVPartitionPartners(bool to_the_left, ColPartition *part)
#define NULL
Definition: host.h:144
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
void tesseract::ColPartitionGrid::FindPartitionPartners ( bool  upper,
ColPartition part 
)

Definition at line 1126 of file colpartitiongrid.cpp.

1126  {
1127  if (part->type() == PT_NOISE)
1128  return; // Noise is not allowed to partner anything.
1129  const TBOX& box = part->bounding_box();
1130  int top = part->median_top();
1131  int bottom = part->median_bottom();
1132  int height = top - bottom;
1133  int mid_y = (bottom + top) / 2;
1134  ColPartitionGridSearch vsearch(this);
1135  // Search down for neighbour below
1136  vsearch.StartVerticalSearch(box.left(), box.right(), part->MidY());
1137  ColPartition* neighbour;
1138  ColPartition* best_neighbour = NULL;
1139  int best_dist = MAX_INT32;
1140  while ((neighbour = vsearch.NextVerticalSearch(!upper)) != NULL) {
1141  if (neighbour == part || neighbour->type() == PT_NOISE)
1142  continue; // Noise is not allowed to partner anything.
1143  int neighbour_bottom = neighbour->median_bottom();
1144  int neighbour_top = neighbour->median_top();
1145  int neighbour_y = (neighbour_bottom + neighbour_top) / 2;
1146  if (upper != (neighbour_y > mid_y))
1147  continue;
1148  if (!part->HOverlaps(*neighbour) && !part->WithinSameMargins(*neighbour))
1149  continue;
1150  if (!part->TypesMatch(*neighbour)) {
1151  if (best_neighbour == NULL)
1152  best_neighbour = neighbour;
1153  continue;
1154  }
1155  int dist = upper ? neighbour_bottom - top : bottom - neighbour_top;
1156  if (dist <= kMaxPartitionSpacing * height) {
1157  if (dist < best_dist) {
1158  best_dist = dist;
1159  best_neighbour = neighbour;
1160  }
1161  } else {
1162  break;
1163  }
1164  }
1165  if (best_neighbour != NULL)
1166  part->AddPartner(upper, best_neighbour);
1167 }
const double kMaxPartitionSpacing
#define NULL
Definition: host.h:144
inT16 left() const
Definition: rect.h:67
Definition: rect.h:29
inT16 right() const
Definition: rect.h:74
#define MAX_INT32
Definition: host.h:120
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
Definition: capi.h:64
void tesseract::ColPartitionGrid::FindVPartitionPartners ( bool  to_the_left,
ColPartition part 
)

Definition at line 1171 of file colpartitiongrid.cpp.

1172  {
1173  if (part->type() == PT_NOISE)
1174  return; // Noise is not allowed to partner anything.
1175  const TBOX& box = part->bounding_box();
1176  int left = part->median_left();
1177  int right = part->median_right();
1178  int width = right - left;
1179  int mid_x = (left + right) / 2;
1180  ColPartitionGridSearch hsearch(this);
1181  // Search left for neighbour to_the_left
1182  hsearch.StartSideSearch(mid_x, box.bottom(), box.top());
1183  ColPartition* neighbour;
1184  ColPartition* best_neighbour = NULL;
1185  int best_dist = MAX_INT32;
1186  while ((neighbour = hsearch.NextSideSearch(to_the_left)) != NULL) {
1187  if (neighbour == part || neighbour->type() == PT_NOISE)
1188  continue; // Noise is not allowed to partner anything.
1189  int neighbour_left = neighbour->median_left();
1190  int neighbour_right = neighbour->median_right();
1191  int neighbour_x = (neighbour_left + neighbour_right) / 2;
1192  if (to_the_left != (neighbour_x < mid_x))
1193  continue;
1194  if (!part->VOverlaps(*neighbour))
1195  continue;
1196  if (!part->TypesMatch(*neighbour))
1197  continue; // Only match to other vertical text.
1198  int dist = to_the_left ? left - neighbour_right : neighbour_left - right;
1199  if (dist <= kMaxPartitionSpacing * width) {
1200  if (dist < best_dist || best_neighbour == NULL) {
1201  best_dist = dist;
1202  best_neighbour = neighbour;
1203  }
1204  } else {
1205  break;
1206  }
1207  }
1208  // For vertical partitions, the upper partner is to the left, and lower is
1209  // to the right.
1210  if (best_neighbour != NULL)
1211  part->AddPartner(to_the_left, best_neighbour);
1212 }
const double kMaxPartitionSpacing
#define NULL
Definition: host.h:144
Definition: rect.h:29
#define MAX_INT32
Definition: host.h:120
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
inT16 top() const
Definition: rect.h:53
Definition: capi.h:64
inT16 bottom() const
Definition: rect.h:60
void tesseract::ColPartitionGrid::GridFindMargins ( ColPartitionSet **  best_columns)

Definition at line 908 of file colpartitiongrid.cpp.

908  {
909  // Iterate the ColPartitions in the grid.
910  ColPartitionGridSearch gsearch(this);
911  gsearch.StartFullSearch();
912  ColPartition* part;
913  while ((part = gsearch.NextFullSearch()) != NULL) {
914  // Set up a rectangle search x-bounded by the column and y by the part.
915  ColPartitionSet* columns = best_columns != NULL
916  ? best_columns[gsearch.GridY()]
917  : NULL;
918  FindPartitionMargins(columns, part);
919  const TBOX& box = part->bounding_box();
920  if (AlignedBlob::WithinTestRegion(2, box.left(), box.bottom())) {
921  tprintf("Computed margins for part:");
922  part->Print();
923  }
924  }
925 }
#define NULL
Definition: host.h:144
inT16 left() const
Definition: rect.h:67
Definition: rect.h:29
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:41
static bool WithinTestRegion(int detail_level, int x, int y)
inT16 bottom() const
Definition: rect.h:60
bool tesseract::ColPartitionGrid::GridSmoothNeighbours ( BlobTextFlowType  source_type,
Pix *  nontext_map,
const TBOX im_box,
const FCOORD rerotation 
)

Definition at line 598 of file colpartitiongrid.cpp.

601  {
602  // Iterate the ColPartitions in the grid.
603  ColPartitionGridSearch gsearch(this);
604  gsearch.StartFullSearch();
605  ColPartition* part;
606  bool any_changed = false;
607  while ((part = gsearch.NextFullSearch()) != NULL) {
608  if (part->flow() != source_type || BLOBNBOX::IsLineType(part->blob_type()))
609  continue;
610  const TBOX& box = part->bounding_box();
611  bool debug = AlignedBlob::WithinTestRegion(2, box.left(), box.bottom());
612  if (SmoothRegionType(nontext_map, im_box, rotation, debug, part))
613  any_changed = true;
614  }
615  return any_changed;
616 }
static bool IsLineType(BlobRegionType type)
Definition: blobbox.h:399
#define NULL
Definition: host.h:144
inT16 left() const
Definition: rect.h:67
Definition: rect.h:29
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
static bool WithinTestRegion(int detail_level, int x, int y)
inT16 bottom() const
Definition: rect.h:60
void tesseract::ColPartitionGrid::HandleClick ( int  x,
int  y 
)
virtual

Reimplemented from tesseract::BBGrid< ColPartition, ColPartition_CLIST, ColPartition_C_IT >.

Definition at line 83 of file colpartitiongrid.cpp.

83  {
84  BBGrid<ColPartition,
85  ColPartition_CLIST, ColPartition_C_IT>::HandleClick(x, y);
86  // Run a radial search for partitions that overlap.
87  ColPartitionGridSearch radsearch(this);
88  radsearch.SetUniqueMode(true);
89  radsearch.StartRadSearch(x, y, 1);
90  ColPartition* neighbour;
91  FCOORD click(x, y);
92  while ((neighbour = radsearch.NextRadSearch()) != NULL) {
93  TBOX nbox = neighbour->bounding_box();
94  if (nbox.contains(click)) {
95  tprintf("Block box:");
96  neighbour->bounding_box().print();
97  neighbour->Print();
98  }
99  }
100 }
bool contains(const FCOORD pt) const
Definition: rect.h:323
#define NULL
Definition: host.h:144
Definition: rect.h:29
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:41
void HandleClick(int x, int y)
Definition: points.h:189
void tesseract::ColPartitionGrid::ListFindMargins ( ColPartitionSet **  best_columns,
ColPartition_LIST *  parts 
)

Definition at line 932 of file colpartitiongrid.cpp.

933  {
934  ColPartition_IT part_it(parts);
935  for (part_it.mark_cycle_pt(); !part_it.cycled_list(); part_it.forward()) {
936  ColPartition* part = part_it.data();
937  ColPartitionSet* columns = NULL;
938  if (best_columns != NULL) {
939  TBOX part_box = part->bounding_box();
940  // Get the columns from the y grid coord.
941  int grid_x, grid_y;
942  GridCoords(part_box.left(), part_box.bottom(), &grid_x, &grid_y);
943  columns = best_columns[grid_y];
944  }
945  FindPartitionMargins(columns, part);
946  }
947 }
void GridCoords(int x, int y, int *grid_x, int *grid_y) const
Definition: bbgrid.cpp:54
#define NULL
Definition: host.h:144
inT16 left() const
Definition: rect.h:67
Definition: rect.h:29
inT16 bottom() const
Definition: rect.h:60
bool tesseract::ColPartitionGrid::MakeColPartSets ( PartSetVector part_sets)

Definition at line 732 of file colpartitiongrid.cpp.

732  {
733  ColPartition_LIST* part_lists = new ColPartition_LIST[gridheight()];
734  part_sets->reserve(gridheight());
735  // Iterate the ColPartitions in the grid to get parts onto lists for the
736  // y bottom of each.
737  ColPartitionGridSearch gsearch(this);
738  gsearch.StartFullSearch();
739  ColPartition* part;
740  bool any_parts_found = false;
741  while ((part = gsearch.NextFullSearch()) != NULL) {
742  BlobRegionType blob_type = part->blob_type();
743  if (blob_type != BRT_NOISE &&
744  (blob_type != BRT_UNKNOWN || !part->boxes()->singleton())) {
745  int grid_x, grid_y;
746  const TBOX& part_box = part->bounding_box();
747  GridCoords(part_box.left(), part_box.bottom(), &grid_x, &grid_y);
748  ColPartition_IT part_it(&part_lists[grid_y]);
749  part_it.add_to_end(part);
750  any_parts_found = true;
751  }
752  }
753  if (any_parts_found) {
754  for (int grid_y = 0; grid_y < gridheight(); ++grid_y) {
755  ColPartitionSet* line_set = NULL;
756  if (!part_lists[grid_y].empty()) {
757  line_set = new ColPartitionSet(&part_lists[grid_y]);
758  }
759  part_sets->push_back(line_set);
760  }
761  }
762  delete [] part_lists;
763  return any_parts_found;
764 }
int gridheight() const
Definition: bbgrid.h:74
BlobRegionType
Definition: blobbox.h:57
void GridCoords(int x, int y, int *grid_x, int *grid_y) const
Definition: bbgrid.cpp:54
#define NULL
Definition: host.h:144
inT16 left() const
Definition: rect.h:67
Definition: rect.h:29
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
inT16 bottom() const
Definition: rect.h:60
ColPartitionSet * tesseract::ColPartitionGrid::MakeSingleColumnSet ( WidthCallback cb)

Definition at line 770 of file colpartitiongrid.cpp.

770  {
771  ColPartition* single_column_part = NULL;
772  // Iterate the ColPartitions in the grid to get parts onto lists for the
773  // y bottom of each.
774  ColPartitionGridSearch gsearch(this);
775  gsearch.StartFullSearch();
776  ColPartition* part;
777  while ((part = gsearch.NextFullSearch()) != NULL) {
778  BlobRegionType blob_type = part->blob_type();
779  if (blob_type != BRT_NOISE &&
780  (blob_type != BRT_UNKNOWN || !part->boxes()->singleton())) {
781  // Consider for single column.
782  BlobTextFlowType flow = part->flow();
783  if ((blob_type == BRT_TEXT &&
784  (flow == BTFT_STRONG_CHAIN || flow == BTFT_CHAIN ||
785  flow == BTFT_LEADER || flow == BTFT_TEXT_ON_IMAGE)) ||
786  blob_type == BRT_RECTIMAGE || blob_type == BRT_POLYIMAGE) {
787  if (single_column_part == NULL) {
788  single_column_part = part->ShallowCopy();
789  single_column_part->set_blob_type(BRT_TEXT);
790  // Copy the tabs from itself to properly setup the margins.
791  single_column_part->CopyLeftTab(*single_column_part, false);
792  single_column_part->CopyRightTab(*single_column_part, false);
793  } else {
794  if (part->left_key() < single_column_part->left_key())
795  single_column_part->CopyLeftTab(*part, false);
796  if (part->right_key() > single_column_part->right_key())
797  single_column_part->CopyRightTab(*part, false);
798  }
799  }
800  }
801  }
802  if (single_column_part != NULL) {
803  // Make a ColPartitionSet out of the single_column_part as a candidate
804  // for the single column case.
805  single_column_part->SetColumnGoodness(cb);
806  return new ColPartitionSet(single_column_part);
807  }
808  return NULL;
809 }
BlobRegionType
Definition: blobbox.h:57
#define NULL
Definition: host.h:144
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
BlobTextFlowType
Definition: blobbox.h:99
bool tesseract::ColPartitionGrid::MergePart ( TessResultCallback2< bool, ColPartition *, TBOX * > *  box_cb,
TessResultCallback2< bool, const ColPartition *, const ColPartition * > *  confirm_cb,
ColPartition part 
)

Definition at line 130 of file colpartitiongrid.cpp.

134  {
135  if (part->IsUnMergeableType())
136  return false;
137  bool any_done = false;
138  // Repeatedly merge part while we find a best merge candidate that works.
139  bool merge_done = false;
140  do {
141  merge_done = false;
142  TBOX box = part->bounding_box();
143  bool debug = AlignedBlob::WithinTestRegion(2, box.left(), box.bottom());
144  if (debug) {
145  tprintf("Merge candidate:");
146  box.print();
147  }
148  // Set up a rectangle search bounded by the part.
149  if (!box_cb->Run(part, &box))
150  continue;
151  // Create a list of merge candidates.
152  ColPartition_CLIST merge_candidates;
153  FindMergeCandidates(part, box, debug, &merge_candidates);
154  // Find the best merge candidate based on minimal overlap increase.
155  int overlap_increase;
156  ColPartition* neighbour = BestMergeCandidate(part, &merge_candidates, debug,
157  confirm_cb,
158  &overlap_increase);
159  if (neighbour != NULL && overlap_increase <= 0) {
160  if (debug) {
161  tprintf("Merging:hoverlap=%d, voverlap=%d, OLI=%d\n",
162  part->HCoreOverlap(*neighbour), part->VCoreOverlap(*neighbour),
163  overlap_increase);
164  }
165  // Looks like a good candidate so merge it.
166  RemoveBBox(neighbour);
167  // We will modify the box of part, so remove it from the grid, merge
168  // it and then re-insert it into the grid.
169  RemoveBBox(part);
170  part->Absorb(neighbour, NULL);
171  InsertBBox(true, true, part);
172  merge_done = true;
173  any_done = true;
174  } else if (neighbour != NULL) {
175  if (debug) {
176  tprintf("Overlapped when merged with increase %d: ", overlap_increase);
177  neighbour->bounding_box().print();
178  }
179  } else if (debug) {
180  tprintf("No candidate neighbour returned\n");
181  }
182  } while (merge_done);
183  return any_done;
184 }
#define NULL
Definition: host.h:144
inT16 left() const
Definition: rect.h:67
virtual R Run(A1, A2)=0
Definition: rect.h:29
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:41
void InsertBBox(bool h_spread, bool v_spread, ColPartition *bbox)
ColPartition * BestMergeCandidate(const ColPartition *part, ColPartition_CLIST *candidates, bool debug, TessResultCallback2< bool, const ColPartition *, const ColPartition * > *confirm_cb, int *overlap_increase)
static bool WithinTestRegion(int detail_level, int x, int y)
void print() const
Definition: rect.h:263
inT16 bottom() const
Definition: rect.h:60
void tesseract::ColPartitionGrid::Merges ( TessResultCallback2< bool, ColPartition *, TBOX * > *  box_cb,
TessResultCallback2< bool, const ColPartition *, const ColPartition * > *  confirm_cb 
)

Definition at line 109 of file colpartitiongrid.cpp.

112  {
113  // Iterate the ColPartitions in the grid.
114  ColPartitionGridSearch gsearch(this);
115  gsearch.StartFullSearch();
116  ColPartition* part;
117  while ((part = gsearch.NextFullSearch()) != NULL) {
118  if (MergePart(box_cb, confirm_cb, part))
119  gsearch.RepositionIterator();
120  }
121  delete box_cb;
122  delete confirm_cb;
123 }
#define NULL
Definition: host.h:144
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
bool MergePart(TessResultCallback2< bool, ColPartition *, TBOX * > *box_cb, TessResultCallback2< bool, const ColPartition *, const ColPartition * > *confirm_cb, ColPartition *part)
void tesseract::ColPartitionGrid::RecomputeBounds ( int  gridsize,
const ICOORD bleft,
const ICOORD tright,
const ICOORD vertical 
)

Definition at line 879 of file colpartitiongrid.cpp.

882  {
883  ColPartition_LIST saved_parts;
884  ColPartition_IT part_it(&saved_parts);
885  // Iterate the ColPartitions in the grid to get parts onto a list.
886  ColPartitionGridSearch gsearch(this);
887  gsearch.StartFullSearch();
888  ColPartition* part;
889  while ((part = gsearch.NextFullSearch()) != NULL) {
890  part_it.add_to_end(part);
891  }
892  // Reinitialize grid to the new size.
893  Init(gridsize, bleft, tright);
894  // Recompute the bounds of the parts and put them back in the new grid.
895  for (part_it.move_to_first(); !part_it.empty(); part_it.forward()) {
896  part = part_it.extract();
897  part->set_vertical(vertical);
898  part->ComputeLimits();
899  InsertBBox(true, true, part);
900  }
901 }
int gridsize() const
Definition: bbgrid.h:68
#define NULL
Definition: host.h:144
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
void InsertBBox(bool h_spread, bool v_spread, ColPartition *bbox)
void Init(int gridsize, const ICOORD &bleft, const ICOORD &tright)
void tesseract::ColPartitionGrid::RefinePartitionPartners ( bool  get_desperate)

Definition at line 1217 of file colpartitiongrid.cpp.

1217  {
1218  ColPartitionGridSearch gsearch(this);
1219  // Refine in type order so that chasing multiple partners can be done
1220  // before eliminating type mis-matching partners.
1221  for (int type = PT_UNKNOWN + 1; type <= PT_COUNT; type++) {
1222  // Iterate the ColPartitions in the grid.
1223  gsearch.StartFullSearch();
1224  ColPartition* part;
1225  while ((part = gsearch.NextFullSearch()) != NULL) {
1226  part->RefinePartners(static_cast<PolyBlockType>(type),
1227  get_desperate, this);
1228  // Iterator may have been messed up by a merge.
1229  gsearch.RepositionIterator();
1230  }
1231  }
1232 }
#define NULL
Definition: host.h:144
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
Definition: capi.h:64
void tesseract::ColPartitionGrid::ReflectInYAxis ( )

Definition at line 660 of file colpartitiongrid.cpp.

660  {
661  ColPartition_LIST parts;
662  ColPartition_IT part_it(&parts);
663  // Iterate the ColPartitions in the grid to extract them.
664  ColPartitionGridSearch gsearch(this);
665  gsearch.StartFullSearch();
666  ColPartition* part;
667  while ((part = gsearch.NextFullSearch()) != NULL) {
668  part_it.add_after_then_move(part);
669  }
670  ICOORD bot_left(-tright().x(), bleft().y());
671  ICOORD top_right(-bleft().x(), tright().y());
672  // Reinitializing the grid with reflected coords also clears all the
673  // pointers, so parts will now own the ColPartitions. (Briefly).
674  Init(gridsize(), bot_left, top_right);
675  for (part_it.move_to_first(); !part_it.empty(); part_it.forward()) {
676  part = part_it.extract();
677  part->ReflectInYAxis();
678  InsertBBox(true, true, part);
679  }
680 }
int gridsize() const
Definition: bbgrid.h:68
#define NULL
Definition: host.h:144
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
const ICOORD & tright() const
Definition: bbgrid.h:80
void InsertBBox(bool h_spread, bool v_spread, ColPartition *bbox)
integer coordinate
Definition: points.h:30
const ICOORD & bleft() const
Definition: bbgrid.h:77
void Init(int gridsize, const ICOORD &bleft, const ICOORD &tright)
void tesseract::ColPartitionGrid::ReTypeBlobs ( BLOBNBOX_LIST *  im_blobs)

Definition at line 825 of file colpartitiongrid.cpp.

825  {
826  BLOBNBOX_IT im_blob_it(im_blobs);
827  ColPartition_LIST dead_parts;
828  ColPartition_IT dead_part_it(&dead_parts);
829  // Iterate the ColPartitions in the grid.
830  ColPartitionGridSearch gsearch(this);
831  gsearch.StartFullSearch();
832  ColPartition* part;
833  while ((part = gsearch.NextFullSearch()) != NULL) {
834  BlobRegionType blob_type = part->blob_type();
835  BlobTextFlowType flow = part->flow();
836  if (blob_type == BRT_POLYIMAGE || blob_type == BRT_RECTIMAGE) {
837  BLOBNBOX_C_IT blob_it(part->boxes());
838  for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
839  BLOBNBOX* blob = blob_it.data();
840  im_blob_it.add_after_then_move(blob);
841  }
842  } else if (blob_type != BRT_NOISE) {
843  // Make sure the blobs are marked with the correct type and flow.
844  BLOBNBOX_C_IT blob_it(part->boxes());
845  for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
846  BLOBNBOX* blob = blob_it.data();
847  if (blob->region_type() == BRT_NOISE) {
848  // TODO(rays) Deprecated. Change this section to an assert to verify
849  // and then delete.
850  ASSERT_HOST(blob->cblob()->area() != 0);
851  blob->set_owner(NULL);
852  blob_it.extract();
853  } else {
854  blob->set_region_type(blob_type);
855  if (blob->flow() != BTFT_LEADER)
856  blob->set_flow(flow);
857  }
858  }
859  }
860  if (blob_type == BRT_NOISE || part->boxes()->empty()) {
861  BLOBNBOX_C_IT blob_it(part->boxes());
862  part->DisownBoxes();
863  dead_part_it.add_to_end(part);
864  gsearch.RemoveBBox();
865  for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
866  BLOBNBOX* blob = blob_it.data();
867  if (blob->cblob()->area() == 0) {
868  // Any blob with zero area is a fake image blob and should be deleted.
869  delete blob->cblob();
870  delete blob;
871  }
872  }
873  }
874  }
875 }
void set_owner(tesseract::ColPartition *new_owner)
Definition: blobbox.h:332
BlobRegionType
Definition: blobbox.h:57
C_BLOB * cblob() const
Definition: blobbox.h:245
BlobRegionType region_type() const
Definition: blobbox.h:260
#define NULL
Definition: host.h:144
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
void set_flow(BlobTextFlowType value)
Definition: blobbox.h:275
inT32 area()
Definition: stepblob.cpp:211
BlobTextFlowType
Definition: blobbox.h:99
BlobTextFlowType flow() const
Definition: blobbox.h:272
#define ASSERT_HOST(x)
Definition: errcode.h:84
void set_region_type(BlobRegionType new_type)
Definition: blobbox.h:263
void tesseract::ColPartitionGrid::SetTabStops ( TabFind tabgrid)

Definition at line 708 of file colpartitiongrid.cpp.

708  {
709  // Iterate the ColPartitions in the grid.
710  ColPartitionGridSearch gsearch(this);
711  gsearch.StartFullSearch();
712  ColPartition* part;
713  while ((part = gsearch.NextFullSearch()) != NULL) {
714  const TBOX& part_box = part->bounding_box();
715  TabVector* left_line = tabgrid->LeftTabForBox(part_box, true, false);
716  // If the overlapping line is not a left tab, try for non-overlapping.
717  if (left_line != NULL && !left_line->IsLeftTab())
718  left_line = tabgrid->LeftTabForBox(part_box, false, false);
719  if (left_line != NULL && left_line->IsLeftTab())
720  part->SetLeftTab(left_line);
721  TabVector* right_line = tabgrid->RightTabForBox(part_box, true, false);
722  if (right_line != NULL && !right_line->IsRightTab())
723  right_line = tabgrid->RightTabForBox(part_box, false, false);
724  if (right_line != NULL && right_line->IsRightTab())
725  part->SetRightTab(right_line);
726  part->SetColumnGoodness(tabgrid->WidthCB());
727  }
728 }
#define NULL
Definition: host.h:144
Definition: rect.h:29
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
void tesseract::ColPartitionGrid::SplitOverlappingPartitions ( ColPartition_LIST *  big_parts)

Definition at line 488 of file colpartitiongrid.cpp.

489  {
490  int ok_overlap =
491  static_cast<int>(kTinyEnoughTextlineOverlapFraction * gridsize() + 0.5);
492  // Iterate the ColPartitions in the grid.
493  ColPartitionGridSearch gsearch(this);
494  gsearch.StartFullSearch();
495  ColPartition* part;
496  while ((part = gsearch.NextFullSearch()) != NULL) {
497  // Set up a rectangle search bounded by the part.
498  const TBOX& box = part->bounding_box();
499  ColPartitionGridSearch rsearch(this);
500  rsearch.SetUniqueMode(true);
501  rsearch.StartRectSearch(box);
502  int unresolved_overlaps = 0;
503 
504  ColPartition* neighbour;
505  while ((neighbour = rsearch.NextRectSearch()) != NULL) {
506  if (neighbour == part)
507  continue;
508  const TBOX& neighbour_box = neighbour->bounding_box();
509  if (neighbour->OKMergeOverlap(*part, *part, ok_overlap, false) &&
510  part->OKMergeOverlap(*neighbour, *neighbour, ok_overlap, false))
511  continue; // The overlap is OK both ways.
512 
513  // If removal of the biggest box from either partition eliminates the
514  // overlap, and it is much bigger than the box left behind, then
515  // it is either a drop-cap, an inter-line join, or some junk that
516  // we don't want anyway, so put it in the big_parts list.
517  if (!part->IsSingleton()) {
518  BLOBNBOX* excluded = part->BiggestBox();
519  TBOX shrunken = part->BoundsWithoutBox(excluded);
520  if (!shrunken.overlap(neighbour_box) &&
521  excluded->bounding_box().height() >
522  kBigPartSizeRatio * shrunken.height()) {
523  // Removing the biggest box fixes the overlap, so do it!
524  gsearch.RemoveBBox();
525  RemoveBadBox(excluded, part, big_parts);
526  InsertBBox(true, true, part);
527  gsearch.RepositionIterator();
528  break;
529  }
530  } else if (box.contains(neighbour_box)) {
531  ++unresolved_overlaps;
532  continue; // No amount of splitting will fix it.
533  }
534  if (!neighbour->IsSingleton()) {
535  BLOBNBOX* excluded = neighbour->BiggestBox();
536  TBOX shrunken = neighbour->BoundsWithoutBox(excluded);
537  if (!shrunken.overlap(box) &&
538  excluded->bounding_box().height() >
539  kBigPartSizeRatio * shrunken.height()) {
540  // Removing the biggest box fixes the overlap, so do it!
541  rsearch.RemoveBBox();
542  RemoveBadBox(excluded, neighbour, big_parts);
543  InsertBBox(true, true, neighbour);
544  gsearch.RepositionIterator();
545  break;
546  }
547  }
548  int part_overlap_count = part->CountOverlappingBoxes(neighbour_box);
549  int neighbour_overlap_count = neighbour->CountOverlappingBoxes(box);
550  ColPartition* right_part = NULL;
551  if (neighbour_overlap_count <= part_overlap_count ||
552  part->IsSingleton()) {
553  // Try to split the neighbour to reduce overlap.
554  BLOBNBOX* split_blob = neighbour->OverlapSplitBlob(box);
555  if (split_blob != NULL) {
556  rsearch.RemoveBBox();
557  right_part = neighbour->SplitAtBlob(split_blob);
558  InsertBBox(true, true, neighbour);
559  ASSERT_HOST(right_part != NULL);
560  }
561  } else {
562  // Try to split part to reduce overlap.
563  BLOBNBOX* split_blob = part->OverlapSplitBlob(neighbour_box);
564  if (split_blob != NULL) {
565  gsearch.RemoveBBox();
566  right_part = part->SplitAtBlob(split_blob);
567  InsertBBox(true, true, part);
568  ASSERT_HOST(right_part != NULL);
569  }
570  }
571  if (right_part != NULL) {
572  InsertBBox(true, true, right_part);
573  gsearch.RepositionIterator();
574  rsearch.RepositionIterator();
575  break;
576  }
577  }
578  if (unresolved_overlaps > 2 && part->IsSingleton()) {
579  // This part is no good so just add to big_parts.
580  RemoveBBox(part);
581  ColPartition_IT big_it(big_parts);
582  part->set_block_owned(true);
583  big_it.add_to_end(part);
584  gsearch.RepositionIterator();
585  }
586  }
587 }
const double kBigPartSizeRatio
const TBOX & bounding_box() const
Definition: blobbox.h:208
bool contains(const FCOORD pt) const
Definition: rect.h:323
int gridsize() const
Definition: bbgrid.h:68
#define NULL
Definition: host.h:144
bool overlap(const TBOX &box) const
Definition: rect.h:345
Definition: rect.h:29
GridSearch< ColPartition, ColPartition_CLIST, ColPartition_C_IT > ColPartitionGridSearch
Definition: colpartition.h:895
void InsertBBox(bool h_spread, bool v_spread, ColPartition *bbox)
#define ASSERT_HOST(x)
Definition: errcode.h:84
inT16 height() const
Definition: rect.h:97
const double kTinyEnoughTextlineOverlapFraction

The documentation for this class was generated from the following files: