tesseract  5.0.0
tabfind.h
Go to the documentation of this file.
1 // File: tabfind.h
3 // Description: Subclass of BBGrid to find tabstops.
4 // Author: Ray Smith
5 //
6 // (C) Copyright 2008, Google Inc.
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
18 
19 #ifndef TESSERACT_TEXTORD_TABFIND_H_
20 #define TESSERACT_TEXTORD_TABFIND_H_
21 
22 #include <functional> // for std::function
23 #include "alignedblob.h"
24 #include "linefind.h"
25 #include "tabvector.h"
26 
27 class BLOBNBOX;
28 class BLOBNBOX_LIST;
29 class TO_BLOCK;
30 class ScrollView;
31 struct Pix;
32 
33 namespace tesseract {
34 
35 using WidthCallback = std::function<bool(int)>;
36 
37 struct AlignedBlobParams;
38 class ColPartitionGrid;
39 
41 const int kColumnWidthFactor = 20;
42 
52 class TESS_API TabFind : public AlignedBlob {
53 public:
54  TabFind(int gridsize, const ICOORD &bleft, const ICOORD &tright, TabVector_LIST *vlines,
55  int vertical_x, int vertical_y, int resolution);
56  ~TabFind() override;
57 
66  void InsertBlobsToGrid(bool h_spread, bool v_spread, BLOBNBOX_LIST *blobs,
68 
76  bool InsertBlob(bool h_spread, bool v_spread, BLOBNBOX *blob,
78  // Calls SetBlobRuleEdges for all the blobs in the given block.
79  void SetBlockRuleEdges(TO_BLOCK *block);
80  // Sets the left and right rule and crossing_rules for the blobs in the given
81  // list by finding the next outermost tabvectors for each blob.
82  void SetBlobRuleEdges(BLOBNBOX_LIST *blobs);
83 
84  // Returns the gutter width of the given TabVector between the given y limits.
85  // Also returns x-shift to be added to the vector to clear any intersecting
86  // blobs. The shift is deducted from the returned gutter.
87  // If ignore_unmergeables is true, then blobs of UnMergeableType are
88  // ignored as if they don't exist. (Used for text on image.)
89  // max_gutter_width is used as the maximum width worth searching for in case
90  // there is nothing near the TabVector.
91  int GutterWidth(int bottom_y, int top_y, const TabVector &v, bool ignore_unmergeables,
92  int max_gutter_width, int *required_shift);
96  void GutterWidthAndNeighbourGap(int tab_x, int mean_height, int max_gutter, bool left,
97  BLOBNBOX *bbox, int *gutter_width, int *neighbour_gap);
98 
105  int RightEdgeForBox(const TBOX &box, bool crossing, bool extended);
109  int LeftEdgeForBox(const TBOX &box, bool crossing, bool extended);
110 
127  TabVector *RightTabForBox(const TBOX &box, bool crossing, bool extended);
131  TabVector *LeftTabForBox(const TBOX &box, bool crossing, bool extended);
132 
137  bool CommonWidth(int width);
142  static bool DifferentSizes(int size1, int size2);
147  static bool VeryDifferentSizes(int size1, int size2);
148 
153  return width_cb_;
154  }
155 
159  const ICOORD &image_origin() const {
160  return image_origin_;
161  }
162 
163 protected:
167  TabVector_LIST *vectors() {
168  return &vectors_;
169  }
170  TabVector_LIST *dead_vectors() {
171  return &dead_vectors_;
172  }
173 
181  bool FindTabVectors(TabVector_LIST *hlines, BLOBNBOX_LIST *image_blobs, TO_BLOCK *block,
182  int min_gutter_width, double tabfind_aligned_gap_fraction,
183  ColPartitionGrid *part_grid, FCOORD *deskew, FCOORD *reskew);
184 
185  // Top-level function to not find TabVectors in an input page block,
186  // but setup for single column mode.
187  void DontFindTabVectors(BLOBNBOX_LIST *image_blobs, TO_BLOCK *block, FCOORD *deskew,
188  FCOORD *reskew);
189 
190  // Cleans up the lists of blobs in the block ready for use by TabFind.
191  // Large blobs that look like text are moved to the main blobs list.
192  // Main blobs that are superseded by the image blobs are deleted.
193  void TidyBlobs(TO_BLOCK *block);
194 
195  // Helper function to setup search limits for *TabForBox.
196  void SetupTabSearch(int x, int y, int *min_key, int *max_key);
197 
201  ScrollView *DisplayTabVectors(ScrollView *tab_win);
202 
203  // First part of FindTabVectors, which may be used twice if the text
204  // is mostly of vertical alignment. If find_vertical_text flag is
205  // true, this finds vertical textlines in possibly rotated blob space.
206  // In other words, when the page has mostly vertical lines and is rotated,
207  // setting this to true will find horizontal lines on the page.
208  // tabfind_aligned_gap_fraction should be the value of parameter
209  // textord_tabfind_aligned_gap_fraction
210  ScrollView *FindInitialTabVectors(BLOBNBOX_LIST *image_blobs, int min_gutter_width,
211  double tabfind_aligned_gap_fraction, TO_BLOCK *block);
212 
213  // Apply the given rotation to the given list of blobs.
214  static void RotateBlobList(const FCOORD &rotation, BLOBNBOX_LIST *blobs);
215 
216  // Flip the vertical and horizontal lines and rotate the grid ready
217  // for working on the rotated image.
218  // The min_gutter_width will be adjusted to the median gutter width between
219  // vertical tabs to set a better threshold for tabboxes in the 2nd pass.
220  void ResetForVerticalText(const FCOORD &rotate, const FCOORD &rerotate,
221  TabVector_LIST *horizontal_lines, int *min_gutter_width);
222 
223  // Clear the grid and get rid of the tab vectors, but not separators,
224  // ready to start again.
225  void Reset();
226 
227  // Reflect the separator tab vectors and the grids in the y-axis.
228  // Can only be called after Reset!
229  void ReflectInYAxis();
230 
231 private:
232  // For each box in the grid, decide whether it is a candidate tab-stop,
233  // and if so add it to the left and right tab boxes.
234  // tabfind_aligned_gap_fraction should be the value of parameter
235  // textord_tabfind_aligned_gap_fraction
236  ScrollView *FindTabBoxes(int min_gutter_width, double tabfind_aligned_gap_fraction);
237 
238  // Return true if this box looks like a candidate tab stop, and set
239  // the appropriate tab type(s) to TT_UNCONFIRMED.
240  // tabfind_aligned_gap_fraction should be the value of parameter
241  // textord_tabfind_aligned_gap_fraction
242  bool TestBoxForTabs(BLOBNBOX *bbox, int min_gutter_width, double tabfind_aligned_gap_fraction);
243 
244  // Returns true if there is nothing in the rectangle of width min_gutter to
245  // the left of bbox.
246  bool ConfirmRaggedLeft(BLOBNBOX *bbox, int min_gutter);
247  // Returns true if there is nothing in the rectangle of width min_gutter to
248  // the right of bbox.
249  bool ConfirmRaggedRight(BLOBNBOX *bbox, int min_gutter);
250  // Returns true if there is nothing in the given search_box that vertically
251  // overlaps target_box other than target_box itself.
252  bool NothingYOverlapsInBox(const TBOX &search_box, const TBOX &target_box);
253 
254  // Fills the list of TabVector with the tabstops found in the grid,
255  // and estimates the logical vertical direction.
256  void FindAllTabVectors(int min_gutter_width);
257  // Helper for FindAllTabVectors finds the vectors of a particular type.
258  int FindTabVectors(int search_size_multiple, TabAlignment alignment, int min_gutter_width,
259  TabVector_LIST *vectors, int *vertical_x, int *vertical_y);
260  // Finds a vector corresponding to a tabstop running through the
261  // given box of the given alignment type.
262  // search_size_multiple is a multiple of height used to control
263  // the size of the search.
264  // vertical_x and y are updated with an estimate of the real
265  // vertical direction. (skew finding.)
266  // Returns nullptr if no decent tabstop can be found.
267  TabVector *FindTabVector(int search_size_multiple, int min_gutter_width, TabAlignment alignment,
268  BLOBNBOX *bbox, int *vertical_x, int *vertical_y);
269 
270  // Set the vertical_skew_ member from the given vector and refit
271  // all vectors parallel to the skew vector.
272  void SetVerticalSkewAndParallelize(int vertical_x, int vertical_y);
273 
274  // Sort all the current vectors using the vertical_skew_ vector.
275  void SortVectors();
276 
277  // Evaluate all the current tab vectors.
278  void EvaluateTabs();
279 
280  // Trace textlines from one side to the other of each tab vector, saving
281  // the most frequent column widths found in a list so that a given width
282  // can be tested for being a common width with a simple callback function.
283  void ComputeColumnWidths(ScrollView *tab_win, ColPartitionGrid *part_grid);
284 
285  // Finds column width and:
286  // if col_widths is not null (pass1):
287  // pair-up tab vectors with existing ColPartitions and accumulate widths.
288  // else (pass2):
289  // find the largest real partition width for each recorded column width,
290  // to be used as the minimum acceptable width.
291  void ApplyPartitionsToColumnWidths(ColPartitionGrid *part_grid, STATS *col_widths);
292 
293  // Helper makes the list of common column widths in column_widths_ from the
294  // input col_widths. Destroys the content of col_widths by repeatedly
295  // finding the mode and erasing the peak.
296  void MakeColumnWidths(int col_widths_size, STATS *col_widths);
297 
298  // Mark blobs as being in a vertical text line where that is the case.
299  void MarkVerticalText();
300 
301  // Returns the median gutter width between pairs of matching tab vectors
302  // assuming they are sorted left-to-right. If there are too few data
303  // points (< kMinLinesInColumn), then 0 is returned.
304  int FindMedianGutterWidth(TabVector_LIST *tab_vectors);
305 
306  // Find the next adjacent (to left or right) blob on this text line,
307  // with the constraint that it must vertically significantly overlap
308  // the [top_y, bottom_y] range.
309  // If ignore_images is true, then blobs with aligned_text() < 0 are treated
310  // as if they do not exist.
311  BLOBNBOX *AdjacentBlob(const BLOBNBOX *bbox, bool look_left, bool ignore_images,
312  double min_overlap_fraction, int gap_limit, int top_y, int bottom_y);
313 
314  // Add a bi-directional partner relationship between the left
315  // and the right. If one (or both) of the vectors is a separator,
316  // extend a nearby extendable vector or create a new one of the
317  // correct type, using the given left or right blob as a guide.
318  void AddPartnerVector(BLOBNBOX *left_blob, BLOBNBOX *right_blob, TabVector *left,
319  TabVector *right);
320 
325  void CleanupTabs();
326 
332  bool Deskew(TabVector_LIST *hlines, BLOBNBOX_LIST *image_blobs, TO_BLOCK *block, FCOORD *deskew,
333  FCOORD *reskew);
334 
335  // Compute the rotation required to deskew, and its inverse rotation.
336  void ComputeDeskewVectors(FCOORD *deskew, FCOORD *reskew);
337 
342  void ApplyTabConstraints();
343 
344 protected:
347 private:
348  ICOORD image_origin_;
349  TabVector_LIST vectors_;
350  TabVector_IT v_it_;
351  TabVector_LIST dead_vectors_;
352  // List of commonly occurring width ranges with x=min and y=max.
353  ICOORDELT_LIST column_widths_;
355  WidthCallback width_cb_;
356  // Sets of bounding boxes that are candidate tab stops.
357  std::vector<BLOBNBOX *> left_tab_boxes_;
358  std::vector<BLOBNBOX *> right_tab_boxes_;
359 };
360 
361 } // namespace tesseract.
362 
363 #endif // TESSERACT_TEXTORD_TABFIND_H_
const int kColumnWidthFactor
Definition: tabfind.h:41
std::function< bool(int)> WidthCallback
Definition: tabfind.h:35
integer coordinate
Definition: points.h:36
~TabFind() override
TabVector_LIST * dead_vectors()
Definition: tabfind.h:170
int resolution_
Of source image in pixels per inch.
Definition: tabfind.h:346
WidthCallback WidthCB()
Definition: tabfind.h:152
const ICOORD & image_origin() const
Definition: tabfind.h:159
ICOORD vertical_skew_
Estimate of true vertical in this image.
Definition: tabfind.h:345
TabVector_LIST * vectors()
Definition: tabfind.h:167
#define TESS_API
Definition: export.h:34