25 #include "config_auto.h"
33 static BOOL_VAR(edges_use_new_outline_complexity,
false,
34 "Use the new outline complexity module");
35 static INT_VAR(edges_max_children_per_outline, 10,
36 "Max number of children inside a character outline");
37 static INT_VAR(edges_max_children_layers, 5,
38 "Max layers of nested children inside a character outline");
40 "turn on debugging for this module");
42 static INT_VAR(edges_children_per_grandchild, 10,
43 "Importance ratio for chucking outlines");
44 static INT_VAR(edges_children_count_limit, 45,
45 "Max holes allowed in blob");
46 static BOOL_VAR(edges_children_fix,
false,
47 "Remove boxy parents of char-like children");
48 static INT_VAR(edges_min_nonhole, 12,
49 "Min pixels for potential char in box");
50 static INT_VAR(edges_patharea_ratio, 40,
51 "Max lensq/area for acceptable child outline");
53 "Min area fraction of child outline");
55 "Min area fraction of grandchild for box");
65 ICOORD tright): bl(bleft), tr(tright) {
69 buckets.reset(
new C_OUTLINE_LIST[bxdim * bydim]);
116 int16_t xindex, yindex;
119 int32_t grandchild_count;
120 C_OUTLINE_IT child_it;
128 grandchild_count = 0;
129 if (++depth > edges_max_children_layers)
130 return max_count + depth;
132 for (yindex = ymin; yindex <= ymax; yindex++) {
133 for (xindex = xmin; xindex <= xmax; xindex++) {
134 child_it.set_to_list(&buckets[yindex * bxdim + xindex]);
135 if (child_it.empty())
137 for (child_it.mark_cycle_pt(); !child_it.cycled_list();
138 child_it.forward()) {
139 child = child_it.data();
140 if (child == outline || !(*child < *outline))
144 if (child_count > edges_max_children_per_outline) {
146 tprintf(
"Discard outline on child_count=%d > "
147 "max_children_per_outline=%d\n",
149 static_cast<int32_t>(edges_max_children_per_outline));
150 return max_count + child_count;
154 int32_t remaining_count = max_count - child_count - grandchild_count;
155 if (remaining_count > 0)
156 grandchild_count += edges_children_per_grandchild *
158 if (child_count + grandchild_count > max_count) {
160 tprintf(
"Disgard outline on child_count=%d + grandchild_count=%d "
162 child_count, grandchild_count, max_count);
163 return child_count + grandchild_count;
168 return child_count + grandchild_count;
185 int16_t xindex, yindex;
188 int32_t grandchild_count;
190 float max_parent_area;
192 int32_t child_length;
194 C_OUTLINE_IT child_it;
202 grandchild_count = 0;
206 for (yindex = ymin; yindex <= ymax; yindex++) {
207 for (xindex = xmin; xindex <= xmax; xindex++) {
208 child_it.set_to_list(&buckets[yindex * bxdim + xindex]);
209 if (child_it.empty())
211 for (child_it.mark_cycle_pt(); !child_it.cycled_list();
212 child_it.forward()) {
213 child = child_it.data();
214 if (child != outline && *child < *outline) {
216 if (child_count <= max_count) {
217 int max_grand =(max_count - child_count) /
218 edges_children_per_grandchild;
221 edges_children_per_grandchild;
225 if (child_count + grandchild_count > max_count) {
227 tprintf(
"Discarding parent with child count=%d, gc=%d\n",
228 child_count,grandchild_count);
229 return child_count + grandchild_count;
231 if (parent_area == 0) {
234 parent_area = -parent_area;
236 if (parent_area < max_parent_area)
240 (!edges_children_fix ||
244 child_area = -child_area;
245 if (edges_children_fix) {
246 if (parent_area - child_area < max_parent_area) {
250 if (grandchild_count > 0) {
252 tprintf(
"Discarding parent of area %d, child area=%d, max%g "
254 parent_area, child_area, max_parent_area,
256 return max_count + 1;
259 if (child_length * child_length >
260 child_area * edges_patharea_ratio) {
262 tprintf(
"Discarding parent of area %d, child area=%d, max%g "
263 "with child length=%d\n",
264 parent_area, child_area, max_parent_area,
266 return max_count + 1;
269 if (child_area < child->bounding_box().area() * edges_childarea) {
271 tprintf(
"Discarding parent of area %d, child area=%d, max%g "
272 "with child rect=%d\n",
273 parent_area, child_area, max_parent_area,
275 return max_count + 1;
282 return child_count + grandchild_count;
300 int16_t xindex, yindex;
302 C_OUTLINE_IT child_it;
309 for (yindex = ymin; yindex <= ymax; yindex++) {
310 for (xindex = xmin; xindex <= xmax; xindex++) {
311 child_it.set_to_list(&buckets[yindex * bxdim + xindex]);
312 for (child_it.mark_cycle_pt(); !child_it.cycled_list();
313 child_it.forward()) {
314 if (*child_it.data() < *outline) {
315 it->add_after_then_move(child_it.extract());
331 C_OUTLINE_LIST outlines;
332 C_OUTLINE_IT out_it = &outlines;
353 C_OUTLINE_LIST *outlines) {
369 C_OUTLINE_LIST *outlines,
373 C_OUTLINE_IT out_it = outlines;
374 C_OUTLINE_IT bucket_it;
377 for (out_it.mark_cycle_pt(); !out_it.cycled_list(); out_it.forward()) {
378 outline = out_it.extract();
381 bucket_it.set_to_list((*buckets) (ol_box.
left(), ol_box.
bottom()));
382 bucket_it.add_to_end(outline);
398 C_OUTLINE_LIST outlines;
400 C_OUTLINE_IT out_it = &outlines;
401 C_OUTLINE_IT bucket_it = buckets->
start_scan();
402 C_OUTLINE_IT parent_it;
403 C_BLOB_IT good_blobs = block->
blob_list();
406 while (!bucket_it.empty()) {
407 out_it.set_to_list(&outlines);
409 parent_it = bucket_it;
412 }
while (!bucket_it.at_first() &&
413 !(*parent_it.data() < *bucket_it.data()));
414 }
while (!bucket_it.at_first());
417 out_it.add_after_then_move(parent_it.extract());
422 bucket_it.set_to_list(buckets->
scan_next());
437 C_BLOB_IT* reject_it,
438 C_OUTLINE_IT* blob_it
443 outline = blob_it->data();
444 if (edges_use_new_outline_complexity)
446 edges_children_count_limit,
450 edges_children_count_limit);
451 if (child_count > edges_children_count_limit)