|
tesseract 3.04.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 PolyBlockType block_type, 00095 BlobRegionType blob_type, 00096 BlobTextFlowType flow); 00097 00098 // Constructs and returns a ColPartition with the given real BLOBNBOX, 00099 // and sets it up to be a "big" partition (single-blob partition bigger 00100 // than the surrounding text that may be a dropcap, two or more vertically 00101 // touching characters, or some graphic element. 00102 // If the given list is not NULL, the partition is also added to the list. 00103 static ColPartition* MakeBigPartition(BLOBNBOX* box, 00104 ColPartition_LIST* big_part_list); 00105 00106 ~ColPartition(); 00107 00108 // Simple accessors. 00109 const TBOX& bounding_box() const { 00110 return bounding_box_; 00111 } 00112 int left_margin() const { 00113 return left_margin_; 00114 } 00115 void set_left_margin(int margin) { 00116 left_margin_ = margin; 00117 } 00118 int right_margin() const { 00119 return right_margin_; 00120 } 00121 void set_right_margin(int margin) { 00122 right_margin_ = margin; 00123 } 00124 int median_top() const { 00125 return median_top_; 00126 } 00127 int median_bottom() const { 00128 return median_bottom_; 00129 } 00130 int median_left() const { 00131 return median_left_; 00132 } 00133 int median_right() const { 00134 return median_right_; 00135 } 00136 int median_size() const { 00137 return median_size_; 00138 } 00139 void set_median_size(int size) { 00140 median_size_ = size; 00141 } 00142 int median_width() const { 00143 return median_width_; 00144 } 00145 void set_median_width(int width) { 00146 median_width_ = width; 00147 } 00148 BlobRegionType blob_type() const { 00149 return blob_type_; 00150 } 00151 void set_blob_type(BlobRegionType t) { 00152 blob_type_ = t; 00153 } 00154 BlobTextFlowType flow() const { 00155 return flow_; 00156 } 00157 void set_flow(BlobTextFlowType f) { 00158 flow_ = f; 00159 } 00160 int good_blob_score() const { 00161 return good_blob_score_; 00162 } 00163 bool good_width() const { 00164 return good_width_; 00165 } 00166 bool good_column() const { 00167 return good_column_; 00168 } 00169 bool left_key_tab() const { 00170 return left_key_tab_; 00171 } 00172 int left_key() const { 00173 return left_key_; 00174 } 00175 bool right_key_tab() const { 00176 return right_key_tab_; 00177 } 00178 int right_key() const { 00179 return right_key_; 00180 } 00181 PolyBlockType type() const { 00182 return type_; 00183 } 00184 void set_type(PolyBlockType t) { 00185 type_ = t; 00186 } 00187 BLOBNBOX_CLIST* boxes() { 00188 return &boxes_; 00189 } 00190 int boxes_count() const { 00191 return boxes_.length(); 00192 } 00193 void set_vertical(const ICOORD& v) { 00194 vertical_ = v; 00195 } 00196 ColPartition_CLIST* upper_partners() { 00197 return &upper_partners_; 00198 } 00199 ColPartition_CLIST* lower_partners() { 00200 return &lower_partners_; 00201 } 00202 void set_working_set(WorkingPartSet* working_set) { 00203 working_set_ = working_set; 00204 } 00205 bool block_owned() const { 00206 return block_owned_; 00207 } 00208 void set_block_owned(bool owned) { 00209 block_owned_ = owned; 00210 } 00211 bool desperately_merged() const { 00212 return desperately_merged_; 00213 } 00214 ColPartitionSet* column_set() const { 00215 return column_set_; 00216 } 00217 void set_side_step(int step) { 00218 side_step_ = step; 00219 } 00220 int bottom_spacing() const { 00221 return bottom_spacing_; 00222 } 00223 void set_bottom_spacing(int spacing) { 00224 bottom_spacing_ = spacing; 00225 } 00226 int top_spacing() const { 00227 return top_spacing_; 00228 } 00229 void set_top_spacing(int spacing) { 00230 top_spacing_ = spacing; 00231 } 00232 00233 void set_table_type() { 00234 if (type_ != PT_TABLE) { 00235 type_before_table_ = type_; 00236 type_ = PT_TABLE; 00237 } 00238 } 00239 void clear_table_type() { 00240 if (type_ == PT_TABLE) 00241 type_ = type_before_table_; 00242 } 00243 bool inside_table_column() { 00244 return inside_table_column_; 00245 } 00246 void set_inside_table_column(bool val) { 00247 inside_table_column_ = val; 00248 } 00249 ColPartition* nearest_neighbor_above() const { 00250 return nearest_neighbor_above_; 00251 } 00252 void set_nearest_neighbor_above(ColPartition* part) { 00253 nearest_neighbor_above_ = part; 00254 } 00255 ColPartition* nearest_neighbor_below() const { 00256 return nearest_neighbor_below_; 00257 } 00258 void set_nearest_neighbor_below(ColPartition* part) { 00259 nearest_neighbor_below_ = part; 00260 } 00261 int space_above() const { 00262 return space_above_; 00263 } 00264 void set_space_above(int space) { 00265 space_above_ = space; 00266 } 00267 int space_below() const { 00268 return space_below_; 00269 } 00270 void set_space_below(int space) { 00271 space_below_ = space; 00272 } 00273 int space_to_left() const { 00274 return space_to_left_; 00275 } 00276 void set_space_to_left(int space) { 00277 space_to_left_ = space; 00278 } 00279 int space_to_right() const { 00280 return space_to_right_; 00281 } 00282 void set_space_to_right(int space) { 00283 space_to_right_ = space; 00284 } 00285 uinT8* color1() { 00286 return color1_; 00287 } 00288 uinT8* color2() { 00289 return color2_; 00290 } 00291 bool owns_blobs() const { 00292 return owns_blobs_; 00293 } 00294 void set_owns_blobs(bool owns_blobs) { 00295 // Do NOT change ownership flag when there are blobs in the list. 00296 // Immediately set the ownership flag when creating copies. 00297 ASSERT_HOST(boxes_.empty()); 00298 owns_blobs_ = owns_blobs; 00299 } 00300 00301 // Inline quasi-accessors that require some computation. 00302 00303 // Returns the middle y-coord of the bounding box. 00304 int MidY() const { 00305 return (bounding_box_.top() + bounding_box_.bottom()) / 2; 00306 } 00307 // Returns the middle y-coord of the median top and bottom. 00308 int MedianY() const { 00309 return (median_top_ + median_bottom_) / 2; 00310 } 00311 // Returns the middle x-coord of the bounding box. 00312 int MidX() const { 00313 return (bounding_box_.left() + bounding_box_.right()) / 2; 00314 } 00315 // Returns the sort key at any given x,y. 00316 int SortKey(int x, int y) const { 00317 return TabVector::SortKey(vertical_, x, y); 00318 } 00319 // Returns the x corresponding to the sortkey, y pair. 00320 int XAtY(int sort_key, int y) const { 00321 return TabVector::XAtY(vertical_, sort_key, y); 00322 } 00323 // Returns the x difference between the two sort keys. 00324 int KeyWidth(int left_key, int right_key) const { 00325 return (right_key - left_key) / vertical_.y(); 00326 } 00327 // Returns the column width between the left and right keys. 00328 int ColumnWidth() const { 00329 return KeyWidth(left_key_, right_key_); 00330 } 00331 // Returns the sort key of the box left edge. 00332 int BoxLeftKey() const { 00333 return SortKey(bounding_box_.left(), MidY()); 00334 } 00335 // Returns the sort key of the box right edge. 00336 int BoxRightKey() const { 00337 return SortKey(bounding_box_.right(), MidY()); 00338 } 00339 // Returns the left edge at the given y, using the sort key. 00340 int LeftAtY(int y) const { 00341 return XAtY(left_key_, y); 00342 } 00343 // Returns the right edge at the given y, using the sort key. 00344 int RightAtY(int y) const { 00345 return XAtY(right_key_, y); 00346 } 00347 // Returns true if the right edge of this is to the left of the right 00348 // edge of other. 00349 bool IsLeftOf(const ColPartition& other) const { 00350 return bounding_box_.right() < other.bounding_box_.right(); 00351 } 00352 // Returns true if the partition contains the given x coordinate at the y. 00353 bool ColumnContains(int x, int y) const { 00354 return LeftAtY(y) - 1 <= x && x <= RightAtY(y) + 1; 00355 } 00356 // Returns true if there are no blobs in the list. 00357 bool IsEmpty() const { 00358 return boxes_.empty(); 00359 } 00360 // Returns true if there is a single blob in the list. 00361 bool IsSingleton() const { 00362 return boxes_.singleton(); 00363 } 00364 // Returns true if this and other overlap horizontally by bounding box. 00365 bool HOverlaps(const ColPartition& other) const { 00366 return bounding_box_.x_overlap(other.bounding_box_); 00367 } 00368 // Returns true if this and other's bounding boxes overlap vertically. 00369 // TODO(rays) Make HOverlaps and VOverlaps truly symmetric. 00370 bool VOverlaps(const ColPartition& other) const { 00371 return bounding_box_.y_gap(other.bounding_box_) < 0; 00372 } 00373 // Returns the vertical overlap (by median) of this and other. 00374 // WARNING! Only makes sense on horizontal partitions! 00375 int VCoreOverlap(const ColPartition& other) const { 00376 return MIN(median_top_, other.median_top_) - 00377 MAX(median_bottom_, other.median_bottom_); 00378 } 00379 // Returns the horizontal overlap (by median) of this and other. 00380 // WARNING! Only makes sense on vertical partitions! 00381 int HCoreOverlap(const ColPartition& other) const { 00382 return MIN(median_right_, other.median_right_) - 00383 MAX(median_left_, other.median_left_); 00384 } 00385 // Returns true if this and other overlap significantly vertically. 00386 // WARNING! Only makes sense on horizontal partitions! 00387 bool VSignificantCoreOverlap(const ColPartition& other) const { 00388 int overlap = VCoreOverlap(other); 00389 int height = MIN(median_top_ - median_bottom_, 00390 other.median_top_ - other.median_bottom_); 00391 return overlap * 3 > height; 00392 } 00393 // Returns true if this and other can be combined without putting a 00394 // horizontal step in either left or right edge of the resulting block. 00395 bool WithinSameMargins(const ColPartition& other) const { 00396 return left_margin_ <= other.bounding_box_.left() && 00397 bounding_box_.left() >= other.left_margin_ && 00398 bounding_box_.right() <= other.right_margin_ && 00399 right_margin_ >= other.bounding_box_.right(); 00400 } 00401 // Returns true if the region types (aligned_text_) match. 00402 // Lines never match anything, as they should never be merged or chained. 00403 bool TypesMatch(const ColPartition& other) const { 00404 return TypesMatch(blob_type_, other.blob_type_); 00405 } 00406 static bool TypesMatch(BlobRegionType type1, BlobRegionType type2) { 00407 return (type1 == type2 || type1 == BRT_UNKNOWN || type2 == BRT_UNKNOWN) && 00408 !BLOBNBOX::IsLineType(type1) && !BLOBNBOX::IsLineType(type2); 00409 } 00410 00411 // Returns true if the types are similar to each other. 00412 static bool TypesSimilar(PolyBlockType type1, PolyBlockType type2) { 00413 return (type1 == type2 || 00414 (type1 == PT_FLOWING_TEXT && type2 == PT_INLINE_EQUATION) || 00415 (type2 == PT_FLOWING_TEXT && type1 == PT_INLINE_EQUATION)); 00416 } 00417 00418 // Returns true if partitions is of horizontal line type 00419 bool IsLineType() const { 00420 return PTIsLineType(type_); 00421 } 00422 // Returns true if partitions is of image type 00423 bool IsImageType() const { 00424 return PTIsImageType(type_); 00425 } 00426 // Returns true if partitions is of text type 00427 bool IsTextType() const { 00428 return PTIsTextType(type_); 00429 } 00430 // Returns true if partitions is of pullout(inter-column) type 00431 bool IsPulloutType() const { 00432 return PTIsPulloutType(type_); 00433 } 00434 // Returns true if the partition is of an exclusively vertical type. 00435 bool IsVerticalType() const { 00436 return blob_type_ == BRT_VERT_TEXT || blob_type_ == BRT_VLINE; 00437 } 00438 // Returns true if the partition is of a definite horizontal type. 00439 bool IsHorizontalType() const { 00440 return blob_type_ == BRT_TEXT || blob_type_ == BRT_HLINE; 00441 } 00442 // Returns true is the partition is of a type that cannot be merged. 00443 bool IsUnMergeableType() const { 00444 return BLOBNBOX::UnMergeableType(blob_type_) || type_ == PT_NOISE; 00445 } 00446 // Returns true if this partition is a vertical line 00447 // TODO(nbeato): Use PartitionType enum when Ray's code is submitted. 00448 bool IsVerticalLine() const { 00449 return IsVerticalType() && IsLineType(); 00450 } 00451 // Returns true if this partition is a horizontal line 00452 // TODO(nbeato): Use PartitionType enum when Ray's code is submitted. 00453 bool IsHorizontalLine() const { 00454 return IsHorizontalType() && IsLineType(); 00455 } 00456 00457 // Adds the given box to the partition, updating the partition bounds. 00458 // The list of boxes in the partition is updated, ensuring that no box is 00459 // recorded twice, and the boxes are kept in increasing left position. 00460 void AddBox(BLOBNBOX* box); 00461 00462 // Removes the given box from the partition, updating the bounds. 00463 void RemoveBox(BLOBNBOX* box); 00464 00465 // Returns the tallest box in the partition, as measured perpendicular to the 00466 // presumed flow of text. 00467 BLOBNBOX* BiggestBox(); 00468 00469 // Returns the bounding box excluding the given box. 00470 TBOX BoundsWithoutBox(BLOBNBOX* box); 00471 00472 // Claims the boxes in the boxes_list by marking them with a this owner 00473 // pointer. 00474 void ClaimBoxes(); 00475 00476 // NULL the owner of the blobs in this partition, so they can be deleted 00477 // independently of the ColPartition. 00478 void DisownBoxes(); 00479 // NULL the owner of the blobs in this partition that are owned by this 00480 // partition, so they can be deleted independently of the ColPartition. 00481 // Any blobs that are not owned by this partition get to keep their owner 00482 // without an assert failure. 00483 void DisownBoxesNoAssert(); 00484 // NULLs the owner of the blobs in this partition that are owned by this 00485 // partition and not leader blobs, removing them from the boxes_ list, thus 00486 // turning this partition back to a leader partition if it contains a leader, 00487 // or otherwise leaving it empty. Returns true if any boxes remain. 00488 bool ReleaseNonLeaderBoxes(); 00489 00490 // Delete the boxes that this partition owns. 00491 void DeleteBoxes(); 00492 00493 // Reflects the partition in the y-axis, assuming that its blobs have 00494 // already been done. Corrects only a limited part of the members, since 00495 // this function is assumed to be used shortly after initial creation, which 00496 // is before a lot of the members are used. 00497 void ReflectInYAxis(); 00498 00499 // Returns true if this is a legal partition - meaning that the conditions 00500 // left_margin <= bounding_box left 00501 // left_key <= bounding box left key 00502 // bounding box left <= bounding box right 00503 // and likewise for right margin and key 00504 // are all met. 00505 bool IsLegal(); 00506 00507 // Returns true if the left and right edges are approximately equal. 00508 bool MatchingColumns(const ColPartition& other) const; 00509 00510 // Returns true if the colors match for two text partitions. 00511 bool MatchingTextColor(const ColPartition& other) const; 00512 00513 // Returns true if the sizes match for two text partitions, 00514 // taking orientation into account 00515 bool MatchingSizes(const ColPartition& other) const; 00516 00517 // Returns true if there is no tabstop violation in merging this and other. 00518 bool ConfirmNoTabViolation(const ColPartition& other) const; 00519 00520 // Returns true if other has a similar stroke width to this. 00521 bool MatchingStrokeWidth(const ColPartition& other, 00522 double fractional_tolerance, 00523 double constant_tolerance) const; 00524 // Returns true if candidate is an acceptable diacritic base char merge 00525 // with this as the diacritic. 00526 bool OKDiacriticMerge(const ColPartition& candidate, bool debug) const; 00527 00528 // Sets the sort key using either the tab vector, or the bounding box if 00529 // the tab vector is NULL. If the tab_vector lies inside the bounding_box, 00530 // use the edge of the box as a key any way. 00531 void SetLeftTab(const TabVector* tab_vector); 00532 void SetRightTab(const TabVector* tab_vector); 00533 00534 // Copies the left/right tab from the src partition, but if take_box is 00535 // true, copies the box instead and uses that as a key. 00536 void CopyLeftTab(const ColPartition& src, bool take_box); 00537 void CopyRightTab(const ColPartition& src, bool take_box); 00538 00539 // Returns the left rule line x coord of the leftmost blob. 00540 int LeftBlobRule() const; 00541 // Returns the right rule line x coord of the rightmost blob. 00542 int RightBlobRule() const; 00543 00544 // Returns the density value for a particular BlobSpecialTextType. 00545 float SpecialBlobsDensity(const BlobSpecialTextType type) const; 00546 // Returns the number of blobs for a particular BlobSpecialTextType. 00547 int SpecialBlobsCount(const BlobSpecialTextType type); 00548 // Set the density value for a particular BlobSpecialTextType, should ONLY be 00549 // used for debugging or testing. In production code, use 00550 // ComputeSpecialBlobsDensity instead. 00551 void SetSpecialBlobsDensity( 00552 const BlobSpecialTextType type, const float density); 00553 // Compute the SpecialTextType density of blobs, where we assume 00554 // that the SpecialTextType in the boxes_ has been set. 00555 void ComputeSpecialBlobsDensity(); 00556 00557 // Add a partner above if upper, otherwise below. 00558 // Add them uniquely and keep the list sorted by box left. 00559 // Partnerships are added symmetrically to partner and this. 00560 void AddPartner(bool upper, ColPartition* partner); 00561 // Removes the partner from this, but does not remove this from partner. 00562 // This asymmetric removal is so as not to mess up the iterator that is 00563 // working on partner's partner list. 00564 void RemovePartner(bool upper, ColPartition* partner); 00565 // Returns the partner if the given partner is a singleton, otherwise NULL. 00566 ColPartition* SingletonPartner(bool upper); 00567 00568 // Merge with the other partition and delete it. 00569 void Absorb(ColPartition* other, WidthCallback* cb); 00570 00571 // Returns true if the overlap between this and the merged pair of 00572 // merge candidates is sufficiently trivial to be allowed. 00573 // The merged box can graze the edge of this by the ok_box_overlap 00574 // if that exceeds the margin to the median top and bottom. 00575 bool OKMergeOverlap(const ColPartition& merge1, const ColPartition& merge2, 00576 int ok_box_overlap, bool debug); 00577 00578 // Find the blob at which to split this to minimize the overlap with the 00579 // given box. Returns the first blob to go in the second partition. 00580 BLOBNBOX* OverlapSplitBlob(const TBOX& box); 00581 00582 // Split this partition keeping the first half in this and returning 00583 // the second half. 00584 // Splits by putting the split_blob and the blobs that follow 00585 // in the second half, and the rest in the first half. 00586 ColPartition* SplitAtBlob(BLOBNBOX* split_blob); 00587 00588 // Splits this partition at the given x coordinate, returning the right 00589 // half and keeping the left half in this. 00590 ColPartition* SplitAt(int split_x); 00591 00592 // Recalculates all the coordinate limits of the partition. 00593 void ComputeLimits(); 00594 00595 // Returns the number of boxes that overlap the given box. 00596 int CountOverlappingBoxes(const TBOX& box); 00597 00598 // Computes and sets the type_, first_column_, last_column_ and column_set_. 00599 // resolution refers to the ppi resolution of the image. 00600 void SetPartitionType(int resolution, ColPartitionSet* columns); 00601 00602 // Returns the PartitionType from the current BlobRegionType and a column 00603 // flow spanning type ColumnSpanningType, generated by 00604 // ColPartitionSet::SpanningType, that indicates how the partition sits 00605 // in the columns. 00606 PolyBlockType PartitionType(ColumnSpanningType flow) const; 00607 00608 // Returns the first and last column touched by this partition. 00609 // resolution refers to the ppi resolution of the image. 00610 void ColumnRange(int resolution, ColPartitionSet* columns, 00611 int* first_col, int* last_col); 00612 00613 // Sets the internal flags good_width_ and good_column_. 00614 void SetColumnGoodness(WidthCallback* cb); 00615 00616 // Determines whether the blobs in this partition mostly represent 00617 // a leader (fixed pitch sequence) and sets the member blobs accordingly. 00618 // Note that height is assumed to have been tested elsewhere, and that this 00619 // function will find most fixed-pitch text as leader without a height filter. 00620 // Leader detection is limited to sequences of identical width objects, 00621 // such as .... or ----, so patterns, such as .-.-.-.-. will not be found. 00622 bool MarkAsLeaderIfMonospaced(); 00623 // Given the result of TextlineProjection::EvaluateColPartition, (positive for 00624 // horizontal text, negative for vertical text, and near zero for non-text), 00625 // sets the blob_type_ and flow_ for this partition to indicate whether it 00626 // is strongly or weakly vertical or horizontal text, or non-text. 00627 void SetRegionAndFlowTypesFromProjectionValue(int value); 00628 00629 // Sets all blobs with the partition blob type and flow, but never overwrite 00630 // leader blobs, as we need to be able to identify them later. 00631 void SetBlobTypes(); 00632 00633 // Returns true if a decent baseline can be fitted through the blobs. 00634 // Works for both horizontal and vertical text. 00635 bool HasGoodBaseline(); 00636 00637 // Adds this ColPartition to a matching WorkingPartSet if one can be found, 00638 // otherwise starts a new one in the appropriate column, ending the previous. 00639 void AddToWorkingSet(const ICOORD& bleft, const ICOORD& tright, 00640 int resolution, ColPartition_LIST* used_parts, 00641 WorkingPartSet_LIST* working_set); 00642 00643 // From the given block_parts list, builds one or more BLOCKs and 00644 // corresponding TO_BLOCKs, such that the line spacing is uniform in each. 00645 // Created blocks are appended to the end of completed_blocks and to_blocks. 00646 // The used partitions are put onto used_parts, as they may still be referred 00647 // to in the partition grid. bleft, tright and resolution are the bounds 00648 // and resolution of the original image. 00649 static void LineSpacingBlocks(const ICOORD& bleft, const ICOORD& tright, 00650 int resolution, 00651 ColPartition_LIST* block_parts, 00652 ColPartition_LIST* used_parts, 00653 BLOCK_LIST* completed_blocks, 00654 TO_BLOCK_LIST* to_blocks); 00655 // Constructs a block from the given list of partitions. 00656 // Arguments are as LineSpacingBlocks above. 00657 static TO_BLOCK* MakeBlock(const ICOORD& bleft, const ICOORD& tright, 00658 ColPartition_LIST* block_parts, 00659 ColPartition_LIST* used_parts); 00660 00661 // Constructs a block from the given list of vertical text partitions. 00662 // Currently only creates rectangular blocks. 00663 static TO_BLOCK* MakeVerticalTextBlock(const ICOORD& bleft, 00664 const ICOORD& tright, 00665 ColPartition_LIST* block_parts, 00666 ColPartition_LIST* used_parts); 00667 00668 // Makes a TO_ROW matching this and moves all the blobs to it, transferring 00669 // ownership to to returned TO_ROW. 00670 TO_ROW* MakeToRow(); 00671 00672 00673 // Returns a copy of everything except the list of boxes. The resulting 00674 // ColPartition is only suitable for keeping in a column candidate list. 00675 ColPartition* ShallowCopy() const; 00676 // Returns a copy of everything with a shallow copy of the blobs. 00677 // The blobs are still owned by their original parent, so they are 00678 // treated as read-only. 00679 ColPartition* CopyButDontOwnBlobs(); 00680 00681 #ifndef GRAPHICS_DISABLED 00682 // Provides a color for BBGrid to draw the rectangle. 00683 ScrollView::Color BoxColor() const; 00684 #endif // GRAPHICS_DISABLED 00685 00686 // Prints debug information on this. 00687 void Print() const; 00688 // Prints debug information on the colors. 00689 void PrintColors(); 00690 00691 // Sets the types of all partitions in the run to be the max of the types. 00692 void SmoothPartnerRun(int working_set_count); 00693 00694 // Cleans up the partners of the given type so that there is at most 00695 // one partner. This makes block creation simpler. 00696 // If get_desperate is true, goes to more desperate merge methods 00697 // to merge flowing text before breaking partnerships. 00698 void RefinePartners(PolyBlockType type, bool get_desperate, 00699 ColPartitionGrid* grid); 00700 00701 // Returns true if this column partition is in the same column as 00702 // part. This function will only work after the SetPartitionType function 00703 // has been called on both column partitions. This is useful for 00704 // doing a SideSearch when you want things in the same page column. 00705 bool IsInSameColumnAs(const ColPartition& part) const; 00706 00707 // Sets the column bounds. Primarily used in testing. 00708 void set_first_column(int column) { 00709 first_column_ = column; 00710 } 00711 void set_last_column(int column) { 00712 last_column_ = column; 00713 } 00714 00715 private: 00716 // enum to refer to the entries in a neighbourhood of lines. 00717 // Used by SmoothSpacings to test for blips with OKSpacingBlip. 00718 enum SpacingNeighbourhood { 00719 PN_ABOVE2, 00720 PN_ABOVE1, 00721 PN_UPPER, 00722 PN_LOWER, 00723 PN_BELOW1, 00724 PN_BELOW2, 00725 PN_COUNT 00726 }; 00727 00728 // Cleans up the partners above if upper is true, else below. 00729 // If get_desperate is true, goes to more desperate merge methods 00730 // to merge flowing text before breaking partnerships. 00731 void RefinePartnersInternal(bool upper, bool get_desperate, 00732 ColPartitionGrid* grid); 00733 // Restricts the partners to only desirable types. For text and BRT_HLINE this 00734 // means the same type_ , and for image types it means any image type. 00735 void RefinePartnersByType(bool upper, ColPartition_CLIST* partners); 00736 // Remove transitive partnerships: this<->a, and a<->b and this<->b. 00737 // Gets rid of this<->b, leaving a clean chain. 00738 // Also if we have this<->a and a<->this, then gets rid of this<->a, as 00739 // this has multiple partners. 00740 void RefinePartnerShortcuts(bool upper, ColPartition_CLIST* partners); 00741 // If multiple text partners can be merged, then do so. 00742 // If desperate is true, then an increase in overlap with the merge is 00743 // allowed. If the overlap increases, then the desperately_merged_ flag 00744 // is set, indicating that the textlines probably need to be regenerated 00745 // by aggressive line fitting/splitting, as there are probably vertically 00746 // joined blobs that cross textlines. 00747 void RefineTextPartnersByMerge(bool upper, bool desperate, 00748 ColPartition_CLIST* partners, 00749 ColPartitionGrid* grid); 00750 // Keep the partner with the biggest overlap. 00751 void RefinePartnersByOverlap(bool upper, ColPartition_CLIST* partners); 00752 00753 // Return true if bbox belongs better in this than other. 00754 bool ThisPartitionBetter(BLOBNBOX* bbox, const ColPartition& other); 00755 00756 // Smoothes the spacings in the list into groups of equal linespacing. 00757 // resolution is the resolution of the original image, used as a basis 00758 // for thresholds in change of spacing. page_height is in pixels. 00759 static void SmoothSpacings(int resolution, int page_height, 00760 ColPartition_LIST* parts); 00761 00762 // Returns true if the parts array of pointers to partitions matches the 00763 // condition for a spacing blip. See SmoothSpacings for what this means 00764 // and how it is used. 00765 static bool OKSpacingBlip(int resolution, int median_spacing, 00766 ColPartition** parts); 00767 00768 // Returns true if both the top and bottom spacings of this match the given 00769 // spacing to within suitable margins dictated by the image resolution. 00770 bool SpacingEqual(int spacing, int resolution) const; 00771 00772 // Returns true if both the top and bottom spacings of this and other 00773 // match to within suitable margins dictated by the image resolution. 00774 bool SpacingsEqual(const ColPartition& other, int resolution) const; 00775 00776 // Returns true if the sum spacing of this and other match the given 00777 // spacing (or twice the given spacing) to within a suitable margin dictated 00778 // by the image resolution. 00779 bool SummedSpacingOK(const ColPartition& other, 00780 int spacing, int resolution) const; 00781 00782 // Returns a suitable spacing margin that can be applied to bottoms of 00783 // text lines, based on the resolution and the stored side_step_. 00784 int BottomSpacingMargin(int resolution) const; 00785 00786 // Returns a suitable spacing margin that can be applied to tops of 00787 // text lines, based on the resolution and the stored side_step_. 00788 int TopSpacingMargin(int resolution) const; 00789 00790 // Returns true if the median text sizes of this and other agree to within 00791 // a reasonable multiplicative factor. 00792 bool SizesSimilar(const ColPartition& other) const; 00793 00794 // Computes and returns in start, end a line segment formed from a 00795 // forwards-iterated group of left edges of partitions that satisfy the 00796 // condition that the rightmost left margin is to the left of the 00797 // leftmost left bounding box edge. 00798 // TODO(rays) Not good enough. Needs improving to tightly wrap text in both 00799 // directions, and to loosely wrap images. 00800 static void LeftEdgeRun(ColPartition_IT* part_it, 00801 ICOORD* start, ICOORD* end); 00802 // Computes and returns in start, end a line segment formed from a 00803 // backwards-iterated group of right edges of partitions that satisfy the 00804 // condition that the leftmost right margin is to the right of the 00805 // rightmost right bounding box edge. 00806 // TODO(rays) Not good enough. Needs improving to tightly wrap text in both 00807 // directions, and to loosely wrap images. 00808 static void RightEdgeRun(ColPartition_IT* part_it, 00809 ICOORD* start, ICOORD* end); 00810 00811 // The margins are determined by the position of the nearest vertically 00812 // overlapping neighbour to the side. They indicate the maximum extent 00813 // that the block/column may be extended without touching something else. 00814 // Leftmost coordinate that the region may occupy over the y limits. 00815 int left_margin_; 00816 // Rightmost coordinate that the region may occupy over the y limits. 00817 int right_margin_; 00818 // Bounding box of all blobs in the partition. 00819 TBOX bounding_box_; 00820 // Median top and bottom of blobs in this partition. 00821 int median_bottom_; 00822 int median_top_; 00823 // Median height of blobs in this partition. 00824 // TODO(rays) rename median_height_. 00825 int median_size_; 00826 // Median left and right of blobs in this partition. 00827 int median_left_; 00828 int median_right_; 00829 // Median width of blobs in this partition. 00830 int median_width_; 00831 // blob_region_type_ for the blobs in this partition. 00832 BlobRegionType blob_type_; 00833 BlobTextFlowType flow_; // Quality of text flow. 00834 // Total of GoodTextBlob results for all blobs in the partition. 00835 int good_blob_score_; 00836 // True if this partition has a common width. 00837 bool good_width_; 00838 // True if this is a good column candidate. 00839 bool good_column_; 00840 // True if the left_key_ is from a tab vector. 00841 bool left_key_tab_; 00842 // True if the right_key_ is from a tab vector. 00843 bool right_key_tab_; 00844 // Left and right sort keys for the edges of the partition. 00845 // If the respective *_key_tab_ is true then this key came from a tab vector. 00846 // If not, then the class promises to keep the key equal to the sort key 00847 // for the respective edge of the bounding box at the MidY, so that 00848 // LeftAtY and RightAtY always returns an x coordinate on the line parallel 00849 // to vertical_ through the bounding box edge at MidY. 00850 int left_key_; 00851 int right_key_; 00852 // Type of this partition after looking at its relation to the columns. 00853 PolyBlockType type_; 00854 // All boxes in the partition stored in increasing left edge coordinate. 00855 BLOBNBOX_CLIST boxes_; 00856 // The global vertical skew direction. 00857 ICOORD vertical_; 00858 // The partitions above that matched this. 00859 ColPartition_CLIST upper_partners_; 00860 // The partitions below that matched this. 00861 ColPartition_CLIST lower_partners_; 00862 // The WorkingPartSet it lives in while blocks are being made. 00863 WorkingPartSet* working_set_; 00864 // Flag is true when AddBox is sorting vertically, false otherwise. 00865 bool last_add_was_vertical_; 00866 // True when the partition's ownership has been taken from the grid and 00867 // placed in a working set, or, after that, in the good_parts_ list. 00868 bool block_owned_; 00869 // Flag to indicate that this partition was subjected to a desperate merge, 00870 // and therefore the textlines need rebuilding. 00871 bool desperately_merged_; 00872 // The first and last column that this partition applies to. 00873 // Flowing partitions (see type_) will have an equal first and last value 00874 // of the form 2n + 1, where n is the zero-based index into the partitions 00875 // in column_set_. (See ColPartitionSet::GetColumnByIndex). 00876 // Heading partitions will have unequal values of the same form. 00877 // Pullout partitions will have equal values, but may have even values, 00878 // indicating placement between columns. 00879 int first_column_; 00880 int last_column_; 00881 // Column_set_ is the column layout applicable to this ColPartition. 00882 ColPartitionSet* column_set_; 00883 // Linespacing data. 00884 int side_step_; // Median y-shift to next blob on same line. 00885 int top_spacing_; // Line spacing from median_top_. 00886 int bottom_spacing_; // Line spacing from median_bottom_. 00887 00888 // Type of this partition before considering it as a table cell. This is 00889 // used to revert the type if a partition is first marked as a table cell but 00890 // later filtering steps decide it does not belong to a table 00891 PolyBlockType type_before_table_; 00892 bool inside_table_column_; // Check whether the current partition has been 00893 // assigned to a table column 00894 // Nearest neighbor above with major x-overlap 00895 ColPartition* nearest_neighbor_above_; 00896 // Nearest neighbor below with major x-overlap 00897 ColPartition* nearest_neighbor_below_; 00898 int space_above_; // Distance from nearest_neighbor_above 00899 int space_below_; // Distance from nearest_neighbor_below 00900 int space_to_left_; // Distance from the left edge of the column 00901 int space_to_right_; // Distance from the right edge of the column 00902 // Color foreground/background data. 00903 uinT8 color1_[kRGBRMSColors]; 00904 uinT8 color2_[kRGBRMSColors]; 00905 bool owns_blobs_; // Does the partition own its blobs? 00906 // The density of special blobs. 00907 float special_blobs_densities_[BSTT_COUNT]; 00908 }; 00909 00910 // Typedef it now in case it becomes a class later. 00911 typedef GridSearch<ColPartition, 00912 ColPartition_CLIST, 00913 ColPartition_C_IT> ColPartitionGridSearch; 00914 00915 } // namespace tesseract. 00916 00917 #endif // TESSERACT_TEXTORD_COLPARTITION_H__