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