/src/tesseract/src/textord/colpartitiongrid.h
Line | Count | Source (jump to first uncovered line) |
1 | | /////////////////////////////////////////////////////////////////////// |
2 | | // File: colpartitiongrid.h |
3 | | // Description: Class collecting code that acts on a BBGrid of ColPartitions. |
4 | | // Author: Ray Smith |
5 | | // |
6 | | // (C) Copyright 2009, 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 | | // |
17 | | /////////////////////////////////////////////////////////////////////// |
18 | | |
19 | | #ifndef TESSERACT_TEXTORD_COLPARTITIONGRID_H_ |
20 | | #define TESSERACT_TEXTORD_COLPARTITIONGRID_H_ |
21 | | |
22 | | #include "bbgrid.h" |
23 | | #include "colpartition.h" |
24 | | #include "colpartitionset.h" |
25 | | |
26 | | namespace tesseract { |
27 | | |
28 | | class TabFind; |
29 | | |
30 | | // ColPartitionGrid is a BBGrid of ColPartition. |
31 | | // It collects functions that work on the grid. |
32 | | class TESS_API ColPartitionGrid |
33 | | : public BBGrid<ColPartition, ColPartition_CLIST, ColPartition_C_IT> { |
34 | | public: |
35 | 0 | ColPartitionGrid() = default; |
36 | | ColPartitionGrid(int gridsize, const ICOORD &bleft, const ICOORD &tright); |
37 | | |
38 | | ~ColPartitionGrid() override = default; |
39 | | |
40 | | // Handles a click event in a display window. |
41 | | void HandleClick(int x, int y) override; |
42 | | |
43 | | // Merges ColPartitions in the grid that look like they belong in the same |
44 | | // textline. |
45 | | // For all partitions in the grid, calls the box_cb permanent callback |
46 | | // to compute the search box, searches the box, and if a candidate is found, |
47 | | // calls the confirm_cb to check any more rules. If the confirm_cb returns |
48 | | // true, then the partitions are merged. |
49 | | // Both callbacks are deleted before returning. |
50 | | void Merges(const std::function<bool(ColPartition *, TBOX *)> &box_cb, |
51 | | const std::function<bool(const ColPartition *, |
52 | | const ColPartition *)> &confirm_cb); |
53 | | |
54 | | // For the given partition, calls the box_cb permanent callback |
55 | | // to compute the search box, searches the box, and if a candidate is found, |
56 | | // calls the confirm_cb to check any more rules. If the confirm_cb returns |
57 | | // true, then the partitions are merged. |
58 | | // Returns true if the partition is consumed by one or more merges. |
59 | | bool MergePart(const std::function<bool(ColPartition *, TBOX *)> &box_cb, |
60 | | const std::function<bool(const ColPartition *, |
61 | | const ColPartition *)> &confirm_cb, |
62 | | ColPartition *part); |
63 | | |
64 | | // Computes and returns the total overlap of all partitions in the grid. |
65 | | // If overlap_grid is non-null, it is filled with a grid that holds empty |
66 | | // partitions representing the union of all overlapped partitions. |
67 | | int ComputeTotalOverlap(ColPartitionGrid **overlap_grid); |
68 | | |
69 | | // Finds all the ColPartitions in the grid that overlap with the given |
70 | | // box and returns them SortByBoxLeft(ed) and uniqued in the given list. |
71 | | // Any partition equal to not_this (may be nullptr) is excluded. |
72 | | void FindOverlappingPartitions(const TBOX &box, const ColPartition *not_this, |
73 | | ColPartition_CLIST *parts); |
74 | | |
75 | | // Finds and returns the best candidate ColPartition to merge with part, |
76 | | // selected from the candidates list, based on the minimum increase in |
77 | | // pairwise overlap among all the partitions overlapped by the combined box. |
78 | | // If overlap_increase is not nullptr then it returns the increase in overlap |
79 | | // that would result from the merge. |
80 | | // See colpartitiongrid.cpp for a diagram. |
81 | | ColPartition *BestMergeCandidate( |
82 | | const ColPartition *part, ColPartition_CLIST *candidates, bool debug, |
83 | | const std::function<bool(const ColPartition *, const ColPartition *)> |
84 | | &confirm_cb, |
85 | | int *overlap_increase); |
86 | | |
87 | | // Split partitions where it reduces overlap between their bounding boxes. |
88 | | // ColPartitions are after all supposed to be a partitioning of the blobs |
89 | | // AND of the space on the page! |
90 | | // Blobs that cause overlaps get removed, put in individual partitions |
91 | | // and added to the big_parts list. They are most likely characters on |
92 | | // 2 textlines that touch, or something big like a dropcap. |
93 | | void SplitOverlappingPartitions(ColPartition_LIST *big_parts); |
94 | | |
95 | | // Filters partitions of source_type by looking at local neighbours. |
96 | | // Where a majority of neighbours have a text type, the partitions are |
97 | | // changed to text, where the neighbours have image type, they are changed |
98 | | // to image, and partitions that have no definite neighbourhood type are |
99 | | // left unchanged. |
100 | | // im_box and rerotation are used to map blob coordinates onto the |
101 | | // nontext_map, which is used to prevent the spread of text neighbourhoods |
102 | | // into images. |
103 | | // Returns true if anything was changed. |
104 | | bool GridSmoothNeighbours(BlobTextFlowType source_type, Image nontext_map, |
105 | | const TBOX &im_box, const FCOORD &rerotation); |
106 | | |
107 | | // Reflects the grid and its colpartitions in the y-axis, assuming that |
108 | | // all blob boxes have already been done. |
109 | | void ReflectInYAxis(); |
110 | | |
111 | | // Rotates the grid and its colpartitions by the given angle, assuming that |
112 | | // all blob boxes have already been done. |
113 | | void Deskew(const FCOORD &deskew); |
114 | | |
115 | | // Transforms the grid of partitions to the output blocks, putting each |
116 | | // partition into a separate block. We don't really care about the order, |
117 | | // as we just want to get as much text as possible without trying to organize |
118 | | // it into proper blocks or columns. |
119 | | void ExtractPartitionsAsBlocks(BLOCK_LIST *blocks, TO_BLOCK_LIST *to_blocks); |
120 | | |
121 | | // Sets the left and right tabs of the partitions in the grid. |
122 | | void SetTabStops(TabFind *tabgrid); |
123 | | |
124 | | // Makes the ColPartSets and puts them in the PartSetVector ready |
125 | | // for finding column bounds. Returns false if no partitions were found. |
126 | | // Each ColPartition in the grid is placed in a single ColPartSet based |
127 | | // on the bottom-left of its bounding box. |
128 | | bool MakeColPartSets(PartSetVector *part_sets); |
129 | | |
130 | | // Makes a single ColPartitionSet consisting of a single ColPartition that |
131 | | // represents the total horizontal extent of the significant content on the |
132 | | // page. Used for the single column setting in place of automatic detection. |
133 | | // Returns nullptr if the page is empty of significant content. |
134 | | ColPartitionSet *MakeSingleColumnSet(WidthCallback cb); |
135 | | |
136 | | // Mark the BLOBNBOXes in each partition as being owned by that partition. |
137 | | void ClaimBoxes(); |
138 | | |
139 | | // Retypes all the blobs referenced by the partitions in the grid. |
140 | | // Image blobs are sliced on the grid boundaries to give the tab finder |
141 | | // a better handle on the edges of the images, and the actual blobs are |
142 | | // returned in the im_blobs list, as they are not owned by the block. |
143 | | void ReTypeBlobs(BLOBNBOX_LIST *im_blobs); |
144 | | |
145 | | // The boxes within the partitions have changed (by deskew) so recompute |
146 | | // the bounds of all the partitions and reinsert them into the grid. |
147 | | void RecomputeBounds(int gridsize, const ICOORD &bleft, const ICOORD &tright, |
148 | | const ICOORD &vertical); |
149 | | |
150 | | // Improves the margins of the ColPartitions in the grid by calling |
151 | | // FindPartitionMargins on each. |
152 | | void GridFindMargins(ColPartitionSet **best_columns); |
153 | | |
154 | | // Improves the margins of the ColPartitions in the list by calling |
155 | | // FindPartitionMargins on each. |
156 | | void ListFindMargins(ColPartitionSet **best_columns, |
157 | | ColPartition_LIST *parts); |
158 | | |
159 | | // Deletes all the partitions in the grid after disowning all the blobs. |
160 | | void DeleteParts(); |
161 | | |
162 | | // Deletes all the partitions in the grid that are of type BRT_UNKNOWN and |
163 | | // all the blobs in them. |
164 | | void DeleteUnknownParts(TO_BLOCK *block); |
165 | | |
166 | | // Deletes all the partitions in the grid that are NOT of flow type |
167 | | // BTFT_LEADER. |
168 | | void DeleteNonLeaderParts(); |
169 | | |
170 | | // Finds and marks text partitions that represent figure captions. |
171 | | void FindFigureCaptions(); |
172 | | |
173 | | //////// Functions that manipulate ColPartitions in the grid /////// |
174 | | //////// to find chains of partner partitions of the same type. /////// |
175 | | // For every ColPartition in the grid, finds its upper and lower neighbours. |
176 | | void FindPartitionPartners(); |
177 | | // Finds the best partner in the given direction for the given partition. |
178 | | // Stores the result with AddPartner. |
179 | | void FindPartitionPartners(bool upper, ColPartition *part); |
180 | | // Finds the best partner in the given direction for the given partition. |
181 | | // Stores the result with AddPartner. |
182 | | void FindVPartitionPartners(bool to_the_left, ColPartition *part); |
183 | | // For every ColPartition with multiple partners in the grid, reduces the |
184 | | // number of partners to 0 or 1. If get_desperate is true, goes to more |
185 | | // desperate merge methods to merge flowing text before breaking partnerships. |
186 | | void RefinePartitionPartners(bool get_desperate); |
187 | | |
188 | | private: |
189 | | // Finds and returns a list of candidate ColPartitions to merge with part. |
190 | | // The candidates must overlap search_box, and when merged must not |
191 | | // overlap any other partitions that are not overlapped by each individually. |
192 | | void FindMergeCandidates(const ColPartition *part, const TBOX &search_box, |
193 | | bool debug, ColPartition_CLIST *candidates); |
194 | | |
195 | | // Smoothes the region type/flow type of the given part by looking at local |
196 | | // neighbours and the given image mask. Searches a padded rectangle with the |
197 | | // padding truncated on one size of the part's box in turn for each side, |
198 | | // using the result (if any) that has the least distance to all neighbours |
199 | | // that contribute to the decision. This biases in favor of rectangular |
200 | | // regions without completely enforcing them. |
201 | | // If a good decision cannot be reached, the part is left unchanged. |
202 | | // im_box and rerotation are used to map blob coordinates onto the |
203 | | // nontext_map, which is used to prevent the spread of text neighbourhoods |
204 | | // into images. |
205 | | // Returns true if the partition was changed. |
206 | | bool SmoothRegionType(Image nontext_map, const TBOX &im_box, |
207 | | const FCOORD &rerotation, bool debug, |
208 | | ColPartition *part); |
209 | | // Executes the search for SmoothRegionType in a single direction. |
210 | | // Creates a bounding box that is padded in all directions except direction, |
211 | | // and searches it for other partitions. Finds the nearest collection of |
212 | | // partitions that makes a decisive result (if any) and returns the type |
213 | | // and the distance of the collection. If there are any pixels in the |
214 | | // nontext_map, then the decision is biased towards image. |
215 | | BlobRegionType SmoothInOneDirection(BlobNeighbourDir direction, |
216 | | Image nontext_map, const TBOX &im_box, |
217 | | const FCOORD &rerotation, bool debug, |
218 | | const ColPartition &part, |
219 | | int *best_distance); |
220 | | // Counts the partitions in the given search_box by appending the gap |
221 | | // distance (scaled by dist_scaling) of the part from the base_part to the |
222 | | // vector of the appropriate type for the partition. Prior to return, the |
223 | | // vectors in the dists array are sorted in increasing order. |
224 | | // dists must be an array of vectors of size NPT_COUNT. |
225 | | void AccumulatePartDistances(const ColPartition &base_part, |
226 | | const ICOORD &dist_scaling, |
227 | | const TBOX &search_box, Image nontext_map, |
228 | | const TBOX &im_box, const FCOORD &rerotation, |
229 | | bool debug, std::vector<int> *dists); |
230 | | |
231 | | // Improves the margins of the ColPartition by searching for |
232 | | // neighbours that vertically overlap significantly. |
233 | | void FindPartitionMargins(ColPartitionSet *columns, ColPartition *part); |
234 | | |
235 | | // Starting at x, and going in the specified direction, up to x_limit, finds |
236 | | // the margin for the given y range by searching sideways, |
237 | | // and ignoring not_this. |
238 | | int FindMargin(int x, bool right_to_left, int x_limit, int y_bottom, |
239 | | int y_top, const ColPartition *not_this); |
240 | | }; |
241 | | |
242 | | } // namespace tesseract. |
243 | | |
244 | | #endif // TESSERACT_TEXTORD_COLPARTITIONGRID_H_ |