tesseract 3.04.01

ccstruct/blobbox.h

Go to the documentation of this file.
00001 /**********************************************************************
00002  * File:        blobbox.h  (Formerly blobnbox.h)
00003  * Description: Code for the textord blob class.
00004  * Author:                                      Ray Smith
00005  * Created:                                     Thu Jul 30 09:08:51 BST 1992
00006  *
00007  * (C) Copyright 1992, Hewlett-Packard Ltd.
00008  ** Licensed under the Apache License, Version 2.0 (the "License");
00009  ** you may not use this file except in compliance with the License.
00010  ** You may obtain a copy of the License at
00011  ** http://www.apache.org/licenses/LICENSE-2.0
00012  ** Unless required by applicable law or agreed to in writing, software
00013  ** distributed under the License is distributed on an "AS IS" BASIS,
00014  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  ** See the License for the specific language governing permissions and
00016  ** limitations under the License.
00017  *
00018  **********************************************************************/
00019 
00020 #ifndef           BLOBBOX_H
00021 #define           BLOBBOX_H
00022 
00023 #include          "clst.h"
00024 #include          "elst2.h"
00025 #include          "werd.h"
00026 #include          "ocrblock.h"
00027 #include          "statistc.h"
00028 
00029 enum PITCH_TYPE
00030 {
00031   PITCH_DUNNO,                   // insufficient data
00032   PITCH_DEF_FIXED,               // definitely fixed
00033   PITCH_MAYBE_FIXED,             // could be
00034   PITCH_DEF_PROP,
00035   PITCH_MAYBE_PROP,
00036   PITCH_CORR_FIXED,
00037   PITCH_CORR_PROP
00038 };
00039 
00040 // The possible tab-stop types of each side of a BLOBNBOX.
00041 // The ordering is important, as it is used for deleting dead-ends in the
00042 // search. ALIGNED, CONFIRMED and VLINE should remain greater than the
00043 // non-aligned, unset, or deleted members.
00044 enum TabType {
00045   TT_NONE,           // Not a tab.
00046   TT_DELETED,        // Not a tab after detailed analysis.
00047   TT_MAYBE_RAGGED,   // Initial designation of a tab-stop candidate.
00048   TT_MAYBE_ALIGNED,  // Initial designation of a tab-stop candidate.
00049   TT_CONFIRMED,      // Aligned with neighbours.
00050   TT_VLINE           // Detected as a vertical line.
00051 };
00052 
00053 // The possible region types of a BLOBNBOX.
00054 // Note: keep all the text types > BRT_UNKNOWN and all the image types less.
00055 // Keep in sync with kBlobTypes in colpartition.cpp and BoxColor, and the
00056 // *Type static functions below.
00057 enum BlobRegionType {
00058   BRT_NOISE,      // Neither text nor image.
00059   BRT_HLINE,      // Horizontal separator line.
00060   BRT_VLINE,      // Vertical separator line.
00061   BRT_RECTIMAGE,  // Rectangular image.
00062   BRT_POLYIMAGE,  // Non-rectangular image.
00063   BRT_UNKNOWN,    // Not determined yet.
00064   BRT_VERT_TEXT,  // Vertical alignment, not necessarily vertically oriented.
00065   BRT_TEXT,       // Convincing text.
00066 
00067   BRT_COUNT       // Number of possibilities.
00068 };
00069 
00070 // enum for elements of arrays that refer to neighbours.
00071 // NOTE: keep in this order, so ^2 can be used to flip direction.
00072 enum BlobNeighbourDir {
00073   BND_LEFT,
00074   BND_BELOW,
00075   BND_RIGHT,
00076   BND_ABOVE,
00077   BND_COUNT
00078 };
00079 
00080 // enum for special type of text characters, such as math symbol or italic.
00081 enum BlobSpecialTextType {
00082   BSTT_NONE,  // No special.
00083   BSTT_ITALIC,  // Italic style.
00084   BSTT_DIGIT,  // Digit symbols.
00085   BSTT_MATH,  // Mathmatical symobls (not including digit).
00086   BSTT_UNCLEAR,  // Characters with low recognition rate.
00087   BSTT_SKIP,  // Characters that we skip labeling (usually too small).
00088   BSTT_COUNT
00089 };
00090 
00091 inline BlobNeighbourDir DirOtherWay(BlobNeighbourDir dir) {
00092   return static_cast<BlobNeighbourDir>(dir ^ 2);
00093 }
00094 
00095 // BlobTextFlowType indicates the quality of neighbouring information
00096 // related to a chain of connected components, either horizontally or
00097 // vertically. Also used by ColPartition for the collection of blobs
00098 // within, which should all have the same value in most cases.
00099 enum BlobTextFlowType {
00100   BTFT_NONE,           // No text flow set yet.
00101   BTFT_NONTEXT,        // Flow too poor to be likely text.
00102   BTFT_NEIGHBOURS,     // Neighbours support flow in this direction.
00103   BTFT_CHAIN,          // There is a weak chain of text in this direction.
00104   BTFT_STRONG_CHAIN,   // There is a strong chain of text in this direction.
00105   BTFT_TEXT_ON_IMAGE,  // There is a strong chain of text on an image.
00106   BTFT_LEADER,         // Leader dots/dashes etc.
00107   BTFT_COUNT
00108 };
00109 
00110 // Returns true if type1 dominates type2 in a merge. Mostly determined by the
00111 // ordering of the enum, LEADER is weak and dominates nothing.
00112 // The function is anti-symmetric (t1 > t2) === !(t2 > t1), except that
00113 // this cannot be true if t1 == t2, so the result is undefined.
00114 inline bool DominatesInMerge(BlobTextFlowType type1, BlobTextFlowType type2) {
00115   // LEADER always loses.
00116   if (type1 == BTFT_LEADER) return false;
00117   if (type2 == BTFT_LEADER) return true;
00118   // With those out of the way, the ordering of the enum determines the result.
00119   return type1 >= type2;
00120 }
00121 
00122 namespace tesseract {
00123 class ColPartition;
00124 }
00125 
00126 class BLOBNBOX;
00127 ELISTIZEH (BLOBNBOX)
00128 class BLOBNBOX:public ELIST_LINK
00129 {
00130   public:
00131     BLOBNBOX() {
00132       ConstructionInit();
00133     }
00134     explicit BLOBNBOX(C_BLOB *srcblob) {
00135       box = srcblob->bounding_box();
00136       ConstructionInit();
00137       cblob_ptr = srcblob;
00138       area = static_cast<int>(srcblob->area());
00139     }
00140     ~BLOBNBOX() {
00141       if (owns_cblob_) delete cblob_ptr;
00142     }
00143     static BLOBNBOX* RealBlob(C_OUTLINE* outline) {
00144       C_BLOB* blob = new C_BLOB(outline);
00145       return new BLOBNBOX(blob);
00146     }
00147 
00148     // Rotates the box and the underlying blob.
00149     void rotate(FCOORD rotation);
00150 
00151     // Methods that act on the box without touching the underlying blob.
00152     // Reflect the box in the y-axis, leaving the underlying blob untouched.
00153     void reflect_box_in_y_axis();
00154     // Rotates the box by the angle given by rotation.
00155     // If the blob is a diacritic, then only small rotations for skew
00156     // correction can be applied.
00157     void rotate_box(FCOORD rotation);
00158     // Moves just the box by the given vector.
00159     void translate_box(ICOORD v) {
00160       if (IsDiacritic()) {
00161         box.move(v);
00162         base_char_top_ += v.y();
00163         base_char_bottom_ += v.y();
00164       } else {
00165         box.move(v);
00166         set_diacritic_box(box);
00167       }
00168     }
00169     void merge(BLOBNBOX *nextblob);
00170     void really_merge(BLOBNBOX* other);
00171     void chop(                        // fake chop blob
00172               BLOBNBOX_IT *start_it,  // location of this
00173               BLOBNBOX_IT *blob_it,   // iterator
00174               FCOORD rotation,        // for landscape
00175               float xheight);         // line height
00176 
00177     void NeighbourGaps(int gaps[BND_COUNT]) const;
00178     void MinMaxGapsClipped(int* h_min, int* h_max,
00179                            int* v_min, int* v_max) const;
00180     void CleanNeighbours();
00181     // Returns positive if there is at least one side neighbour that has a
00182     // similar stroke width and is not on the other side of a rule line.
00183     int GoodTextBlob() const;
00184     // Returns the number of side neighbours that are of type BRT_NOISE.
00185     int NoisyNeighbours() const;
00186 
00187     // Returns true if the blob is noise and has no owner.
00188     bool DeletableNoise() const {
00189       return owner() == NULL && region_type() == BRT_NOISE;
00190     }
00191 
00192     // Returns true, and sets vert_possible/horz_possible if the blob has some
00193     // feature that makes it individually appear to flow one way.
00194     // eg if it has a high aspect ratio, yet has a complex shape, such as a
00195     // joined word in Latin, Arabic, or Hindi, rather than being a -, I, l, 1.
00196     bool DefiniteIndividualFlow();
00197 
00198     // Returns true if there is no tabstop violation in merging this and other.
00199     bool ConfirmNoTabViolation(const BLOBNBOX& other) const;
00200 
00201     // Returns true if other has a similar stroke width to this.
00202     bool MatchingStrokeWidth(const BLOBNBOX& other,
00203                              double fractional_tolerance,
00204                              double constant_tolerance) const;
00205 
00206     // Returns a bounding box of the outline contained within the
00207     // given horizontal range.
00208     TBOX BoundsWithinLimits(int left, int right);
00209 
00210     // Estimates and stores the baseline position based on the shape of the
00211     // outline.
00212     void EstimateBaselinePosition();
00213 
00214     // Simple accessors.
00215     const TBOX& bounding_box() const {
00216       return box;
00217     }
00218     // Set the bounding box. Use with caution.
00219     // Normally use compute_bounding_box instead.
00220     void set_bounding_box(const TBOX& new_box) {
00221       box = new_box;
00222       base_char_top_ = box.top();
00223       base_char_bottom_ = box.bottom();
00224     }
00225     void compute_bounding_box() {
00226       box = cblob_ptr->bounding_box();
00227       base_char_top_ = box.top();
00228       base_char_bottom_ = box.bottom();
00229       baseline_y_ = box.bottom();
00230     }
00231     const TBOX& reduced_box() const {
00232       return red_box;
00233     }
00234     void set_reduced_box(TBOX new_box) {
00235       red_box = new_box;
00236       reduced = TRUE;
00237     }
00238     inT32 enclosed_area() const {
00239       return area;
00240     }
00241     bool joined_to_prev() const {
00242       return joined != 0;
00243     }
00244     bool red_box_set() const {
00245       return reduced != 0;
00246     }
00247     int repeated_set() const {
00248       return repeated_set_;
00249     }
00250     void set_repeated_set(int set_id) {
00251       repeated_set_ = set_id;
00252     }
00253     C_BLOB *cblob() const {
00254       return cblob_ptr;
00255     }
00256     TabType left_tab_type() const {
00257       return left_tab_type_;
00258     }
00259     void set_left_tab_type(TabType new_type) {
00260       left_tab_type_ = new_type;
00261     }
00262     TabType right_tab_type() const {
00263       return right_tab_type_;
00264     }
00265     void set_right_tab_type(TabType new_type) {
00266       right_tab_type_ = new_type;
00267     }
00268     BlobRegionType region_type() const {
00269       return region_type_;
00270     }
00271     void set_region_type(BlobRegionType new_type) {
00272       region_type_ = new_type;
00273     }
00274     BlobSpecialTextType special_text_type() const {
00275       return spt_type_;
00276     }
00277     void set_special_text_type(BlobSpecialTextType new_type) {
00278       spt_type_ = new_type;
00279     }
00280     BlobTextFlowType flow() const {
00281       return flow_;
00282     }
00283     void set_flow(BlobTextFlowType value) {
00284       flow_ = value;
00285     }
00286     bool vert_possible() const {
00287       return vert_possible_;
00288     }
00289     void set_vert_possible(bool value) {
00290       vert_possible_ = value;
00291     }
00292     bool horz_possible() const {
00293       return horz_possible_;
00294     }
00295     void set_horz_possible(bool value) {
00296       horz_possible_ = value;
00297     }
00298     int left_rule() const {
00299       return left_rule_;
00300     }
00301     void set_left_rule(int new_left) {
00302       left_rule_ = new_left;
00303     }
00304     int right_rule() const {
00305       return right_rule_;
00306     }
00307     void set_right_rule(int new_right) {
00308       right_rule_ = new_right;
00309     }
00310     int left_crossing_rule() const {
00311       return left_crossing_rule_;
00312     }
00313     void set_left_crossing_rule(int new_left) {
00314       left_crossing_rule_ = new_left;
00315     }
00316     int right_crossing_rule() const {
00317       return right_crossing_rule_;
00318     }
00319     void set_right_crossing_rule(int new_right) {
00320       right_crossing_rule_ = new_right;
00321     }
00322     float horz_stroke_width() const {
00323       return horz_stroke_width_;
00324     }
00325     void set_horz_stroke_width(float width) {
00326       horz_stroke_width_ = width;
00327     }
00328     float vert_stroke_width() const {
00329       return vert_stroke_width_;
00330     }
00331     void set_vert_stroke_width(float width) {
00332       vert_stroke_width_ = width;
00333     }
00334     float area_stroke_width() const {
00335       return area_stroke_width_;
00336     }
00337     tesseract::ColPartition* owner() const {
00338       return owner_;
00339     }
00340     void set_owner(tesseract::ColPartition* new_owner) {
00341       owner_ = new_owner;
00342     }
00343     bool leader_on_left() const {
00344       return leader_on_left_;
00345     }
00346     void set_leader_on_left(bool flag) {
00347       leader_on_left_ = flag;
00348     }
00349     bool leader_on_right() const {
00350       return leader_on_right_;
00351     }
00352     void set_leader_on_right(bool flag) {
00353       leader_on_right_ = flag;
00354     }
00355     BLOBNBOX* neighbour(BlobNeighbourDir n) const {
00356       return neighbours_[n];
00357     }
00358     bool good_stroke_neighbour(BlobNeighbourDir n) const {
00359       return good_stroke_neighbours_[n];
00360     }
00361     void set_neighbour(BlobNeighbourDir n, BLOBNBOX* neighbour, bool good) {
00362       neighbours_[n] = neighbour;
00363       good_stroke_neighbours_[n] = good;
00364     }
00365     bool IsDiacritic() const {
00366       return base_char_top_ != box.top() || base_char_bottom_ != box.bottom();
00367     }
00368     int base_char_top() const {
00369       return base_char_top_;
00370     }
00371     int base_char_bottom() const {
00372       return base_char_bottom_;
00373     }
00374     int baseline_position() const {
00375       return baseline_y_;
00376     }
00377     int line_crossings() const {
00378       return line_crossings_;
00379     }
00380     void set_line_crossings(int value) {
00381       line_crossings_ = value;
00382     }
00383     void set_diacritic_box(const TBOX& diacritic_box) {
00384       base_char_top_ = diacritic_box.top();
00385       base_char_bottom_ = diacritic_box.bottom();
00386     }
00387     BLOBNBOX* base_char_blob() const {
00388       return base_char_blob_;
00389     }
00390     void set_base_char_blob(BLOBNBOX* blob) {
00391       base_char_blob_ = blob;
00392     }
00393     void set_owns_cblob(bool value) { owns_cblob_ = value; }
00394 
00395     bool UniquelyVertical() const {
00396       return vert_possible_ && !horz_possible_;
00397     }
00398     bool UniquelyHorizontal() const {
00399       return horz_possible_ && !vert_possible_;
00400     }
00401 
00402     // Returns true if the region type is text.
00403     static bool IsTextType(BlobRegionType type) {
00404       return type == BRT_TEXT || type == BRT_VERT_TEXT;
00405     }
00406     // Returns true if the region type is image.
00407     static bool IsImageType(BlobRegionType type) {
00408       return type == BRT_RECTIMAGE || type == BRT_POLYIMAGE;
00409     }
00410     // Returns true if the region type is line.
00411     static bool IsLineType(BlobRegionType type) {
00412       return type == BRT_HLINE || type == BRT_VLINE;
00413     }
00414     // Returns true if the region type cannot be merged.
00415     static bool UnMergeableType(BlobRegionType type) {
00416       return IsLineType(type) || IsImageType(type);
00417     }
00418     // Helper to call CleanNeighbours on all blobs on the list.
00419     static void CleanNeighbours(BLOBNBOX_LIST* blobs);
00420     // Helper to delete all the deletable blobs on the list.
00421     static void DeleteNoiseBlobs(BLOBNBOX_LIST* blobs);
00422     // Helper to compute edge offsets for  all the blobs on the list.
00423     // See coutln.h for an explanation of edge offsets.
00424     static void ComputeEdgeOffsets(Pix* thresholds, Pix* grey,
00425                                    BLOBNBOX_LIST* blobs);
00426 
00427 #ifndef GRAPHICS_DISABLED
00428     // Helper to draw all the blobs on the list in the given body_colour,
00429     // with child outlines in the child_colour.
00430     static void PlotBlobs(BLOBNBOX_LIST* list,
00431                           ScrollView::Color body_colour,
00432                           ScrollView::Color child_colour,
00433                           ScrollView* win);
00434     // Helper to draw only DeletableNoise blobs (unowned, BRT_NOISE) on the
00435     // given list in the given body_colour, with child outlines in the
00436     // child_colour.
00437     static void PlotNoiseBlobs(BLOBNBOX_LIST* list,
00438                                ScrollView::Color body_colour,
00439                                ScrollView::Color child_colour,
00440                                ScrollView* win);
00441 
00442     static ScrollView::Color TextlineColor(BlobRegionType region_type,
00443                                            BlobTextFlowType flow_type);
00444 
00445     // Keep in sync with BlobRegionType.
00446     ScrollView::Color BoxColor() const;
00447 
00448     void plot(ScrollView* window,                // window to draw in
00449               ScrollView::Color blob_colour,     // for outer bits
00450               ScrollView::Color child_colour);   // for holes
00451 #endif
00452 
00453   // Initializes the bulk of the members to default values for use at
00454   // construction time.
00455   void ConstructionInit() {
00456     cblob_ptr = NULL;
00457     owns_cblob_ = false;
00458     area = 0;
00459     area_stroke_width_ = 0.0f;
00460     horz_stroke_width_ = 0.0f;
00461     vert_stroke_width_ = 0.0f;
00462     ReInit();
00463   }
00464   // Initializes members set by StrokeWidth and beyond, without discarding
00465   // stored area and strokewidth values, which are expensive to calculate.
00466   void ReInit() {
00467     joined = false;
00468     reduced = false;
00469     repeated_set_ = 0;
00470     left_tab_type_ = TT_NONE;
00471     right_tab_type_ = TT_NONE;
00472     region_type_ = BRT_UNKNOWN;
00473     flow_ = BTFT_NONE;
00474     spt_type_ = BSTT_SKIP;
00475     left_rule_ = 0;
00476     right_rule_ = 0;
00477     left_crossing_rule_ = 0;
00478     right_crossing_rule_ = 0;
00479     if (area_stroke_width_ == 0.0f && area > 0 && cblob() != NULL)
00480       area_stroke_width_ = 2.0f * area / cblob()->perimeter();
00481     owner_ = NULL;
00482     base_char_top_ = box.top();
00483     base_char_bottom_ = box.bottom();
00484     baseline_y_ = box.bottom();
00485     line_crossings_ = 0;
00486     base_char_blob_ = NULL;
00487     horz_possible_ = false;
00488     vert_possible_ = false;
00489     leader_on_left_ = false;
00490     leader_on_right_ = false;
00491     ClearNeighbours();
00492   }
00493 
00494   void ClearNeighbours() {
00495     for (int n = 0; n < BND_COUNT; ++n) {
00496       neighbours_[n] = NULL;
00497       good_stroke_neighbours_[n] = false;
00498     }
00499   }
00500 
00501  private:
00502   C_BLOB *cblob_ptr;            // edgestep blob
00503   TBOX box;                     // bounding box
00504   TBOX red_box;                 // bounding box
00505   int area:30;                  // enclosed area
00506   int joined:1;                 // joined to prev
00507   int reduced:1;                // reduced box set
00508   int repeated_set_;            // id of the set of repeated blobs
00509   TabType left_tab_type_;       // Indicates tab-stop assessment
00510   TabType right_tab_type_;      // Indicates tab-stop assessment
00511   BlobRegionType region_type_;  // Type of region this blob belongs to
00512   BlobTextFlowType flow_;       // Quality of text flow.
00513   inT16 left_rule_;             // x-coord of nearest but not crossing rule line
00514   inT16 right_rule_;            // x-coord of nearest but not crossing rule line
00515   inT16 left_crossing_rule_;    // x-coord of nearest or crossing rule line
00516   inT16 right_crossing_rule_;   // x-coord of nearest or crossing rule line
00517   inT16 base_char_top_;         // y-coord of top/bottom of diacritic base,
00518   inT16 base_char_bottom_;      // if it exists else top/bottom of this blob.
00519   inT16 baseline_y_;            // Estimate of baseline position.
00520   int line_crossings_;          // Number of line intersections touched.
00521   BLOBNBOX* base_char_blob_;    // The blob that was the base char.
00522   float horz_stroke_width_;     // Median horizontal stroke width
00523   float vert_stroke_width_;     // Median vertical stroke width
00524   float area_stroke_width_;     // Stroke width from area/perimeter ratio.
00525   tesseract::ColPartition* owner_;  // Who will delete me when I am not needed
00526   BlobSpecialTextType spt_type_;   // Special text type.
00527   BLOBNBOX* neighbours_[BND_COUNT];
00528   bool good_stroke_neighbours_[BND_COUNT];
00529   bool horz_possible_;           // Could be part of horizontal flow.
00530   bool vert_possible_;           // Could be part of vertical flow.
00531   bool leader_on_left_;          // There is a leader to the left.
00532   bool leader_on_right_;         // There is a leader to the right.
00533   // Iff true, then the destructor should delete the cblob_ptr.
00534   // TODO(rays) migrate all uses to correctly setting this flag instead of
00535   // deleting the C_BLOB before deleting the BLOBNBOX.
00536   bool owns_cblob_;
00537 };
00538 
00539 class TO_ROW: public ELIST2_LINK
00540 {
00541   public:
00542     static const int kErrorWeight = 3;
00543 
00544     TO_ROW() {
00545       clear();
00546     }                            //empty
00547     TO_ROW(                 //constructor
00548            BLOBNBOX *blob,  //from first blob
00549            float top,       //of row //target height
00550            float bottom,
00551            float row_size);
00552 
00553     void print() const;
00554     float max_y() const {  //access function
00555       return y_max;
00556     }
00557     float min_y() const {
00558       return y_min;
00559     }
00560     float mean_y() const {
00561       return (y_min + y_max) / 2.0f;
00562     }
00563     float initial_min_y() const {
00564       return initial_y_min;
00565     }
00566     float line_m() const {  //access to line fit
00567       return m;
00568     }
00569     float line_c() const {
00570       return c;
00571     }
00572     float line_error() const {
00573       return error;
00574     }
00575     float parallel_c() const {
00576       return para_c;
00577     }
00578     float parallel_error() const {
00579       return para_error;
00580     }
00581     float believability() const {  //baseline goodness
00582       return credibility;
00583     }
00584     float intercept() const {  //real parallel_c
00585       return y_origin;
00586     }
00587     void add_blob(                 //put in row
00588                   BLOBNBOX *blob,  //blob to add
00589                   float top,       //of row //target height
00590                   float bottom,
00591                   float row_size);
00592     void insert_blob(  //put in row in order
00593                      BLOBNBOX *blob);
00594 
00595     BLOBNBOX_LIST *blob_list() {  //get list
00596       return &blobs;
00597     }
00598 
00599     void set_line(              //set line spec
00600                   float new_m,  //line to set
00601                   float new_c,
00602                   float new_error) {
00603       m = new_m;
00604       c = new_c;
00605       error = new_error;
00606     }
00607     void set_parallel_line(                 //set fixed gradient line
00608                            float gradient,  //page gradient
00609                            float new_c,
00610                            float new_error) {
00611       para_c = new_c;
00612       para_error = new_error;
00613       credibility =
00614         (float) (blobs.length () - kErrorWeight * new_error);
00615       y_origin = (float) (new_c / sqrt (1 + gradient * gradient));
00616       //real intercept
00617     }
00618     void set_limits(                  //set min,max
00619                     float new_min,    //bottom and
00620                     float new_max) {  //top of row
00621       y_min = new_min;
00622       y_max = new_max;
00623     }
00624     void compute_vertical_projection();
00625     //get projection
00626 
00627     bool rep_chars_marked() const {
00628       return num_repeated_sets_ != -1;
00629     }
00630     void clear_rep_chars_marked() {
00631       num_repeated_sets_ = -1;
00632     }
00633     int num_repeated_sets() const {
00634       return num_repeated_sets_;
00635     }
00636     void set_num_repeated_sets(int num_sets) {
00637       num_repeated_sets_ = num_sets;
00638     }
00639 
00640                                  // true when dead
00641     BOOL8 merged;
00642     BOOL8 all_caps;              // had no ascenders
00643     BOOL8 used_dm_model;         // in guessing pitch
00644     inT16 projection_left;       // start of projection
00645     inT16 projection_right;      // start of projection
00646     PITCH_TYPE pitch_decision;   // how strong is decision
00647     float fixed_pitch;           // pitch or 0
00648     float fp_space;              // sp if fixed pitch
00649     float fp_nonsp;              // nonsp if fixed pitch
00650     float pr_space;              // sp if prop
00651     float pr_nonsp;              // non sp if prop
00652     float spacing;               // to "next" row
00653     float xheight;               // of line
00654     int xheight_evidence;        // number of blobs of height xheight
00655     float ascrise;               // ascenders
00656     float descdrop;              // descenders
00657     float body_size;             // of CJK characters.  Assumed to be
00658                                  // xheight+ascrise for non-CJK text.
00659     inT32 min_space;             // min size for real space
00660     inT32 max_nonspace;          // max size of non-space
00661     inT32 space_threshold;       // space vs nonspace
00662     float kern_size;             // average non-space
00663     float space_size;            // average space
00664     WERD_LIST rep_words;         // repeated chars
00665     ICOORDELT_LIST char_cells;   // fixed pitch cells
00666     QSPLINE baseline;            // curved baseline
00667     STATS projection;            // vertical projection
00668 
00669   private:
00670     void clear();  // clear all values to reasonable defaults
00671 
00672     BLOBNBOX_LIST blobs;         //blobs in row
00673     float y_min;                 //coords
00674     float y_max;
00675     float initial_y_min;
00676     float m, c;                  //line spec
00677     float error;                 //line error
00678     float para_c;                //constrained fit
00679     float para_error;
00680     float y_origin;              //rotated para_c;
00681     float credibility;           //baseline believability
00682     int num_repeated_sets_;      // number of sets of repeated blobs
00683                                  // set to -1 if we have not searched
00684                                  // for repeated blobs in this row yet
00685 };
00686 
00687 ELIST2IZEH (TO_ROW)
00688 class TO_BLOCK:public ELIST_LINK
00689 {
00690   public:
00691     TO_BLOCK() : pitch_decision(PITCH_DUNNO) {
00692       clear();
00693     }                            //empty
00694     TO_BLOCK(                    //constructor
00695              BLOCK *src_block);  //real block
00696     ~TO_BLOCK();
00697 
00698     void clear();  // clear all scalar members.
00699 
00700     TO_ROW_LIST *get_rows() {  //access function
00701       return &row_list;
00702     }
00703 
00704     // Rotate all the blobnbox lists and the underlying block. Then update the
00705     // median size statistic from the blobs list.
00706     void rotate(const FCOORD& rotation) {
00707       BLOBNBOX_LIST* blobnbox_list[] = {&blobs, &underlines, &noise_blobs,
00708                                         &small_blobs, &large_blobs, NULL};
00709       for (BLOBNBOX_LIST** list = blobnbox_list; *list != NULL; ++list) {
00710         BLOBNBOX_IT it(*list);
00711         for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
00712           it.data()->rotate(rotation);
00713         }
00714       }
00715       // Rotate the block
00716       ASSERT_HOST(block->poly_block() != NULL);
00717       block->rotate(rotation);
00718       // Update the median size statistic from the blobs list.
00719       STATS widths(0, block->bounding_box().width());
00720       STATS heights(0, block->bounding_box().height());
00721       BLOBNBOX_IT blob_it(&blobs);
00722       for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
00723         widths.add(blob_it.data()->bounding_box().width(), 1);
00724         heights.add(blob_it.data()->bounding_box().height(), 1);
00725       }
00726       block->set_median_size(static_cast<int>(widths.median() + 0.5),
00727                              static_cast<int>(heights.median() + 0.5));
00728     }
00729 
00730     void print_rows() {  //debug info
00731       TO_ROW_IT row_it = &row_list;
00732       TO_ROW *row;
00733 
00734       for (row_it.mark_cycle_pt(); !row_it.cycled_list();
00735            row_it.forward()) {
00736         row = row_it.data();
00737         tprintf("Row range (%g,%g), para_c=%g, blobcount=" INT32FORMAT
00738                 "\n", row->min_y(), row->max_y(), row->parallel_c(),
00739                 row->blob_list()->length());
00740       }
00741     }
00742 
00743     // Reorganizes the blob lists with a different definition of small, medium
00744     // and large, compared to the original definition.
00745     // Height is still the primary filter key, but medium width blobs of small
00746     // height become medium, and very wide blobs of small height stay small.
00747     void ReSetAndReFilterBlobs();
00748 
00749     // Deletes noise blobs from all lists where not owned by a ColPartition.
00750     void DeleteUnownedNoise();
00751 
00752     // Computes and stores the edge offsets on each blob for use in feature
00753     // extraction, using greyscale if the supplied grey and thresholds pixes
00754     // are 8-bit or otherwise (if NULL or not 8 bit) the original binary
00755     // edge step outlines.
00756     // Thresholds must either be the same size as grey or an integer down-scale
00757     // of grey.
00758     // See coutln.h for an explanation of edge offsets.
00759     void ComputeEdgeOffsets(Pix* thresholds, Pix* grey);
00760 
00761 #ifndef GRAPHICS_DISABLED
00762     // Draw the noise blobs from all lists in red.
00763     void plot_noise_blobs(ScrollView* to_win);
00764     // Draw the blobs on on the various lists in the block in different colors.
00765     void plot_graded_blobs(ScrollView* to_win);
00766 #endif
00767 
00768     BLOBNBOX_LIST blobs;         //medium size
00769     BLOBNBOX_LIST underlines;    //underline blobs
00770     BLOBNBOX_LIST noise_blobs;   //very small
00771     BLOBNBOX_LIST small_blobs;   //fairly small
00772     BLOBNBOX_LIST large_blobs;   //big blobs
00773     BLOCK *block;                //real block
00774     PITCH_TYPE pitch_decision;   //how strong is decision
00775     float line_spacing;          //estimate
00776     // line_size is a lower-bound estimate of the font size in pixels of
00777     // the text in the block (with ascenders and descenders), being a small
00778     // (1.25) multiple of the median height of filtered blobs.
00779     // In most cases the font size will be bigger, but it will be closer
00780     // if the text is allcaps, or in a no-x-height script.
00781     float line_size;             //estimate
00782     float max_blob_size;         //line assignment limit
00783     float baseline_offset;       //phase shift
00784     float xheight;               //median blob size
00785     float fixed_pitch;           //pitch or 0
00786     float kern_size;             //average non-space
00787     float space_size;            //average space
00788     inT32 min_space;             //min definite space
00789     inT32 max_nonspace;          //max definite
00790     float fp_space;              //sp if fixed pitch
00791     float fp_nonsp;              //nonsp if fixed pitch
00792     float pr_space;              //sp if prop
00793     float pr_nonsp;              //non sp if prop
00794     TO_ROW *key_row;             //starting row
00795 
00796    private:
00797     TO_ROW_LIST row_list;        //temporary rows
00798 };
00799 
00800 ELISTIZEH (TO_BLOCK)
00801 extern double_VAR_H (textord_error_weight, 3,
00802 "Weighting for error in believability");
00803 void find_cblob_limits(                  //get y limits
00804                        C_BLOB *blob,     //blob to search
00805                        float leftx,      //x limits
00806                        float rightx,
00807                        FCOORD rotation,  //for landscape
00808                        float &ymin,      //output y limits
00809                        float &ymax);
00810 void find_cblob_vlimits(               //get y limits
00811                         C_BLOB *blob,  //blob to search
00812                         float leftx,   //x limits
00813                         float rightx,
00814                         float &ymin,   //output y limits
00815                         float &ymax);
00816 void find_cblob_hlimits(                //get x limits
00817                         C_BLOB *blob,   //blob to search
00818                         float bottomy,  //y limits
00819                         float topy,
00820                         float &xmin,    //output x limits
00821                         float &xymax);
00822 C_BLOB *crotate_cblob(                 //rotate it
00823                       C_BLOB *blob,    //blob to search
00824                       FCOORD rotation  //for landscape
00825                      );
00826 TBOX box_next(                 //get bounding box
00827              BLOBNBOX_IT *it  //iterator to blobds
00828             );
00829 TBOX box_next_pre_chopped(                 //get bounding box
00830                          BLOBNBOX_IT *it  //iterator to blobds
00831                         );
00832 void vertical_cblob_projection(               //project outlines
00833                                C_BLOB *blob,  //blob to project
00834                                STATS *stats   //output
00835                               );
00836 void vertical_coutline_projection(                     //project outlines
00837                                   C_OUTLINE *outline,  //outline to project
00838                                   STATS *stats         //output
00839                                  );
00840 #ifndef GRAPHICS_DISABLED
00841 void plot_blob_list(ScrollView* win,                   // window to draw in
00842                     BLOBNBOX_LIST *list,               // blob list
00843                     ScrollView::Color body_colour,     // colour to draw
00844                     ScrollView::Color child_colour);   // colour of child
00845 #endif  // GRAPHICS_DISABLED
00846 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines