Tesseract
3.02
|
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 the partition is of an exclusively vertical type. 00431 bool IsVerticalType() const { 00432 return blob_type_ == BRT_VERT_TEXT || blob_type_ == BRT_VLINE; 00433 } 00434 // Returns true if the partition is of a definite horizontal type. 00435 bool IsHorizontalType() const { 00436 return blob_type_ == BRT_TEXT || blob_type_ == BRT_HLINE; 00437 } 00438 // Returns true is the partition is of a type that cannot be merged. 00439 bool IsUnMergeableType() const { 00440 return BLOBNBOX::UnMergeableType(blob_type_) || type_ == PT_NOISE; 00441 } 00442 // Returns true if this partition is a vertical line 00443 // TODO(nbeato): Use PartitionType enum when Ray's code is submitted. 00444 bool IsVerticalLine() const { 00445 return IsVerticalType() && IsLineType(); 00446 } 00447 // Returns true if this partition is a horizontal line 00448 // TODO(nbeato): Use PartitionType enum when Ray's code is submitted. 00449 bool IsHorizontalLine() const { 00450 return IsHorizontalType() && IsLineType(); 00451 } 00452 00453 // Adds the given box to the partition, updating the partition bounds. 00454 // The list of boxes in the partition is updated, ensuring that no box is 00455 // recorded twice, and the boxes are kept in increasing left position. 00456 void AddBox(BLOBNBOX* box); 00457 00458 // Removes the given box from the partition, updating the bounds. 00459 void RemoveBox(BLOBNBOX* box); 00460 00461 // Returns the tallest box in the partition, as measured perpendicular to the 00462 // presumed flow of text. 00463 BLOBNBOX* BiggestBox(); 00464 00465 // Returns the bounding box excluding the given box. 00466 TBOX BoundsWithoutBox(BLOBNBOX* box); 00467 00468 // Claims the boxes in the boxes_list by marking them with a this owner 00469 // pointer. 00470 void ClaimBoxes(); 00471 00472 // NULL the owner of the blobs in this partition, so they can be deleted 00473 // independently of the ColPartition. 00474 void DisownBoxes(); 00475 00476 // Delete the boxes that this partition owns. 00477 void DeleteBoxes(); 00478 00479 // Reflects the partition in the y-axis, assuming that its blobs have 00480 // already been done. Corrects only a limited part of the members, since 00481 // this function is assumed to be used shortly after initial creation, which 00482 // is before a lot of the members are used. 00483 void ReflectInYAxis(); 00484 00485 // Returns true if this is a legal partition - meaning that the conditions 00486 // left_margin <= bounding_box left 00487 // left_key <= bounding box left key 00488 // bounding box left <= bounding box right 00489 // and likewise for right margin and key 00490 // are all met. 00491 bool IsLegal(); 00492 00493 // Returns true if the left and right edges are approximately equal. 00494 bool MatchingColumns(const ColPartition& other) const; 00495 00496 // Returns true if the colors match for two text partitions. 00497 bool MatchingTextColor(const ColPartition& other) const; 00498 00499 // Returns true if the sizes match for two text partitions, 00500 // taking orientation into account 00501 bool MatchingSizes(const ColPartition& other) const; 00502 00503 // Returns true if there is no tabstop violation in merging this and other. 00504 bool ConfirmNoTabViolation(const ColPartition& other) const; 00505 00506 // Returns true if other has a similar stroke width to this. 00507 bool MatchingStrokeWidth(const ColPartition& other, 00508 double fractional_tolerance, 00509 double constant_tolerance) const; 00510 // Returns true if candidate is an acceptable diacritic base char merge 00511 // with this as the diacritic. 00512 bool OKDiacriticMerge(const ColPartition& candidate, bool debug) const; 00513 00514 // Sets the sort key using either the tab vector, or the bounding box if 00515 // the tab vector is NULL. If the tab_vector lies inside the bounding_box, 00516 // use the edge of the box as a key any way. 00517 void SetLeftTab(const TabVector* tab_vector); 00518 void SetRightTab(const TabVector* tab_vector); 00519 00520 // Copies the left/right tab from the src partition, but if take_box is 00521 // true, copies the box instead and uses that as a key. 00522 void CopyLeftTab(const ColPartition& src, bool take_box); 00523 void CopyRightTab(const ColPartition& src, bool take_box); 00524 00525 // Returns the left rule line x coord of the leftmost blob. 00526 int LeftBlobRule() const; 00527 // Returns the right rule line x coord of the rightmost blob. 00528 int RightBlobRule() const; 00529 00530 // Returns the density value for a particular BlobSpecialTextType. 00531 float SpecialBlobsDensity(const BlobSpecialTextType type) const; 00532 // Returns the number of blobs for a particular BlobSpecialTextType. 00533 int SpecialBlobsCount(const BlobSpecialTextType type); 00534 // Set the density value for a particular BlobSpecialTextType, should ONLY be 00535 // used for debugging or testing. In production code, use 00536 // ComputeSpecialBlobsDensity instead. 00537 void SetSpecialBlobsDensity( 00538 const BlobSpecialTextType type, const float density); 00539 // Compute the SpecialTextType density of blobs, where we assume 00540 // that the SpecialTextType in the boxes_ has been set. 00541 void ComputeSpecialBlobsDensity(); 00542 00543 // Add a partner above if upper, otherwise below. 00544 // Add them uniquely and keep the list sorted by box left. 00545 // Partnerships are added symmetrically to partner and this. 00546 void AddPartner(bool upper, ColPartition* partner); 00547 // Removes the partner from this, but does not remove this from partner. 00548 // This asymmetric removal is so as not to mess up the iterator that is 00549 // working on partner's partner list. 00550 void RemovePartner(bool upper, ColPartition* partner); 00551 // Returns the partner if the given partner is a singleton, otherwise NULL. 00552 ColPartition* SingletonPartner(bool upper); 00553 00554 // Merge with the other partition and delete it. 00555 void Absorb(ColPartition* other, WidthCallback* cb); 00556 00557 // Returns true if the overlap between this and the merged pair of 00558 // merge candidates is sufficiently trivial to be allowed. 00559 // The merged box can graze the edge of this by the ok_box_overlap 00560 // if that exceeds the margin to the median top and bottom. 00561 bool OKMergeOverlap(const ColPartition& merge1, const ColPartition& merge2, 00562 int ok_box_overlap, bool debug); 00563 00564 // Find the blob at which to split this to minimize the overlap with the 00565 // given box. Returns the first blob to go in the second partition. 00566 BLOBNBOX* OverlapSplitBlob(const TBOX& box); 00567 00568 // Split this partition keeping the first half in this and returning 00569 // the second half. 00570 // Splits by putting the split_blob and the blobs that follow 00571 // in the second half, and the rest in the first half. 00572 ColPartition* SplitAtBlob(BLOBNBOX* split_blob); 00573 00574 // Splits this partition at the given x coordinate, returning the right 00575 // half and keeping the left half in this. 00576 ColPartition* SplitAt(int split_x); 00577 00578 // Recalculates all the coordinate limits of the partition. 00579 void ComputeLimits(); 00580 00581 // Returns the number of boxes that overlap the given box. 00582 int CountOverlappingBoxes(const TBOX& box); 00583 00584 // Computes and sets the type_, first_column_, last_column_ and column_set_. 00585 // resolution refers to the ppi resolution of the image. 00586 void SetPartitionType(int resolution, ColPartitionSet* columns); 00587 00588 // Returns the PartitionType from the current BlobRegionType and a column 00589 // flow spanning type ColumnSpanningType, generated by 00590 // ColPartitionSet::SpanningType, that indicates how the partition sits 00591 // in the columns. 00592 PolyBlockType PartitionType(ColumnSpanningType flow) const; 00593 00594 // Returns the first and last column touched by this partition. 00595 // resolution refers to the ppi resolution of the image. 00596 void ColumnRange(int resolution, ColPartitionSet* columns, 00597 int* first_col, int* last_col); 00598 00599 // Sets the internal flags good_width_ and good_column_. 00600 void SetColumnGoodness(WidthCallback* cb); 00601 00602 // Determines whether the blobs in this partition mostly represent 00603 // a leader (fixed pitch sequence) and sets the member blobs accordingly. 00604 // Note that height is assumed to have been tested elsewhere, and that this 00605 // function will find most fixed-pitch text as leader without a height filter. 00606 // Leader detection is limited to sequences of identical width objects, 00607 // such as .... or ----, so patterns, such as .-.-.-.-. will not be found. 00608 bool MarkAsLeaderIfMonospaced(); 00609 // Given the result of TextlineProjection::EvaluateColPartition, (positive for 00610 // horizontal text, negative for vertical text, and near zero for non-text), 00611 // sets the blob_type_ and flow_ for this partition to indicate whether it 00612 // is strongly or weakly vertical or horizontal text, or non-text. 00613 void SetRegionAndFlowTypesFromProjectionValue(int value); 00614 00615 // Sets all blobs with the partition blob type and flow, but never overwrite 00616 // leader blobs, as we need to be able to identify them later. 00617 void SetBlobTypes(); 00618 00619 // Returns true if a decent baseline can be fitted through the blobs. 00620 // Works for both horizontal and vertical text. 00621 bool HasGoodBaseline(); 00622 00623 // Adds this ColPartition to a matching WorkingPartSet if one can be found, 00624 // otherwise starts a new one in the appropriate column, ending the previous. 00625 void AddToWorkingSet(const ICOORD& bleft, const ICOORD& tright, 00626 int resolution, ColPartition_LIST* used_parts, 00627 WorkingPartSet_LIST* working_set); 00628 00629 // From the given block_parts list, builds one or more BLOCKs and 00630 // corresponding TO_BLOCKs, such that the line spacing is uniform in each. 00631 // Created blocks are appended to the end of completed_blocks and to_blocks. 00632 // The used partitions are put onto used_parts, as they may still be referred 00633 // to in the partition grid. bleft, tright and resolution are the bounds 00634 // and resolution of the original image. 00635 static void LineSpacingBlocks(const ICOORD& bleft, const ICOORD& tright, 00636 int resolution, 00637 ColPartition_LIST* block_parts, 00638 ColPartition_LIST* used_parts, 00639 BLOCK_LIST* completed_blocks, 00640 TO_BLOCK_LIST* to_blocks); 00641 // Constructs a block from the given list of partitions. 00642 // Arguments are as LineSpacingBlocks above. 00643 static TO_BLOCK* MakeBlock(const ICOORD& bleft, const ICOORD& tright, 00644 ColPartition_LIST* block_parts, 00645 ColPartition_LIST* used_parts); 00646 00647 // Constructs a block from the given list of vertical text partitions. 00648 // Currently only creates rectangular blocks. 00649 static TO_BLOCK* MakeVerticalTextBlock(const ICOORD& bleft, 00650 const ICOORD& tright, 00651 ColPartition_LIST* block_parts, 00652 ColPartition_LIST* used_parts); 00653 00654 00655 // Returns a copy of everything except the list of boxes. The resulting 00656 // ColPartition is only suitable for keeping in a column candidate list. 00657 ColPartition* ShallowCopy() const; 00658 // Returns a copy of everything with a shallow copy of the blobs. 00659 // The blobs are still owned by their original parent, so they are 00660 // treated as read-only. 00661 ColPartition* CopyButDontOwnBlobs(); 00662 00663 // Provides a color for BBGrid to draw the rectangle. 00664 ScrollView::Color BoxColor() const; 00665 00666 // Prints debug information on this. 00667 void Print() const; 00668 // Prints debug information on the colors. 00669 void PrintColors(); 00670 00671 // Sets the types of all partitions in the run to be the max of the types. 00672 void SmoothPartnerRun(int working_set_count); 00673 00674 // Cleans up the partners of the given type so that there is at most 00675 // one partner. This makes block creation simpler. 00676 // If get_desperate is true, goes to more desperate merge methods 00677 // to merge flowing text before breaking partnerships. 00678 void RefinePartners(PolyBlockType type, bool get_desparate, 00679 ColPartitionGrid* grid); 00680 00681 // Returns true if this column partition is in the same column as 00682 // part. This function will only work after the SetPartitionType function 00683 // has been called on both column partitions. This is useful for 00684 // doing a SideSearch when you want things in the same page column. 00685 bool IsInSameColumnAs(const ColPartition& part) const; 00686 00687 // Sets the column bounds. Primarily used in testing. 00688 void set_first_column(int column) { 00689 first_column_ = column; 00690 } 00691 void set_last_column(int column) { 00692 last_column_ = column; 00693 } 00694 00695 private: 00696 // enum to refer to the entries in a neigbourhood of lines. 00697 // Used by SmoothSpacings to test for blips with OKSpacingBlip. 00698 enum SpacingNeighbourhood { 00699 PN_ABOVE2, 00700 PN_ABOVE1, 00701 PN_UPPER, 00702 PN_LOWER, 00703 PN_BELOW1, 00704 PN_BELOW2, 00705 PN_COUNT 00706 }; 00707 00708 // Cleans up the partners above if upper is true, else below. 00709 // If get_desperate is true, goes to more desperate merge methods 00710 // to merge flowing text before breaking partnerships. 00711 void RefinePartnersInternal(bool upper, bool get_desperate, 00712 ColPartitionGrid* grid); 00713 // Restricts the partners to only desirable types. For text and BRT_HLINE this 00714 // means the same type_ , and for image types it means any image type. 00715 void RefinePartnersByType(bool upper, ColPartition_CLIST* partners); 00716 // Remove transitive partnerships: this<->a, and a<->b and this<->b. 00717 // Gets rid of this<->b, leaving a clean chain. 00718 // Also if we have this<->a and a<->this, then gets rid of this<->a, as 00719 // this has multiple partners. 00720 void RefinePartnerShortcuts(bool upper, ColPartition_CLIST* partners); 00721 // If multiple text partners can be merged, then do so. 00722 // If desperate is true, then an increase in overlap with the merge is 00723 // allowed. If the overlap increases, then the desperately_merged_ flag 00724 // is set, indicating that the textlines probably need to be regenerated 00725 // by aggressive line fitting/splitting, as there are probably vertically 00726 // joined blobs that cross textlines. 00727 void RefineTextPartnersByMerge(bool upper, bool desperate, 00728 ColPartition_CLIST* partners, 00729 ColPartitionGrid* grid); 00730 // Keep the partner with the biggest overlap. 00731 void RefinePartnersByOverlap(bool upper, ColPartition_CLIST* partners); 00732 00733 // Return true if bbox belongs better in this than other. 00734 bool ThisPartitionBetter(BLOBNBOX* bbox, const ColPartition& other); 00735 00736 // Smoothes the spacings in the list into groups of equal linespacing. 00737 // resolution is the resolution of the original image, used as a basis 00738 // for thresholds in change of spacing. page_height is in pixels. 00739 static void SmoothSpacings(int resolution, int page_height, 00740 ColPartition_LIST* parts); 00741 00742 // Returns true if the parts array of pointers to partitions matches the 00743 // condition for a spacing blip. See SmoothSpacings for what this means 00744 // and how it is used. 00745 static bool OKSpacingBlip(int resolution, int median_spacing, 00746 ColPartition** parts); 00747 00748 // Returns true if both the top and bottom spacings of this match the given 00749 // spacing to within suitable margins dictated by the image resolution. 00750 bool SpacingEqual(int spacing, int resolution) const; 00751 00752 // Returns true if both the top and bottom spacings of this and other 00753 // match to within suitable margins dictated by the image resolution. 00754 bool SpacingsEqual(const ColPartition& other, int resolution) const; 00755 00756 // Returns true if the sum spacing of this and other match the given 00757 // spacing (or twice the given spacing) to within a suitable margin dictated 00758 // by the image resolution. 00759 bool SummedSpacingOK(const ColPartition& other, 00760 int spacing, int resolution) const; 00761 00762 // Returns a suitable spacing margin that can be applied to bottoms of 00763 // text lines, based on the resolution and the stored side_step_. 00764 int BottomSpacingMargin(int resolution) const; 00765 00766 // Returns a suitable spacing margin that can be applied to tops of 00767 // text lines, based on the resolution and the stored side_step_. 00768 int TopSpacingMargin(int resolution) const; 00769 00770 // Returns true if the median text sizes of this and other agree to within 00771 // a reasonable multiplicative factor. 00772 bool SizesSimilar(const ColPartition& other) const; 00773 00774 // Computes and returns in start, end a line segment formed from a 00775 // forwards-iterated group of left edges of partitions that satisfy the 00776 // condition that the rightmost left margin is to the left of the 00777 // leftmost left bounding box edge. 00778 // TODO(rays) Not good enough. Needs improving to tightly wrap text in both 00779 // directions, and to loosely wrap images. 00780 static void LeftEdgeRun(ColPartition_IT* part_it, 00781 ICOORD* start, ICOORD* end); 00782 // Computes and returns in start, end a line segment formed from a 00783 // backwards-iterated group of right edges of partitions that satisfy the 00784 // condition that the leftmost right margin is to the right of the 00785 // rightmost right bounding box edge. 00786 // TODO(rays) Not good enough. Needs improving to tightly wrap text in both 00787 // directions, and to loosely wrap images. 00788 static void RightEdgeRun(ColPartition_IT* part_it, 00789 ICOORD* start, ICOORD* end); 00790 00791 // The margins are determined by the position of the nearest vertically 00792 // overlapping neighbour to the side. They indicate the maximum extent 00793 // that the block/column may be extended without touching something else. 00794 // Leftmost coordinate that the region may occupy over the y limits. 00795 int left_margin_; 00796 // Rightmost coordinate that the region may occupy over the y limits. 00797 int right_margin_; 00798 // Bounding box of all blobs in the partition. 00799 TBOX bounding_box_; 00800 // Median top and bottom of blobs in this partition. 00801 int median_bottom_; 00802 int median_top_; 00803 // Median height of blobs in this partition. 00804 // TODO(rays) rename median_height_. 00805 int median_size_; 00806 // Median left and right of blobs in this partition. 00807 int median_left_; 00808 int median_right_; 00809 // Median width of blobs in this partition. 00810 int median_width_; 00811 // blob_region_type_ for the blobs in this partition. 00812 BlobRegionType blob_type_; 00813 BlobTextFlowType flow_; // Quality of text flow. 00814 // Total of GoodTextBlob results for all blobs in the partition. 00815 int good_blob_score_; 00816 // True if this partition has a common width. 00817 bool good_width_; 00818 // True if this is a good column candidate. 00819 bool good_column_; 00820 // True if the left_key_ is from a tab vector. 00821 bool left_key_tab_; 00822 // True if the right_key_ is from a tab vector. 00823 bool right_key_tab_; 00824 // Left and right sort keys for the edges of the partition. 00825 // If the respective *_key_tab_ is true then this key came from a tab vector. 00826 // If not, then the class promises to keep the key equal to the sort key 00827 // for the respective edge of the bounding box at the MidY, so that 00828 // LeftAtY and RightAtY always returns an x coordinate on the line parallel 00829 // to vertical_ through the bounding box edge at MidY. 00830 int left_key_; 00831 int right_key_; 00832 // Type of this partition after looking at its relation to the columns. 00833 PolyBlockType type_; 00834 // All boxes in the partition stored in increasing left edge coordinate. 00835 BLOBNBOX_CLIST boxes_; 00836 // The global vertical skew direction. 00837 ICOORD vertical_; 00838 // The partitions above that matched this. 00839 ColPartition_CLIST upper_partners_; 00840 // The partitions below that matched this. 00841 ColPartition_CLIST lower_partners_; 00842 // The WorkingPartSet it lives in while blocks are being made. 00843 WorkingPartSet* working_set_; 00844 // Flag is true when AddBox is sorting vertically, false otherwise. 00845 bool last_add_was_vertical_; 00846 // True when the partition's ownership has been taken from the grid and 00847 // placed in a working set, or, after that, in the good_parts_ list. 00848 bool block_owned_; 00849 // Flag to indicate that this partition was subjected to a desperate merge, 00850 // and therefore the textlines need rebuilding. 00851 bool desperately_merged_; 00852 // The first and last column that this partition applies to. 00853 // Flowing partitions (see type_) will have an equal first and last value 00854 // of the form 2n + 1, where n is the zero-based index into the partitions 00855 // in column_set_. (See ColPartitionSet::GetColumnByIndex). 00856 // Heading partitions will have unequal values of the same form. 00857 // Pullout partitions will have equal values, but may have even values, 00858 // indicating placement between columns. 00859 int first_column_; 00860 int last_column_; 00861 // Column_set_ is the column layout applicable to this ColPartition. 00862 ColPartitionSet* column_set_; 00863 // Linespacing data. 00864 int side_step_; // Median y-shift to next blob on same line. 00865 int top_spacing_; // Line spacing from median_top_. 00866 int bottom_spacing_; // Line spacing from median_bottom_. 00867 00868 // Type of this partition before considering it as a table cell. This is 00869 // used to revert the type if a partition is first marked as a table cell but 00870 // later filtering steps decide it does not belong to a table 00871 PolyBlockType type_before_table_; 00872 bool inside_table_column_; // Check whether the current partition has been 00873 // assigned to a table column 00874 // Nearest neighbor above with major x-overlap 00875 ColPartition* nearest_neighbor_above_; 00876 // Nearest neighbor below with major x-overlap 00877 ColPartition* nearest_neighbor_below_; 00878 int space_above_; // Distance from nearest_neighbor_above 00879 int space_below_; // Distance from nearest_neighbor_below 00880 int space_to_left_; // Distance from the left edge of the column 00881 int space_to_right_; // Distance from the right edge of the column 00882 // Color foreground/background data. 00883 uinT8 color1_[kRGBRMSColors]; 00884 uinT8 color2_[kRGBRMSColors]; 00885 bool owns_blobs_; // Does the partition own its blobs? 00886 // The density of special blobs. 00887 float special_blobs_densities_[BSTT_COUNT]; 00888 }; 00889 00890 // Typedef it now in case it becomes a class later. 00891 typedef GridSearch<ColPartition, 00892 ColPartition_CLIST, 00893 ColPartition_C_IT> ColPartitionGridSearch; 00894 00895 } // namespace tesseract. 00896 00897 #endif // TESSERACT_TEXTORD_COLPARTITION_H__