tesseract 3.04.01

ccstruct/blobs.h

Go to the documentation of this file.
00001 /* -*-C-*-
00002  ********************************************************************************
00003  *
00004  * File:        blobs.h  (Formerly blobs.h)
00005  * Description:  Blob definition
00006  * Author:       Mark Seaman, OCR Technology
00007  * Created:      Fri Oct 27 15:39:52 1989
00008  * Modified:     Thu Mar 28 15:33:38 1991 (Mark Seaman) marks@hpgrlt
00009  * Language:     C
00010  * Package:      N/A
00011  * Status:       Experimental (Do Not Distribute)
00012  *
00013  * (c) Copyright 1989, Hewlett-Packard Company.
00014  ** Licensed under the Apache License, Version 2.0 (the "License");
00015  ** you may not use this file except in compliance with the License.
00016  ** You may obtain a copy of the License at
00017  ** http://www.apache.org/licenses/LICENSE-2.0
00018  ** Unless required by applicable law or agreed to in writing, software
00019  ** distributed under the License is distributed on an "AS IS" BASIS,
00020  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00021  ** See the License for the specific language governing permissions and
00022  ** limitations under the License.
00023  *
00024  *********************************************************************************/
00025 
00026 #ifndef BLOBS_H
00027 #define BLOBS_H
00028 
00029 /*----------------------------------------------------------------------
00030               I n c l u d e s
00031 ----------------------------------------------------------------------*/
00032 #include "clst.h"
00033 #include "normalis.h"
00034 #include "publictypes.h"
00035 #include "rect.h"
00036 #include "vecfuncs.h"
00037 
00038 class BLOCK;
00039 class C_BLOB;
00040 class C_OUTLINE;
00041 class LLSQ;
00042 class ROW;
00043 class WERD;
00044 
00045 /*----------------------------------------------------------------------
00046               T y p e s
00047 ----------------------------------------------------------------------*/
00048 #define EDGEPTFLAGS     4        /*concavity,length etc. */
00049 
00050 struct TPOINT {
00051   TPOINT(): x(0), y(0) {}
00052   TPOINT(inT16 vx, inT16 vy) : x(vx), y(vy) {}
00053   TPOINT(const ICOORD &ic) : x(ic.x()), y(ic.y()) {}
00054 
00055   void operator+=(const TPOINT& other) {
00056     x += other.x;
00057     y += other.y;
00058   }
00059   void operator/=(int divisor) {
00060     x /= divisor;
00061     y /= divisor;
00062   }
00063   bool operator==(const TPOINT& other) const {
00064     return x == other.x && y == other.y;
00065   }
00066   // Returns true when the two line segments cross each other.
00067   // (Moved from outlines.cpp).
00068   static bool IsCrossed(const TPOINT& a0, const TPOINT& a1, const TPOINT& b0,
00069                         const TPOINT& b1);
00070 
00071   inT16 x;                       // absolute x coord.
00072   inT16 y;                       // absolute y coord.
00073 };
00074 typedef TPOINT VECTOR;           // structure for coordinates.
00075 
00076 struct EDGEPT {
00077   EDGEPT()
00078   : next(NULL), prev(NULL), src_outline(NULL), start_step(0), step_count(0) {
00079     memset(flags, 0, EDGEPTFLAGS * sizeof(flags[0]));
00080   }
00081   EDGEPT(const EDGEPT& src) : next(NULL), prev(NULL) {
00082     CopyFrom(src);
00083   }
00084   EDGEPT& operator=(const EDGEPT& src) {
00085     CopyFrom(src);
00086     return *this;
00087   }
00088   // Copies the data elements, but leaves the pointers untouched.
00089   void CopyFrom(const EDGEPT& src) {
00090     pos = src.pos;
00091     vec = src.vec;
00092     memcpy(flags, src.flags, EDGEPTFLAGS * sizeof(flags[0]));
00093     src_outline = src.src_outline;
00094     start_step = src.start_step;
00095     step_count = src.step_count;
00096   }
00097   // Returns the squared distance between the points, with the x-component
00098   // weighted by x_factor.
00099   int WeightedDistance(const EDGEPT& other, int x_factor) const {
00100     int x_dist = pos.x - other.pos.x;
00101     int y_dist = pos.y - other.pos.y;
00102     return x_dist * x_dist * x_factor + y_dist * y_dist;
00103   }
00104   // Returns true if the positions are equal.
00105   bool EqualPos(const EDGEPT& other) const { return pos == other.pos; }
00106   // Returns the bounding box of the outline segment from *this to *end.
00107   // Ignores hidden edge flags.
00108   TBOX SegmentBox(const EDGEPT* end) const {
00109     TBOX box(pos.x, pos.y, pos.x, pos.y);
00110     const EDGEPT* pt = this;
00111     do {
00112       pt = pt->next;
00113       if (pt->pos.x < box.left()) box.set_left(pt->pos.x);
00114       if (pt->pos.x > box.right()) box.set_right(pt->pos.x);
00115       if (pt->pos.y < box.bottom()) box.set_bottom(pt->pos.y);
00116       if (pt->pos.y > box.top()) box.set_top(pt->pos.y);
00117     } while (pt != end && pt != this);
00118     return box;
00119   }
00120   // Returns the area of the outline segment from *this to *end.
00121   // Ignores hidden edge flags.
00122   int SegmentArea(const EDGEPT* end) const {
00123     int area = 0;
00124     const EDGEPT* pt = this->next;
00125     do {
00126       TPOINT origin_vec(pt->pos.x - pos.x, pt->pos.y - pos.y);
00127       area += CROSS(origin_vec, pt->vec);
00128       pt = pt->next;
00129     } while (pt != end && pt != this);
00130     return area;
00131   }
00132   // Returns true if the number of points in the outline segment from *this to
00133   // *end is less that min_points and false if we get back to *this first.
00134   // Ignores hidden edge flags.
00135   bool ShortNonCircularSegment(int min_points, const EDGEPT* end) const {
00136     int count = 0;
00137     const EDGEPT* pt = this;
00138     do {
00139       if (pt == end) return true;
00140       pt = pt->next;
00141       ++count;
00142     } while (pt != this && count <= min_points);
00143     return false;
00144   }
00145 
00146   // Accessors to hide or reveal a cut edge from feature extractors.
00147   void Hide() {
00148     flags[0] = true;
00149   }
00150   void Reveal() {
00151     flags[0] = false;
00152   }
00153   bool IsHidden() const {
00154     return flags[0] != 0;
00155   }
00156   void MarkChop() {
00157     flags[2] = true;
00158   }
00159   bool IsChopPt() const {
00160     return flags[2] != 0;
00161   }
00162 
00163   TPOINT pos;                    // position
00164   VECTOR vec;                    // vector to next point
00165   // TODO(rays) Remove flags and replace with
00166   // is_hidden, runlength, dir, and fixed. The only use
00167   // of the flags other than is_hidden is in polyaprx.cpp.
00168   char flags[EDGEPTFLAGS];       // concavity, length etc
00169   EDGEPT* next;                  // anticlockwise element
00170   EDGEPT* prev;                  // clockwise element
00171   C_OUTLINE* src_outline;        // Outline it came from.
00172   // The following fields are not used if src_outline is NULL.
00173   int start_step;                // Location of pos in src_outline.
00174   int step_count;                // Number of steps used (may wrap around).
00175 };
00176 
00177 // For use in chop and findseam to keep a list of which EDGEPTs were inserted.
00178 CLISTIZEH(EDGEPT);
00179 
00180 struct TESSLINE {
00181   TESSLINE() : is_hole(false), loop(NULL), next(NULL) {}
00182   TESSLINE(const TESSLINE& src) : loop(NULL), next(NULL) {
00183     CopyFrom(src);
00184   }
00185   ~TESSLINE() {
00186     Clear();
00187   }
00188   TESSLINE& operator=(const TESSLINE& src) {
00189     CopyFrom(src);
00190     return *this;
00191   }
00192   // Consume the circular list of EDGEPTs to make a TESSLINE.
00193   static TESSLINE* BuildFromOutlineList(EDGEPT* outline);
00194   // Copies the data and the outline, but leaves next untouched.
00195   void CopyFrom(const TESSLINE& src);
00196   // Deletes owned data.
00197   void Clear();
00198   // Normalize in-place using the DENORM.
00199   void Normalize(const DENORM& denorm);
00200   // Rotates by the given rotation in place.
00201   void Rotate(const FCOORD rotation);
00202   // Moves by the given vec in place.
00203   void Move(const ICOORD vec);
00204   // Scales by the given factor in place.
00205   void Scale(float factor);
00206   // Sets up the start and vec members of the loop from the pos members.
00207   void SetupFromPos();
00208   // Recomputes the bounding box from the points in the loop.
00209   void ComputeBoundingBox();
00210   // Computes the min and max cross product of the outline points with the
00211   // given vec and returns the results in min_xp and max_xp. Geometrically
00212   // this is the left and right edge of the outline perpendicular to the
00213   // given direction, but to get the distance units correct, you would
00214   // have to divide by the modulus of vec.
00215   void MinMaxCrossProduct(const TPOINT vec, int* min_xp, int* max_xp) const;
00216 
00217   TBOX bounding_box() const;
00218   // Returns true if *this and other have equal bounding boxes.
00219   bool SameBox(const TESSLINE& other) const {
00220     return topleft == other.topleft && botright == other.botright;
00221   }
00222   // Returns true if the given line segment crosses any outline of this blob.
00223   bool SegmentCrosses(const TPOINT& pt1, const TPOINT& pt2) const {
00224     if (Contains(pt1) && Contains(pt2)) {
00225       EDGEPT* pt = loop;
00226       do {
00227         if (TPOINT::IsCrossed(pt1, pt2, pt->pos, pt->next->pos)) return true;
00228         pt = pt->next;
00229       } while (pt != loop);
00230     }
00231     return false;
00232   }
00233   // Returns true if the point is contained within the outline box.
00234   bool Contains(const TPOINT& pt) const {
00235     return topleft.x <= pt.x && pt.x <= botright.x &&
00236            botright.y <= pt.y && pt.y <= topleft.y;
00237   }
00238 
00239   #ifndef GRAPHICS_DISABLED
00240   void plot(ScrollView* window, ScrollView::Color color,
00241             ScrollView::Color child_color);
00242   #endif  // GRAPHICS_DISABLED
00243 
00244   // Returns the first outline point that has a different src_outline to its
00245   // predecessor, or, if all the same, the lowest indexed point.
00246   EDGEPT* FindBestStartPt() const;
00247 
00248 
00249   int BBArea() const {
00250     return (botright.x - topleft.x) * (topleft.y - botright.y);
00251   }
00252 
00253   TPOINT topleft;                // Top left of loop.
00254   TPOINT botright;               // Bottom right of loop.
00255   TPOINT start;                  // Start of loop.
00256   bool is_hole;                  // True if this is a hole/child outline.
00257   EDGEPT *loop;                  // Edgeloop.
00258   TESSLINE *next;                // Next outline in blob.
00259 };                               // Outline structure.
00260 
00261 struct TBLOB {
00262   TBLOB() : outlines(NULL) {}
00263   TBLOB(const TBLOB& src) : outlines(NULL) {
00264     CopyFrom(src);
00265   }
00266   ~TBLOB() {
00267     Clear();
00268   }
00269   TBLOB& operator=(const TBLOB& src) {
00270     CopyFrom(src);
00271     return *this;
00272   }
00273   // Factory to build a TBLOB from a C_BLOB with polygonal approximation along
00274   // the way. If allow_detailed_fx is true, the EDGEPTs in the returned TBLOB
00275   // contain pointers to the input C_OUTLINEs that enable higher-resolution
00276   // feature extraction that does not use the polygonal approximation.
00277   static TBLOB* PolygonalCopy(bool allow_detailed_fx, C_BLOB* src);
00278   // Factory builds a blob with no outlines, but copies the other member data.
00279   static TBLOB* ShallowCopy(const TBLOB& src);
00280   // Normalizes the blob for classification only if needed.
00281   // (Normally this means a non-zero classify rotation.)
00282   // If no Normalization is needed, then NULL is returned, and the input blob
00283   // can be used directly. Otherwise a new TBLOB is returned which must be
00284   // deleted after use.
00285   TBLOB* ClassifyNormalizeIfNeeded() const;
00286 
00287   // Copies the data and the outlines, but leaves next untouched.
00288   void CopyFrom(const TBLOB& src);
00289   // Deletes owned data.
00290   void Clear();
00291   // Sets up the built-in DENORM and normalizes the blob in-place.
00292   // For parameters see DENORM::SetupNormalization, plus the inverse flag for
00293   // this blob and the Pix for the full image.
00294   void Normalize(const BLOCK* block,
00295                  const FCOORD* rotation,
00296                  const DENORM* predecessor,
00297                  float x_origin, float y_origin,
00298                  float x_scale, float y_scale,
00299                  float final_xshift, float final_yshift,
00300                  bool inverse, Pix* pix);
00301   // Rotates by the given rotation in place.
00302   void Rotate(const FCOORD rotation);
00303   // Moves by the given vec in place.
00304   void Move(const ICOORD vec);
00305   // Scales by the given factor in place.
00306   void Scale(float factor);
00307   // Recomputes the bounding boxes of the outlines.
00308   void ComputeBoundingBoxes();
00309 
00310   // Returns the number of outlines.
00311   int NumOutlines() const;
00312 
00313   TBOX bounding_box() const;
00314 
00315   // Returns true if the given line segment crosses any outline of this blob.
00316   bool SegmentCrossesOutline(const TPOINT& pt1, const TPOINT& pt2) const {
00317     for (const TESSLINE* outline = outlines; outline != NULL;
00318          outline = outline->next) {
00319       if (outline->SegmentCrosses(pt1, pt2)) return true;
00320     }
00321     return false;
00322   }
00323   // Returns true if the point is contained within any of the outline boxes.
00324   bool Contains(const TPOINT& pt) const {
00325     for (const TESSLINE* outline = outlines; outline != NULL;
00326          outline = outline->next) {
00327       if (outline->Contains(pt)) return true;
00328     }
00329     return false;
00330   }
00331 
00332   // Finds and deletes any duplicate outlines in this blob, without deleting
00333   // their EDGEPTs.
00334   void EliminateDuplicateOutlines();
00335 
00336   // Swaps the outlines of *this and next if needed to keep the centers in
00337   // increasing x.
00338   void CorrectBlobOrder(TBLOB* next);
00339 
00340   const DENORM& denorm() const {
00341     return denorm_;
00342   }
00343 
00344   #ifndef GRAPHICS_DISABLED
00345   void plot(ScrollView* window, ScrollView::Color color,
00346             ScrollView::Color child_color);
00347   #endif  // GRAPHICS_DISABLED
00348 
00349   int BBArea() const {
00350     int total_area = 0;
00351     for (TESSLINE* outline = outlines; outline != NULL; outline = outline->next)
00352       total_area += outline->BBArea();
00353     return total_area;
00354   }
00355 
00356   // Computes the center of mass and second moments for the old baseline and
00357   // 2nd moment normalizations. Returns the outline length.
00358   // The input denorm should be the normalizations that have been applied from
00359   // the image to the current state of this TBLOB.
00360   int ComputeMoments(FCOORD* center, FCOORD* second_moments) const;
00361   // Computes the precise bounding box of the coords that are generated by
00362   // GetEdgeCoords. This may be different from the bounding box of the polygon.
00363   void GetPreciseBoundingBox(TBOX* precise_box) const;
00364   // Adds edges to the given vectors.
00365   // For all the edge steps in all the outlines, or polygonal approximation
00366   // where there are no edge steps, collects the steps into x_coords/y_coords.
00367   // x_coords is a collection of the x-coords of vertical edges for each
00368   // y-coord starting at box.bottom().
00369   // y_coords is a collection of the y-coords of horizontal edges for each
00370   // x-coord starting at box.left().
00371   // Eg x_coords[0] is a collection of the x-coords of edges at y=bottom.
00372   // Eg x_coords[1] is a collection of the x-coords of edges at y=bottom + 1.
00373   void GetEdgeCoords(const TBOX& box,
00374                      GenericVector<GenericVector<int> >* x_coords,
00375                      GenericVector<GenericVector<int> >* y_coords) const;
00376 
00377   TESSLINE *outlines;            // List of outlines in blob.
00378 
00379  private:  // TODO(rays) Someday the data members will be private too.
00380   // For all the edge steps in all the outlines, or polygonal approximation
00381   // where there are no edge steps, collects the steps into the bounding_box,
00382   // llsq and/or the x_coords/y_coords. Both are used in different kinds of
00383   // normalization.
00384   // For a description of x_coords, y_coords, see GetEdgeCoords above.
00385   void CollectEdges(const TBOX& box,
00386                     TBOX* bounding_box, LLSQ* llsq,
00387                     GenericVector<GenericVector<int> >* x_coords,
00388                     GenericVector<GenericVector<int> >* y_coords) const;
00389 
00390  private:
00391   // DENORM indicating the transformations that this blob has undergone so far.
00392   DENORM denorm_;
00393 };                               // Blob structure.
00394 
00395 struct TWERD {
00396   TWERD() : latin_script(false) {}
00397   TWERD(const TWERD& src) {
00398     CopyFrom(src);
00399   }
00400   ~TWERD() {
00401     Clear();
00402   }
00403   TWERD& operator=(const TWERD& src) {
00404     CopyFrom(src);
00405     return *this;
00406   }
00407   // Factory to build a TWERD from a (C_BLOB) WERD, with polygonal
00408   // approximation along the way.
00409   static TWERD* PolygonalCopy(bool allow_detailed_fx, WERD* src);
00410   // Baseline normalizes the blobs in-place, recording the normalization in the
00411   // DENORMs in the blobs.
00412   void BLNormalize(const BLOCK* block, const ROW* row, Pix* pix, bool inverse,
00413                    float x_height, float baseline_shift, bool numeric_mode,
00414                    tesseract::OcrEngineMode hint,
00415                    const TBOX* norm_box,
00416                    DENORM* word_denorm);
00417   // Copies the data and the blobs, but leaves next untouched.
00418   void CopyFrom(const TWERD& src);
00419   // Deletes owned data.
00420   void Clear();
00421   // Recomputes the bounding boxes of the blobs.
00422   void ComputeBoundingBoxes();
00423 
00424   // Returns the number of blobs in the word.
00425   int NumBlobs() const {
00426     return blobs.size();
00427   }
00428   TBOX bounding_box() const;
00429 
00430   // Merges the blobs from start to end, not including end, and deletes
00431   // the blobs between start and end.
00432   void MergeBlobs(int start, int end);
00433 
00434   void plot(ScrollView* window);
00435 
00436   GenericVector<TBLOB*> blobs;   // Blobs in word.
00437   bool latin_script;             // This word is in a latin-based script.
00438 };
00439 
00440 /*----------------------------------------------------------------------
00441               M a c r o s
00442 ----------------------------------------------------------------------*/
00443 /**********************************************************************
00444  * free_widths
00445  *
00446  * Free the memory taken up by a width array.
00447  **********************************************************************/
00448 #define free_widths(w)  \
00449 if (w) memfree (w)
00450 
00451 /*----------------------------------------------------------------------
00452               F u n c t i o n s
00453 ----------------------------------------------------------------------*/
00454 // TODO(rays) Make divisible_blob and divide_blobs members of TBLOB.
00455 bool divisible_blob(TBLOB *blob, bool italic_blob, TPOINT* location);
00456 
00457 void divide_blobs(TBLOB *blob, TBLOB *other_blob, bool italic_blob,
00458                   const TPOINT& location);
00459 
00460 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines