Tesseract 3.01
|
00001 00002 // File: colpartition.h 00003 // Description: Class to hold partitions of the page that correspond 00004 // roughly to text lines. 00005 // Author: Ray Smith 00006 // Created: Thu Aug 14 10:50:01 PDT 2008 00007 // 00008 // (C) Copyright 2008, Google Inc. 00009 // Licensed under the Apache License, Version 2.0 (the "License"); 00010 // you may not use this file except in compliance with the License. 00011 // You may obtain a copy of the License at 00012 // http://www.apache.org/licenses/LICENSE-2.0 00013 // Unless required by applicable law or agreed to in writing, software 00014 // distributed under the License is distributed on an "AS IS" BASIS, 00015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 // See the License for the specific language governing permissions and 00017 // limitations under the License. 00018 // 00020 00021 #ifndef TESSERACT_TEXTORD_COLPARTITION_H__ 00022 #define TESSERACT_TEXTORD_COLPARTITION_H__ 00023 00024 #include "bbgrid.h" 00025 #include "blobbox.h" // For BlobRegionType. 00026 #include "ndminx.h" 00027 #include "ocrblock.h" 00028 #include "rect.h" // For TBOX. 00029 #include "scrollview.h" 00030 #include "tabfind.h" // For WidthCallback. 00031 #include "tabvector.h" // For BLOBNBOX_CLIST. 00032 00033 namespace tesseract { 00034 00035 // Number of colors in the color1, color2 arrays. 00036 const int kRGBRMSColors = 4; 00037 00038 class ColPartition; 00039 class ColPartitionSet; 00040 class ColPartitionGrid; 00041 class WorkingPartSet; 00042 class WorkingPartSet_LIST; 00043 00044 // An enum to indicate how a partition sits on the columns. 00045 // The order of flowing/heading/pullout must be kept consistent with 00046 // PolyBlockType. 00047 enum ColumnSpanningType { 00048 CST_NOISE, // Strictly between columns. 00049 CST_FLOWING, // Strictly within a single column. 00050 CST_HEADING, // Spans multiple columns. 00051 CST_PULLOUT, // Touches multiple columns, but doesn't span them. 00052 CST_COUNT // Number of entries. 00053 }; 00054 00055 ELIST2IZEH(ColPartition) 00056 CLISTIZEH(ColPartition) 00057 00067 class ColPartition : public ELIST2_LINK { 00068 public: 00069 ColPartition() { 00070 // This empty constructor is here only so that the class can be ELISTIZED. 00071 // TODO(rays) change deep_copy in elst.h line 955 to take a callback copier 00072 // and eliminate CLASSNAME##_copier. 00073 } 00078 ColPartition(BlobRegionType blob_type, const ICOORD& vertical); 00083 static ColPartition* MakeLinePartition(BlobRegionType blob_type, 00084 const ICOORD& vertical, 00085 int left, int bottom, 00086 int right, int top); 00087 00088 // Constructs and returns a fake ColPartition with a single fake BLOBNBOX, 00089 // all made from a single TBOX. 00090 // WARNING: Despite being on C_LISTs, the BLOBNBOX owns the C_BLOB and 00091 // the ColPartition owns the BLOBNBOX!!! 00092 // Call DeleteBoxes before deleting the ColPartition. 00093 static ColPartition* FakePartition(const TBOX& box); 00094 00095 ~ColPartition(); 00096 00097 // Simple accessors. 00098 const TBOX& bounding_box() const { 00099 return bounding_box_; 00100 } 00101 int left_margin() const { 00102 return left_margin_; 00103 } 00104 void set_left_margin(int margin) { 00105 left_margin_ = margin; 00106 } 00107 int right_margin() const { 00108 return right_margin_; 00109 } 00110 void set_right_margin(int margin) { 00111 right_margin_ = margin; 00112 } 00113 int median_top() const { 00114 return median_top_; 00115 } 00116 int median_bottom() const { 00117 return median_bottom_; 00118 } 00119 int median_size() const { 00120 return median_size_; 00121 } 00122 void set_median_size(int size) { 00123 median_size_ = size; 00124 } 00125 int median_width() const { 00126 return median_width_; 00127 } 00128 void set_median_width(int width) { 00129 median_width_ = width; 00130 } 00131 BlobRegionType blob_type() const { 00132 return blob_type_; 00133 } 00134 void set_blob_type(BlobRegionType t) { 00135 blob_type_ = t; 00136 } 00137 BlobTextFlowType flow() const { 00138 return flow_; 00139 } 00140 void set_flow(BlobTextFlowType f) { 00141 flow_ = f; 00142 } 00143 int good_blob_score() const { 00144 return good_blob_score_; 00145 } 00146 bool good_width() const { 00147 return good_width_; 00148 } 00149 bool good_column() const { 00150 return good_column_; 00151 } 00152 bool left_key_tab() const { 00153 return left_key_tab_; 00154 } 00155 int left_key() const { 00156 return left_key_; 00157 } 00158 bool right_key_tab() const { 00159 return right_key_tab_; 00160 } 00161 int right_key() const { 00162 return right_key_; 00163 } 00164 PolyBlockType type() const { 00165 return type_; 00166 } 00167 void set_type(PolyBlockType t) { 00168 type_ = t; 00169 } 00170 BLOBNBOX_CLIST* boxes() { 00171 return &boxes_; 00172 } 00173 int boxes_count() const { 00174 return boxes_.length(); 00175 } 00176 void set_vertical(const ICOORD& v) { 00177 vertical_ = v; 00178 } 00179 ColPartition_CLIST* upper_partners() { 00180 return &upper_partners_; 00181 } 00182 ColPartition_CLIST* lower_partners() { 00183 return &lower_partners_; 00184 } 00185 void set_working_set(WorkingPartSet* working_set) { 00186 working_set_ = working_set; 00187 } 00188 bool desperately_merged() const { 00189 return desperately_merged_; 00190 } 00191 ColPartitionSet* column_set() const { 00192 return column_set_; 00193 } 00194 void set_side_step(int step) { 00195 side_step_ = step; 00196 } 00197 int bottom_spacing() const { 00198 return bottom_spacing_; 00199 } 00200 void set_bottom_spacing(int spacing) { 00201 bottom_spacing_ = spacing; 00202 } 00203 int top_spacing() const { 00204 return top_spacing_; 00205 } 00206 void set_top_spacing(int spacing) { 00207 top_spacing_ = spacing; 00208 } 00209 00210 void set_table_type() { 00211 if (type_ != PT_TABLE) { 00212 type_before_table_ = type_; 00213 type_ = PT_TABLE; 00214 } 00215 } 00216 void clear_table_type() { 00217 if (type_ == PT_TABLE) 00218 type_ = type_before_table_; 00219 } 00220 bool inside_table_column() { 00221 return inside_table_column_; 00222 } 00223 void set_inside_table_column(bool val) { 00224 inside_table_column_ = val; 00225 } 00226 ColPartition* nearest_neighbor_above() const { 00227 return nearest_neighbor_above_; 00228 } 00229 void set_nearest_neighbor_above(ColPartition* part) { 00230 nearest_neighbor_above_ = part; 00231 } 00232 ColPartition* nearest_neighbor_below() const { 00233 return nearest_neighbor_below_; 00234 } 00235 void set_nearest_neighbor_below(ColPartition* part) { 00236 nearest_neighbor_below_ = part; 00237 } 00238 int space_above() const { 00239 return space_above_; 00240 } 00241 void set_space_above(int space) { 00242 space_above_ = space; 00243 } 00244 int space_below() const { 00245 return space_below_; 00246 } 00247 void set_space_below(int space) { 00248 space_below_ = space; 00249 } 00250 int space_to_left() const { 00251 return space_to_left_; 00252 } 00253 void set_space_to_left(int space) { 00254 space_to_left_ = space; 00255 } 00256 int space_to_right() const { 00257 return space_to_right_; 00258 } 00259 void set_space_to_right(int space) { 00260 space_to_right_ = space; 00261 } 00262 uinT8* color1() { 00263 return color1_; 00264 } 00265 uinT8* color2() { 00266 return color2_; 00267 } 00268 bool owns_blobs() const { 00269 return owns_blobs_; 00270 } 00271 void set_owns_blobs(bool owns_blobs) { 00272 // Do NOT change ownership flag when there are blobs in the list. 00273 // Immediately set the ownership flag when creating copies. 00274 ASSERT_HOST(boxes_.empty()); 00275 owns_blobs_ = owns_blobs; 00276 } 00277 00278 // Inline quasi-accessors that require some computation. 00279 00280 // Returns the middle y-coord of the bounding box. 00281 int MidY() const { 00282 return (bounding_box_.top() + bounding_box_.bottom()) / 2; 00283 } 00284 // Returns the middle y-coord of the median top and bottom. 00285 int MedianY() const { 00286 return (median_top_ + median_bottom_) / 2; 00287 } 00288 // Returns the middle x-coord of the bounding box. 00289 int MidX() const { 00290 return (bounding_box_.left() + bounding_box_.right()) / 2; 00291 } 00292 // Returns the sort key at any given x,y. 00293 int SortKey(int x, int y) const { 00294 return TabVector::SortKey(vertical_, x, y); 00295 } 00296 // Returns the x corresponding to the sortkey, y pair. 00297 int XAtY(int sort_key, int y) const { 00298 return TabVector::XAtY(vertical_, sort_key, y); 00299 } 00300 // Returns the x difference between the two sort keys. 00301 int KeyWidth(int left_key, int right_key) const { 00302 return (right_key - left_key) / vertical_.y(); 00303 } 00304 // Returns the column width between the left and right keys. 00305 int ColumnWidth() const { 00306 return KeyWidth(left_key_, right_key_); 00307 } 00308 // Returns the sort key of the box left edge. 00309 int BoxLeftKey() const { 00310 return SortKey(bounding_box_.left(), MidY()); 00311 } 00312 // Returns the sort key of the box right edge. 00313 int BoxRightKey() const { 00314 return SortKey(bounding_box_.right(), MidY()); 00315 } 00316 // Returns the left edge at the given y, using the sort key. 00317 int LeftAtY(int y) const { 00318 return XAtY(left_key_, y); 00319 } 00320 // Returns the right edge at the given y, using the sort key. 00321 int RightAtY(int y) const { 00322 return XAtY(right_key_, y); 00323 } 00324 // Returns true if the right edge of this is to the left of the right 00325 // edge of other. 00326 bool IsLeftOf(const ColPartition& other) const { 00327 return bounding_box_.right() < other.bounding_box_.right(); 00328 } 00329 // Returns true if the partition contains the given x coordinate at the y. 00330 bool ColumnContains(int x, int y) const { 00331 return LeftAtY(y) - 1 <= x && x <= RightAtY(y) + 1; 00332 } 00333 // Returns true if there are no blobs in the list. 00334 bool IsEmpty() const { 00335 return boxes_.empty(); 00336 } 00337 // Returns true if there is a single blob in the list. 00338 bool IsSingleton() const { 00339 return boxes_.singleton(); 00340 } 00341 // Returns true if this and other overlap horizontally by bounding box. 00342 bool HOverlaps(const ColPartition& other) const { 00343 return bounding_box_.x_overlap(other.bounding_box_); 00344 } 00345 // Returns true if this and other can be combined without putting a 00346 // horizontal step in either left or right edge. 00347 bool HCompatible(const ColPartition& other) const { 00348 return left_margin_ <= other.bounding_box_.left() && 00349 bounding_box_.left() >= other.left_margin_ && 00350 bounding_box_.right() <= other.right_margin_ && 00351 right_margin_ >= other.bounding_box_.right(); 00352 } 00353 // Returns the vertical overlap (by median) of this and other. 00354 // WARNING! Only makes sense on horizontal partitions! 00355 int VOverlap(const ColPartition& other) const { 00356 return MIN(median_top_, other.median_top_) - 00357 MAX(median_bottom_, other.median_bottom_); 00358 } 00359 // Returns the horizontal overlap (by median) of this and other. 00360 // WARNING! Only makes sense on vertical partitions! 00361 int HOverlap(const ColPartition& other) const { 00362 return MIN(median_right_, other.median_right_) - 00363 MAX(median_left_, other.median_left_); 00364 } 00365 // Returns true if this and other overlap significantly vertically. 00366 bool VOverlaps(const ColPartition& other) const { 00367 int overlap = VOverlap(other); 00368 int height = MIN(median_top_ - median_bottom_, 00369 other.median_top_ - other.median_bottom_); 00370 return overlap * 3 > height; 00371 } 00372 // Returns true if the region types (aligned_text_) match. 00373 // Lines never match anything, as they should never be merged or chained. 00374 bool TypesMatch(const ColPartition& other) const { 00375 return TypesMatch(blob_type_, other.blob_type_); 00376 } 00377 static bool TypesMatch(BlobRegionType type1, BlobRegionType type2) { 00378 return (type1 == type2 || type1 == BRT_UNKNOWN || type2 == BRT_UNKNOWN) && 00379 !BLOBNBOX::IsLineType(type1) && !BLOBNBOX::IsLineType(type2); 00380 } 00381 00382 // Returns true if partitions is of horizontal line type 00383 bool IsLineType() const { 00384 return PTIsLineType(type_); 00385 } 00386 // Returns true if partitions is of image type 00387 bool IsImageType() const { 00388 return PTIsImageType(type_); 00389 } 00390 // Returns true if partitions is of text type 00391 bool IsTextType() const { 00392 return PTIsTextType(type_); 00393 } 00394 // Returns true if the partition is of an exclusively vertical type. 00395 bool IsVerticalType() const { 00396 return blob_type_ == BRT_VERT_TEXT || blob_type_ == BRT_VLINE; 00397 } 00398 // Returns true if the partition is of a definite horizontal type. 00399 bool IsHorizontalType() const { 00400 return blob_type_ == BRT_TEXT || blob_type_ == BRT_HLINE; 00401 } 00402 // Returns true is the partition is of a type that cannot be merged. 00403 bool IsUnMergeableType() const { 00404 return BLOBNBOX::UnMergeableType(blob_type_) || type_ == PT_NOISE; 00405 } 00406 // Returns true if this partition is a vertical line 00407 // TODO(nbeato): Use PartitionType enum when Ray's code is submitted. 00408 bool IsVerticalLine() const { 00409 return IsVerticalType() && IsLineType(); 00410 } 00411 // Returns true if this partition is a horizontal line 00412 // TODO(nbeato): Use PartitionType enum when Ray's code is submitted. 00413 bool IsHorizontalLine() const { 00414 return IsHorizontalType() && IsLineType(); 00415 } 00416 00417 // Adds the given box to the partition, updating the partition bounds. 00418 // The list of boxes in the partition is updated, ensuring that no box is 00419 // recorded twice, and the boxes are kept in increasing left position. 00420 void AddBox(BLOBNBOX* box); 00421 00422 // Removes the given box from the partition, updating the bounds. 00423 void RemoveBox(BLOBNBOX* box); 00424 00425 // Returns the tallest box in the partition, as measured perpendicular to the 00426 // presumed flow of text. 00427 BLOBNBOX* BiggestBox(); 00428 00429 // Returns the bounding box excluding the given box. 00430 TBOX BoundsWithoutBox(BLOBNBOX* box); 00431 00432 // Claims the boxes in the boxes_list by marking them with a this owner 00433 // pointer. If a box is already owned, then run Unique on it. 00434 void ClaimBoxes(WidthCallback* cb); 00435 00436 // NULL the owner of the blobs in this partition, so they can be deleted 00437 // independently of the ColPartition. 00438 void DisownBoxes(); 00439 00440 // Delete the boxes that this partition owns. 00441 void DeleteBoxes(); 00442 00443 // Returns true if this is a legal partition - meaning that the conditions 00444 // left_margin <= bounding_box left 00445 // left_key <= bounding box left key 00446 // bounding box left <= bounding box right 00447 // and likewise for right margin and key 00448 // are all met. 00449 bool IsLegal(); 00450 00451 // Returns true if the left and right edges are approximately equal. 00452 bool MatchingColumns(const ColPartition& other) const; 00453 00454 // Returns true if the sizes match for two text partitions, 00455 // taking orientation into account 00456 bool MatchingSizes(const ColPartition& other) const; 00457 00458 // Returns true if there is no tabstop violation in merging this and other. 00459 bool ConfirmNoTabViolation(const ColPartition& other) const; 00460 00461 // Returns true if other has a similar stroke width to this. 00462 bool MatchingStrokeWidth(const ColPartition& other, 00463 double fractional_tolerance, 00464 double constant_tolerance) const; 00465 // Returns true if candidate is an acceptable diacritic base char merge 00466 // with this as the diacritic. 00467 bool OKDiacriticMerge(const ColPartition& candidate, bool debug) const; 00468 00469 // Sets the sort key using either the tab vector, or the bounding box if 00470 // the tab vector is NULL. If the tab_vector lies inside the bounding_box, 00471 // use the edge of the box as a key any way. 00472 void SetLeftTab(const TabVector* tab_vector); 00473 void SetRightTab(const TabVector* tab_vector); 00474 00475 // Copies the left/right tab from the src partition, but if take_box is 00476 // true, copies the box instead and uses that as a key. 00477 void CopyLeftTab(const ColPartition& src, bool take_box); 00478 void CopyRightTab(const ColPartition& src, bool take_box); 00479 00480 // Returns the left rule line x coord of the leftmost blob. 00481 int LeftBlobRule() const; 00482 // Returns the right rule line x coord of the rightmost blob. 00483 int RightBlobRule() const; 00484 00485 // Add a partner above if upper, otherwise below. 00486 // Add them uniquely and keep the list sorted by box left. 00487 // Partnerships are added symmetrically to partner and this. 00488 void AddPartner(bool upper, ColPartition* partner); 00489 // Removes the partner from this, but does not remove this from partner. 00490 // This asymmetric removal is so as not to mess up the iterator that is 00491 // working on partner's partner list. 00492 void RemovePartner(bool upper, ColPartition* partner); 00493 // Returns the partner if the given partner is a singleton, otherwise NULL. 00494 ColPartition* SingletonPartner(bool upper); 00495 00496 // Merge with the other partition and delete it. 00497 void Absorb(ColPartition* other, WidthCallback* cb); 00498 00499 // Shares out any common boxes amongst the partitions, ensuring that no 00500 // box stays in both. Returns true if anything was done. 00501 bool Unique(ColPartition* other, WidthCallback* cb); 00502 // Returns true if the overlap between this and the merged pair of 00503 // merge candidates is sufficiently trivial to be allowed. 00504 // The merged box can graze the edge of this by the ok_box_overlap 00505 // if that exceeds the margin to the median top and bottom. 00506 bool OKMergeOverlap(const ColPartition& merge1, const ColPartition& merge2, 00507 int ok_box_overlap, bool debug); 00508 00509 // Find the blob at which to split this to minimize the overlap with the 00510 // given box. Returns the first blob to go in the second partition. 00511 BLOBNBOX* OverlapSplitBlob(const TBOX& box); 00512 00513 // Split this partition keeping the first half in this and returning 00514 // the second half. 00515 // Splits by putting the split_blob and the blobs that follow 00516 // in the second half, and the rest in the first half. 00517 ColPartition* SplitAtBlob(BLOBNBOX* split_blob); 00518 00519 // Splits this partition at the given x coordinate, returning the right 00520 // half and keeping the left half in this. 00521 ColPartition* SplitAt(int split_x); 00522 00523 // Recalculates all the coordinate limits of the partition. 00524 void ComputeLimits(); 00525 00526 // Returns the number of boxes that overlap the given box. 00527 int CountOverlappingBoxes(const TBOX& box); 00528 00529 // Computes and sets the type_, first_column_, last_column_ and column_set_. 00530 // resolution refers to the ppi resolution of the image. 00531 void SetPartitionType(int resolution, ColPartitionSet* columns); 00532 00533 // Returns the PartitionType from the current BlobRegionType and a column 00534 // flow spanning type ColumnSpanningType, generated by 00535 // ColPartitionSet::SpanningType, that indicates how the partition sits 00536 // in the columns. 00537 PolyBlockType PartitionType(ColumnSpanningType flow) const; 00538 00539 // Returns the first and last column touched by this partition. 00540 // resolution refers to the ppi resolution of the image. 00541 void ColumnRange(int resolution, ColPartitionSet* columns, 00542 int* first_col, int* last_col); 00543 00544 // Sets the internal flags good_width_ and good_column_. 00545 void SetColumnGoodness(WidthCallback* cb); 00546 00547 // Determines whether the blobs in this partition mostly represent 00548 // a leader (fixed pitch sequence) and sets the member blobs accordingly. 00549 // Note that height is assumed to have been tested elsewhere, and that this 00550 // function will find most fixed-pitch text as leader without a height filter. 00551 // Leader detection is limited to sequences of identical width objects, 00552 // such as .... or ----, so patterns, such as .-.-.-.-. will not be found. 00553 bool MarkAsLeaderIfMonospaced(); 00554 00555 // Sets all blobs with the partition blob type and flow. 00556 void SetBlobTypes(); 00557 00558 // Adds this ColPartition to a matching WorkingPartSet if one can be found, 00559 // otherwise starts a new one in the appropriate column, ending the previous. 00560 void AddToWorkingSet(const ICOORD& bleft, const ICOORD& tright, 00561 int resolution, ColPartition_LIST* used_parts, 00562 WorkingPartSet_LIST* working_set); 00563 00564 // From the given block_parts list, builds one or more BLOCKs and 00565 // corresponding TO_BLOCKs, such that the line spacing is uniform in each. 00566 // Created blocks are appended to the end of completed_blocks and to_blocks. 00567 // The used partitions are put onto used_parts, as they may still be referred 00568 // to in the partition grid. bleft, tright and resolution are the bounds 00569 // and resolution of the original image. 00570 static void LineSpacingBlocks(const ICOORD& bleft, const ICOORD& tright, 00571 int resolution, 00572 ColPartition_LIST* block_parts, 00573 ColPartition_LIST* used_parts, 00574 BLOCK_LIST* completed_blocks, 00575 TO_BLOCK_LIST* to_blocks); 00576 // Constructs a block from the given list of partitions. 00577 // Arguments are as LineSpacingBlocks above. 00578 static TO_BLOCK* MakeBlock(const ICOORD& bleft, const ICOORD& tright, 00579 ColPartition_LIST* block_parts, 00580 ColPartition_LIST* used_parts); 00581 00582 00583 // Returns a copy of everything except the list of boxes. The resulting 00584 // ColPartition is only suitable for keeping in a column candidate list. 00585 ColPartition* ShallowCopy() const; 00586 // Returns a copy of everything with a shallow copy of the blobs. 00587 // The blobs are still owned by their original parent, so they are 00588 // treated as read-only. 00589 ColPartition* CopyButDontOwnBlobs(); 00590 00591 // Provides a color for BBGrid to draw the rectangle. 00592 ScrollView::Color BoxColor() const; 00593 00594 // Prints debug information on this. 00595 void Print() const; 00596 // Prints debug information on the colors. 00597 void PrintColors(); 00598 00599 // Sets the types of all partitions in the run to be the max of the types. 00600 void SmoothPartnerRun(int working_set_count); 00601 00602 // Cleans up the partners of the given type so that there is at most 00603 // one partner. This makes block creation simpler. 00604 // If get_desperate is true, goes to more desperate merge methods 00605 // to merge flowing text before breaking partnerships. 00606 void RefinePartners(PolyBlockType type, bool get_desparate, 00607 ColPartitionGrid* grid); 00608 00609 // Returns true if this column partition is in the same column as 00610 // part. This function will only work after the SetPartitionType function 00611 // has been called on both column partitions. This is useful for 00612 // doing a SideSearch when you want things in the same page column. 00613 bool IsInSameColumnAs(const ColPartition& part) const; 00614 00615 // Sets the column bounds. Primarily used in testing. 00616 void set_first_column(int column) { 00617 first_column_ = column; 00618 } 00619 void set_last_column(int column) { 00620 last_column_ = column; 00621 } 00622 00623 private: 00624 // enum to refer to the entries in a neigbourhood of lines. 00625 // Used by SmoothSpacings to test for blips with OKSpacingBlip. 00626 enum SpacingNeighbourhood { 00627 PN_ABOVE2, 00628 PN_ABOVE1, 00629 PN_UPPER, 00630 PN_LOWER, 00631 PN_BELOW1, 00632 PN_BELOW2, 00633 PN_COUNT 00634 }; 00635 00636 // Cleans up the partners above if upper is true, else below. 00637 // If get_desperate is true, goes to more desperate merge methods 00638 // to merge flowing text before breaking partnerships. 00639 void RefinePartnersInternal(bool upper, bool get_desperate, 00640 ColPartitionGrid* grid); 00641 // Restricts the partners to only desirable types. For text and BRT_HLINE this 00642 // means the same type_ , and for image types it means any image type. 00643 void RefinePartnersByType(bool upper, ColPartition_CLIST* partners); 00644 // Remove transitive partnerships: this<->a, and a<->b and this<->b. 00645 // Gets rid of this<->b, leaving a clean chain. 00646 // Also if we have this<->a and a<->this, then gets rid of this<->a, as 00647 // this has multiple partners. 00648 void RefinePartnerShortcuts(bool upper, ColPartition_CLIST* partners); 00649 // If multiple text partners can be merged, then do so. 00650 // If desperate is true, then an increase in overlap with the merge is 00651 // allowed. If the overlap increases, then the desperately_merged_ flag 00652 // is set, indicating that the textlines probably need to be regenerated 00653 // by aggressive line fitting/splitting, as there are probably vertically 00654 // joined blobs that cross textlines. 00655 void RefineTextPartnersByMerge(bool upper, bool desperate, 00656 ColPartition_CLIST* partners, 00657 ColPartitionGrid* grid); 00658 // Keep the partner with the biggest overlap. 00659 void RefinePartnersByOverlap(bool upper, ColPartition_CLIST* partners); 00660 00661 // Return true if bbox belongs better in this than other. 00662 bool ThisPartitionBetter(BLOBNBOX* bbox, const ColPartition& other); 00663 00664 // Smoothes the spacings in the list into groups of equal linespacing. 00665 // resolution is the resolution of the original image, used as a basis 00666 // for thresholds in change of spacing. page_height is in pixels. 00667 static void SmoothSpacings(int resolution, int page_height, 00668 ColPartition_LIST* parts); 00669 00670 // Returns true if the parts array of pointers to partitions matches the 00671 // condition for a spacing blip. See SmoothSpacings for what this means 00672 // and how it is used. 00673 static bool OKSpacingBlip(int resolution, int median_spacing, 00674 ColPartition** parts); 00675 00676 // Returns true if both the top and bottom spacings of this match the given 00677 // spacing to within suitable margins dictated by the image resolution. 00678 bool SpacingEqual(int spacing, int resolution) const; 00679 00680 // Returns true if both the top and bottom spacings of this and other 00681 // match to within suitable margins dictated by the image resolution. 00682 bool SpacingsEqual(const ColPartition& other, int resolution) const; 00683 00684 // Returns true if the sum spacing of this and other match the given 00685 // spacing (or twice the given spacing) to within a suitable margin dictated 00686 // by the image resolution. 00687 bool SummedSpacingOK(const ColPartition& other, 00688 int spacing, int resolution) const; 00689 00690 // Returns a suitable spacing margin that can be applied to bottoms of 00691 // text lines, based on the resolution and the stored side_step_. 00692 int BottomSpacingMargin(int resolution) const; 00693 00694 // Returns a suitable spacing margin that can be applied to tops of 00695 // text lines, based on the resolution and the stored side_step_. 00696 int TopSpacingMargin(int resolution) const; 00697 00698 // Returns true if the median text sizes of this and other agree to within 00699 // a reasonable multiplicative factor. 00700 bool SizesSimilar(const ColPartition& other) const; 00701 00702 // Computes and returns in start, end a line segment formed from a 00703 // forwards-iterated group of left edges of partitions that satisfy the 00704 // condition that the rightmost left margin is to the left of the 00705 // leftmost left bounding box edge. 00706 // TODO(rays) Not good enough. Needs improving to tightly wrap text in both 00707 // directions, and to loosely wrap images. 00708 static void LeftEdgeRun(ColPartition_IT* part_it, 00709 ICOORD* start, ICOORD* end); 00710 // Computes and returns in start, end a line segment formed from a 00711 // backwards-iterated group of right edges of partitions that satisfy the 00712 // condition that the leftmost right margin is to the right of the 00713 // rightmost right bounding box edge. 00714 // TODO(rays) Not good enough. Needs improving to tightly wrap text in both 00715 // directions, and to loosely wrap images. 00716 static void RightEdgeRun(ColPartition_IT* part_it, 00717 ICOORD* start, ICOORD* end); 00718 00719 // The margins are determined by the position of the nearest vertically 00720 // overlapping neighbour to the side. They indicate the maximum extent 00721 // that the block/column may be extended without touching something else. 00722 // Leftmost coordinate that the region may occupy over the y limits. 00723 int left_margin_; 00724 // Rightmost coordinate that the region may occupy over the y limits. 00725 int right_margin_; 00726 // Bounding box of all blobs in the partition. 00727 TBOX bounding_box_; 00728 // Median top and bottom of blobs in this partition. 00729 int median_bottom_; 00730 int median_top_; 00731 // Median height of blobs in this partition. 00732 // TODO(rays) rename median_height_. 00733 int median_size_; 00734 // Median left and right of blobs in this partition. 00735 int median_left_; 00736 int median_right_; 00737 // Median width of blobs in this partition. 00738 int median_width_; 00739 // blob_region_type_ for the blobs in this partition. 00740 BlobRegionType blob_type_; 00741 BlobTextFlowType flow_; // Quality of text flow. 00742 // Total of GoodTextBlob results for all blobs in the partition. 00743 int good_blob_score_; 00744 // True if this partition has a common width. 00745 bool good_width_; 00746 // True if this is a good column candidate. 00747 bool good_column_; 00748 // True if the left_key_ is from a tab vector. 00749 bool left_key_tab_; 00750 // True if the right_key_ is from a tab vector. 00751 bool right_key_tab_; 00752 // Left and right sort keys for the edges of the partition. 00753 // If the respective *_key_tab_ is true then this key came from a tab vector. 00754 // If not, then the class promises to keep the key equal to the sort key 00755 // for the respective edge of the bounding box at the MidY, so that 00756 // LeftAtY and RightAtY always returns an x coordinate on the line parallel 00757 // to vertical_ through the bounding box edge at MidY. 00758 int left_key_; 00759 int right_key_; 00760 // Type of this partition after looking at its relation to the columns. 00761 PolyBlockType type_; 00762 // All boxes in the partition stored in increasing left edge coordinate. 00763 BLOBNBOX_CLIST boxes_; 00764 // The global vertical skew direction. 00765 ICOORD vertical_; 00766 // The partitions above that matched this. 00767 ColPartition_CLIST upper_partners_; 00768 // The partitions below that matched this. 00769 ColPartition_CLIST lower_partners_; 00770 // The WorkingPartSet it lives in while blocks are being made. 00771 WorkingPartSet* working_set_; 00772 // True when the partition's ownership has been taken from the grid and 00773 // placed in a working set, or, after that, in the good_parts_ list. 00774 bool block_owned_; 00775 // Flag to indicate that this partition was subjected to a desperate merge, 00776 // and therefore the textlines need rebuilding. 00777 bool desperately_merged_; 00778 // The first and last column that this partition applies to. 00779 // Flowing partitions (see type_) will have an equal first and last value 00780 // of the form 2n + 1, where n is the zero-based index into the partitions 00781 // in column_set_. (See ColPartitionSet::GetColumnByIndex). 00782 // Heading partitions will have unequal values of the same form. 00783 // Pullout partitions will have equal values, but may have even values, 00784 // indicating placement between columns. 00785 int first_column_; 00786 int last_column_; 00787 // Column_set_ is the column layout applicable to this ColPartition. 00788 ColPartitionSet* column_set_; 00789 // Linespacing data. 00790 int side_step_; // Median y-shift to next blob on same line. 00791 int top_spacing_; // Line spacing from median_top_. 00792 int bottom_spacing_; // Line spacing from median_bottom_. 00793 00794 // Type of this partition before considering it as a table cell. This is 00795 // used to revert the type if a partition is first marked as a table cell but 00796 // later filtering steps decide it does not belong to a table 00797 PolyBlockType type_before_table_; 00798 bool inside_table_column_; // Check whether the current partition has been 00799 // assigned to a table column 00800 // Nearest neighbor above with major x-overlap 00801 ColPartition* nearest_neighbor_above_; 00802 // Nearest neighbor below with major x-overlap 00803 ColPartition* nearest_neighbor_below_; 00804 int space_above_; // Distance from nearest_neighbor_above 00805 int space_below_; // Distance from nearest_neighbor_below 00806 int space_to_left_; // Distance from the left edge of the column 00807 int space_to_right_; // Distance from the right edge of the column 00808 // Color foreground/background data. 00809 uinT8 color1_[kRGBRMSColors]; 00810 uinT8 color2_[kRGBRMSColors]; 00811 bool owns_blobs_; // Does the partition own its blobs? 00812 }; 00813 00814 // Typedef it now in case it becomes a class later. 00815 typedef GridSearch<ColPartition, 00816 ColPartition_CLIST, 00817 ColPartition_C_IT> ColPartitionGridSearch; 00818 00819 } // namespace tesseract. 00820 00821 #endif // TESSERACT_TEXTORD_COLPARTITION_H__