Tesseract 3.01
/data/source/tesseract-ocr/textord/colpartition.h
Go to the documentation of this file.
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__
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines