tesseract  4.1.0
blobs.h
Go to the documentation of this file.
1 /* -*-C-*-
2  ********************************************************************************
3  *
4  * File: blobs.h
5  * Description: Blob definition
6  * Author: Mark Seaman, OCR Technology
7  *
8  * (c) Copyright 1989, Hewlett-Packard Company.
9  ** Licensed under the Apache License, Version 2.0 (the "License");
10  ** you may not use this file except in compliance with the License.
11  ** You may obtain a copy of the License at
12  ** http://www.apache.org/licenses/LICENSE-2.0
13  ** Unless required by applicable law or agreed to in writing, software
14  ** distributed under the License is distributed on an "AS IS" BASIS,
15  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  ** See the License for the specific language governing permissions and
17  ** limitations under the License.
18  *
19  *********************************************************************************/
20 
21 #ifndef BLOBS_H
22 #define BLOBS_H
23 
24 /*----------------------------------------------------------------------
25  I n c l u d e s
26 ----------------------------------------------------------------------*/
27 #include <cstdint> // for int16_t
28 #include <cstring> // for memcpy, memset
29 #include "clst.h" // for CLIST_ITERATOR, CLISTIZEH
30 #include "genericvector.h" // for GenericVector
31 #include "normalis.h" // for DENORM
32 #include "points.h" // for FCOORD, ICOORD
33 #include "publictypes.h" // for OcrEngineMode
34 #include "rect.h" // for TBOX
35 #include "scrollview.h" // for ScrollView, ScrollView::Color
36 #include "vecfuncs.h" // for CROSS
37 
38 class BLOCK;
39 class C_BLOB;
40 class C_OUTLINE;
41 class LLSQ;
42 class ROW;
43 class WERD;
44 
45 struct Pix;
46 
47 /*----------------------------------------------------------------------
48  T y p e s
49 ----------------------------------------------------------------------*/
50 #define EDGEPTFLAGS 4 /*concavity,length etc. */
51 
52 struct TPOINT {
53  TPOINT(): x(0), y(0) {}
54  TPOINT(int16_t vx, int16_t vy) : x(vx), y(vy) {}
55  TPOINT(const ICOORD &ic) : x(ic.x()), y(ic.y()) {}
56 
57  void operator+=(const TPOINT& other) {
58  x += other.x;
59  y += other.y;
60  }
61  void operator/=(int divisor) {
62  x /= divisor;
63  y /= divisor;
64  }
65  bool operator==(const TPOINT& other) const {
66  return x == other.x && y == other.y;
67  }
68  // Returns true when the two line segments cross each other.
69  // (Moved from outlines.cpp).
70  static bool IsCrossed(const TPOINT& a0, const TPOINT& a1, const TPOINT& b0,
71  const TPOINT& b1);
72 
73  int16_t x; // absolute x coord.
74  int16_t y; // absolute y coord.
75 };
76 using VECTOR = TPOINT; // structure for coordinates.
77 
78 struct EDGEPT {
80  : next(nullptr), prev(nullptr), src_outline(nullptr), start_step(0), step_count(0) {
81  memset(flags, 0, EDGEPTFLAGS * sizeof(flags[0]));
82  }
83  EDGEPT(const EDGEPT& src) : next(nullptr), prev(nullptr) {
84  CopyFrom(src);
85  }
86  EDGEPT& operator=(const EDGEPT& src) {
87  CopyFrom(src);
88  return *this;
89  }
90  // Copies the data elements, but leaves the pointers untouched.
91  void CopyFrom(const EDGEPT& src) {
92  pos = src.pos;
93  vec = src.vec;
94  memcpy(flags, src.flags, EDGEPTFLAGS * sizeof(flags[0]));
95  src_outline = src.src_outline;
96  start_step = src.start_step;
97  step_count = src.step_count;
98  }
99  // Returns the squared distance between the points, with the x-component
100  // weighted by x_factor.
101  int WeightedDistance(const EDGEPT& other, int x_factor) const {
102  int x_dist = pos.x - other.pos.x;
103  int y_dist = pos.y - other.pos.y;
104  return x_dist * x_dist * x_factor + y_dist * y_dist;
105  }
106  // Returns true if the positions are equal.
107  bool EqualPos(const EDGEPT& other) const { return pos == other.pos; }
108  // Returns the bounding box of the outline segment from *this to *end.
109  // Ignores hidden edge flags.
110  TBOX SegmentBox(const EDGEPT* end) const {
111  TBOX box(pos.x, pos.y, pos.x, pos.y);
112  const EDGEPT* pt = this;
113  do {
114  pt = pt->next;
115  if (pt->pos.x < box.left()) box.set_left(pt->pos.x);
116  if (pt->pos.x > box.right()) box.set_right(pt->pos.x);
117  if (pt->pos.y < box.bottom()) box.set_bottom(pt->pos.y);
118  if (pt->pos.y > box.top()) box.set_top(pt->pos.y);
119  } while (pt != end && pt != this);
120  return box;
121  }
122  // Returns the area of the outline segment from *this to *end.
123  // Ignores hidden edge flags.
124  int SegmentArea(const EDGEPT* end) const {
125  int area = 0;
126  const EDGEPT* pt = this->next;
127  do {
128  TPOINT origin_vec(pt->pos.x - pos.x, pt->pos.y - pos.y);
129  area += CROSS(origin_vec, pt->vec);
130  pt = pt->next;
131  } while (pt != end && pt != this);
132  return area;
133  }
134  // Returns true if the number of points in the outline segment from *this to
135  // *end is less that min_points and false if we get back to *this first.
136  // Ignores hidden edge flags.
137  bool ShortNonCircularSegment(int min_points, const EDGEPT* end) const {
138  int count = 0;
139  const EDGEPT* pt = this;
140  do {
141  if (pt == end) return true;
142  pt = pt->next;
143  ++count;
144  } while (pt != this && count <= min_points);
145  return false;
146  }
147 
148  // Accessors to hide or reveal a cut edge from feature extractors.
149  void Hide() {
150  flags[0] = true;
151  }
152  void Reveal() {
153  flags[0] = false;
154  }
155  bool IsHidden() const {
156  return flags[0] != 0;
157  }
158  void MarkChop() {
159  flags[2] = true;
160  }
161  bool IsChopPt() const {
162  return flags[2] != 0;
163  }
164 
165  TPOINT pos; // position
166  VECTOR vec; // vector to next point
167  // TODO(rays) Remove flags and replace with
168  // is_hidden, runlength, dir, and fixed. The only use
169  // of the flags other than is_hidden is in polyaprx.cpp.
170  char flags[EDGEPTFLAGS]; // concavity, length etc
171  EDGEPT* next; // anticlockwise element
172  EDGEPT* prev; // clockwise element
173  C_OUTLINE* src_outline; // Outline it came from.
174  // The following fields are not used if src_outline is nullptr.
175  int start_step; // Location of pos in src_outline.
176  int step_count; // Number of steps used (may wrap around).
177 };
178 
179 // For use in chop and findseam to keep a list of which EDGEPTs were inserted.
181 
182 struct TESSLINE {
183  TESSLINE() : is_hole(false), loop(nullptr), next(nullptr) {}
184  TESSLINE(const TESSLINE& src) : loop(nullptr), next(nullptr) {
185  CopyFrom(src);
186  }
188  Clear();
189  }
190  TESSLINE& operator=(const TESSLINE& src) {
191  CopyFrom(src);
192  return *this;
193  }
194  // Consume the circular list of EDGEPTs to make a TESSLINE.
195  static TESSLINE* BuildFromOutlineList(EDGEPT* outline);
196  // Copies the data and the outline, but leaves next untouched.
197  void CopyFrom(const TESSLINE& src);
198  // Deletes owned data.
199  void Clear();
200  // Normalize in-place using the DENORM.
201  void Normalize(const DENORM& denorm);
202  // Rotates by the given rotation in place.
203  void Rotate(const FCOORD rotation);
204  // Moves by the given vec in place.
205  void Move(const ICOORD vec);
206  // Scales by the given factor in place.
207  void Scale(float factor);
208  // Sets up the start and vec members of the loop from the pos members.
209  void SetupFromPos();
210  // Recomputes the bounding box from the points in the loop.
211  void ComputeBoundingBox();
212  // Computes the min and max cross product of the outline points with the
213  // given vec and returns the results in min_xp and max_xp. Geometrically
214  // this is the left and right edge of the outline perpendicular to the
215  // given direction, but to get the distance units correct, you would
216  // have to divide by the modulus of vec.
217  void MinMaxCrossProduct(const TPOINT vec, int* min_xp, int* max_xp) const;
218 
219  TBOX bounding_box() const;
220  // Returns true if *this and other have equal bounding boxes.
221  bool SameBox(const TESSLINE& other) const {
222  return topleft == other.topleft && botright == other.botright;
223  }
224  // Returns true if the given line segment crosses any outline of this blob.
225  bool SegmentCrosses(const TPOINT& pt1, const TPOINT& pt2) const {
226  if (Contains(pt1) && Contains(pt2)) {
227  EDGEPT* pt = loop;
228  do {
229  if (TPOINT::IsCrossed(pt1, pt2, pt->pos, pt->next->pos)) return true;
230  pt = pt->next;
231  } while (pt != loop);
232  }
233  return false;
234  }
235  // Returns true if the point is contained within the outline box.
236  bool Contains(const TPOINT& pt) const {
237  return topleft.x <= pt.x && pt.x <= botright.x &&
238  botright.y <= pt.y && pt.y <= topleft.y;
239  }
240 
241  #ifndef GRAPHICS_DISABLED
242  void plot(ScrollView* window, ScrollView::Color color,
243  ScrollView::Color child_color);
244  #endif // GRAPHICS_DISABLED
245 
246  // Returns the first outline point that has a different src_outline to its
247  // predecessor, or, if all the same, the lowest indexed point.
248  EDGEPT* FindBestStartPt() const;
249 
250 
251  int BBArea() const {
252  return (botright.x - topleft.x) * (topleft.y - botright.y);
253  }
254 
255  TPOINT topleft; // Top left of loop.
256  TPOINT botright; // Bottom right of loop.
257  TPOINT start; // Start of loop.
258  bool is_hole; // True if this is a hole/child outline.
259  EDGEPT *loop; // Edgeloop.
260  TESSLINE *next; // Next outline in blob.
261 }; // Outline structure.
262 
263 struct TBLOB {
264  TBLOB() : outlines(nullptr) {}
265  TBLOB(const TBLOB& src) : outlines(nullptr) {
266  CopyFrom(src);
267  }
268  ~TBLOB() {
269  Clear();
270  }
271  TBLOB& operator=(const TBLOB& src) {
272  CopyFrom(src);
273  return *this;
274  }
275  // Factory to build a TBLOB from a C_BLOB with polygonal approximation along
276  // the way. If allow_detailed_fx is true, the EDGEPTs in the returned TBLOB
277  // contain pointers to the input C_OUTLINEs that enable higher-resolution
278  // feature extraction that does not use the polygonal approximation.
279  static TBLOB* PolygonalCopy(bool allow_detailed_fx, C_BLOB* src);
280  // Factory builds a blob with no outlines, but copies the other member data.
281  static TBLOB* ShallowCopy(const TBLOB& src);
282  // Normalizes the blob for classification only if needed.
283  // (Normally this means a non-zero classify rotation.)
284  // If no Normalization is needed, then nullptr is returned, and the input blob
285  // can be used directly. Otherwise a new TBLOB is returned which must be
286  // deleted after use.
287  TBLOB* ClassifyNormalizeIfNeeded() const;
288 
289  // Copies the data and the outlines, but leaves next untouched.
290  void CopyFrom(const TBLOB& src);
291  // Deletes owned data.
292  void Clear();
293  // Sets up the built-in DENORM and normalizes the blob in-place.
294  // For parameters see DENORM::SetupNormalization, plus the inverse flag for
295  // this blob and the Pix for the full image.
296  void Normalize(const BLOCK* block,
297  const FCOORD* rotation,
298  const DENORM* predecessor,
299  float x_origin, float y_origin,
300  float x_scale, float y_scale,
301  float final_xshift, float final_yshift,
302  bool inverse, Pix* pix);
303  // Rotates by the given rotation in place.
304  void Rotate(const FCOORD rotation);
305  // Moves by the given vec in place.
306  void Move(const ICOORD vec);
307  // Scales by the given factor in place.
308  void Scale(float factor);
309  // Recomputes the bounding boxes of the outlines.
310  void ComputeBoundingBoxes();
311 
312  // Returns the number of outlines.
313  int NumOutlines() const;
314 
315  TBOX bounding_box() const;
316 
317  // Returns true if the given line segment crosses any outline of this blob.
318  bool SegmentCrossesOutline(const TPOINT& pt1, const TPOINT& pt2) const {
319  for (const TESSLINE* outline = outlines; outline != nullptr;
320  outline = outline->next) {
321  if (outline->SegmentCrosses(pt1, pt2)) return true;
322  }
323  return false;
324  }
325  // Returns true if the point is contained within any of the outline boxes.
326  bool Contains(const TPOINT& pt) const {
327  for (const TESSLINE* outline = outlines; outline != nullptr;
328  outline = outline->next) {
329  if (outline->Contains(pt)) return true;
330  }
331  return false;
332  }
333 
334  // Finds and deletes any duplicate outlines in this blob, without deleting
335  // their EDGEPTs.
336  void EliminateDuplicateOutlines();
337 
338  // Swaps the outlines of *this and next if needed to keep the centers in
339  // increasing x.
340  void CorrectBlobOrder(TBLOB* next);
341 
342  const DENORM& denorm() const {
343  return denorm_;
344  }
345 
346  #ifndef GRAPHICS_DISABLED
347  void plot(ScrollView* window, ScrollView::Color color,
348  ScrollView::Color child_color);
349  #endif // GRAPHICS_DISABLED
350 
351  int BBArea() const {
352  int total_area = 0;
353  for (TESSLINE* outline = outlines; outline != nullptr; outline = outline->next)
354  total_area += outline->BBArea();
355  return total_area;
356  }
357 
358  // Computes the center of mass and second moments for the old baseline and
359  // 2nd moment normalizations. Returns the outline length.
360  // The input denorm should be the normalizations that have been applied from
361  // the image to the current state of this TBLOB.
362  int ComputeMoments(FCOORD* center, FCOORD* second_moments) const;
363  // Computes the precise bounding box of the coords that are generated by
364  // GetEdgeCoords. This may be different from the bounding box of the polygon.
365  void GetPreciseBoundingBox(TBOX* precise_box) const;
366  // Adds edges to the given vectors.
367  // For all the edge steps in all the outlines, or polygonal approximation
368  // where there are no edge steps, collects the steps into x_coords/y_coords.
369  // x_coords is a collection of the x-coords of vertical edges for each
370  // y-coord starting at box.bottom().
371  // y_coords is a collection of the y-coords of horizontal edges for each
372  // x-coord starting at box.left().
373  // Eg x_coords[0] is a collection of the x-coords of edges at y=bottom.
374  // Eg x_coords[1] is a collection of the x-coords of edges at y=bottom + 1.
375  void GetEdgeCoords(const TBOX& box,
376  GenericVector<GenericVector<int> >* x_coords,
377  GenericVector<GenericVector<int> >* y_coords) const;
378 
379  TESSLINE *outlines; // List of outlines in blob.
380 
381  private: // TODO(rays) Someday the data members will be private too.
382  // For all the edge steps in all the outlines, or polygonal approximation
383  // where there are no edge steps, collects the steps into the bounding_box,
384  // llsq and/or the x_coords/y_coords. Both are used in different kinds of
385  // normalization.
386  // For a description of x_coords, y_coords, see GetEdgeCoords above.
387  void CollectEdges(const TBOX& box,
388  TBOX* bounding_box, LLSQ* llsq,
389  GenericVector<GenericVector<int> >* x_coords,
390  GenericVector<GenericVector<int> >* y_coords) const;
391 
392  private:
393  // DENORM indicating the transformations that this blob has undergone so far.
394  DENORM denorm_;
395 }; // Blob structure.
396 
397 struct TWERD {
398  TWERD() : latin_script(false) {}
399  TWERD(const TWERD& src) {
400  CopyFrom(src);
401  }
402  ~TWERD() {
403  Clear();
404  }
405  TWERD& operator=(const TWERD& src) {
406  CopyFrom(src);
407  return *this;
408  }
409  // Factory to build a TWERD from a (C_BLOB) WERD, with polygonal
410  // approximation along the way.
411  static TWERD* PolygonalCopy(bool allow_detailed_fx, WERD* src);
412  // Baseline normalizes the blobs in-place, recording the normalization in the
413  // DENORMs in the blobs.
414  void BLNormalize(const BLOCK* block, const ROW* row, Pix* pix, bool inverse,
415  float x_height, float baseline_shift, bool numeric_mode,
417  const TBOX* norm_box,
418  DENORM* word_denorm);
419  // Copies the data and the blobs, but leaves next untouched.
420  void CopyFrom(const TWERD& src);
421  // Deletes owned data.
422  void Clear();
423  // Recomputes the bounding boxes of the blobs.
424  void ComputeBoundingBoxes();
425 
426  // Returns the number of blobs in the word.
427  int NumBlobs() const {
428  return blobs.size();
429  }
430  TBOX bounding_box() const;
431 
432  // Merges the blobs from start to end, not including end, and deletes
433  // the blobs between start and end.
434  void MergeBlobs(int start, int end);
435 
436  void plot(ScrollView* window);
437 
438  GenericVector<TBLOB*> blobs; // Blobs in word.
439  bool latin_script; // This word is in a latin-based script.
440 };
441 
442 /*----------------------------------------------------------------------
443  F u n c t i o n s
444 ----------------------------------------------------------------------*/
445 // TODO(rays) Make divisible_blob and divide_blobs members of TBLOB.
446 bool divisible_blob(TBLOB *blob, bool italic_blob, TPOINT* location);
447 
448 void divide_blobs(TBLOB *blob, TBLOB *other_blob, bool italic_blob,
449  const TPOINT& location);
450 
451 #endif
Definition: werd.h:56
int step_count
Definition: blobs.h:176
int16_t top() const
Definition: rect.h:58
TESSLINE * next
Definition: blobs.h:260
EDGEPT & operator=(const EDGEPT &src)
Definition: blobs.h:86
bool EqualPos(const EDGEPT &other) const
Definition: blobs.h:107
void set_top(int y)
Definition: rect.h:61
Definition: rect.h:34
char flags[EDGEPTFLAGS]
Definition: blobs.h:170
bool Contains(const TPOINT &pt) const
Definition: blobs.h:326
TESSLINE()
Definition: blobs.h:183
int SegmentArea(const EDGEPT *end) const
Definition: blobs.h:124
void set_right(int x)
Definition: rect.h:82
EDGEPT()
Definition: blobs.h:79
int16_t x
Definition: blobs.h:73
Definition: blobs.h:397
bool IsHidden() const
Definition: blobs.h:155
void Normalize(float *Values)
GenericVector< TBLOB * > blobs
Definition: blobs.h:438
Definition: points.h:188
#define EDGEPTFLAGS
Definition: blobs.h:50
~TBLOB()
Definition: blobs.h:268
EDGEPT * next
Definition: blobs.h:171
TESSLINE & operator=(const TESSLINE &src)
Definition: blobs.h:190
TBLOB()
Definition: blobs.h:264
TESSLINE * outlines
Definition: blobs.h:379
~TESSLINE()
Definition: blobs.h:187
EDGEPT * loop
Definition: blobs.h:259
integer coordinate
Definition: points.h:31
TPOINT pos
Definition: blobs.h:165
TESSLINE(const TESSLINE &src)
Definition: blobs.h:184
Definition: blobs.h:263
TPOINT topleft
Definition: blobs.h:255
void operator+=(const TPOINT &other)
Definition: blobs.h:57
bool SegmentCrossesOutline(const TPOINT &pt1, const TPOINT &pt2) const
Definition: blobs.h:318
int BBArea() const
Definition: blobs.h:351
TPOINT botright
Definition: blobs.h:256
EDGEPT(const EDGEPT &src)
Definition: blobs.h:83
void set_left(int x)
Definition: rect.h:75
void CopyFrom(const EDGEPT &src)
Definition: blobs.h:91
void MarkChop()
Definition: blobs.h:158
TBLOB & operator=(const TBLOB &src)
Definition: blobs.h:271
Definition: linlsq.h:28
TBOX SegmentBox(const EDGEPT *end) const
Definition: blobs.h:110
bool latin_script
Definition: blobs.h:439
int16_t y
Definition: blobs.h:74
void divide_blobs(TBLOB *blob, TBLOB *other_blob, bool italic_blob, const TPOINT &location)
Definition: blobs.cpp:966
bool Contains(const TPOINT &pt) const
Definition: blobs.h:236
Definition: blobs.h:52
int start_step
Definition: blobs.h:175
bool operator==(const TPOINT &other) const
Definition: blobs.h:65
TPOINT(int16_t vx, int16_t vy)
Definition: blobs.h:54
bool SameBox(const TESSLINE &other) const
Definition: blobs.h:221
bool ShortNonCircularSegment(int min_points, const EDGEPT *end) const
Definition: blobs.h:137
Definition: blobs.h:78
~TWERD()
Definition: blobs.h:402
bool SegmentCrosses(const TPOINT &pt1, const TPOINT &pt2) const
Definition: blobs.h:225
bool is_hole
Definition: blobs.h:258
void operator/=(int divisor)
Definition: blobs.h:61
int16_t right() const
Definition: rect.h:79
int16_t bottom() const
Definition: rect.h:65
C_OUTLINE * src_outline
Definition: blobs.h:173
TWERD & operator=(const TWERD &src)
Definition: blobs.h:405
int NumBlobs() const
Definition: blobs.h:427
TPOINT(const ICOORD &ic)
Definition: blobs.h:55
const DENORM & denorm() const
Definition: blobs.h:342
int16_t left() const
Definition: rect.h:72
TWERD(const TWERD &src)
Definition: blobs.h:399
void Reveal()
Definition: blobs.h:152
Definition: ocrrow.h:36
static bool IsCrossed(const TPOINT &a0, const TPOINT &a1, const TPOINT &b0, const TPOINT &b1)
Definition: blobs.cpp:67
int WeightedDistance(const EDGEPT &other, int x_factor) const
Definition: blobs.h:101
TPOINT start
Definition: blobs.h:257
#define CROSS(a, b)
Definition: vecfuncs.h:47
int BBArea() const
Definition: blobs.h:251
void set_bottom(int y)
Definition: rect.h:68
TPOINT()
Definition: blobs.h:53
void Hide()
Definition: blobs.h:149
CLISTIZEH(STRING) CLISTIZE(STRING) namespace tesseract
Definition: reject.cpp:51
TBLOB(const TBLOB &src)
Definition: blobs.h:265
VECTOR vec
Definition: blobs.h:166
bool IsChopPt() const
Definition: blobs.h:161
int count(LIST var_list)
Definition: oldlist.cpp:96
TWERD()
Definition: blobs.h:398
Definition: ocrblock.h:29
EDGEPT * prev
Definition: blobs.h:172
bool divisible_blob(TBLOB *blob, bool italic_blob, TPOINT *location)
Definition: blobs.cpp:917