583 needs_evaluation_ =
false;
584 int length = endpt_.
y() - startpt_.
y();
585 if (length == 0 || boxes_.empty()) {
587 Print(
"Zero length in evaluate");
591 BLOBNBOX_C_IT it(&boxes_);
593 int height_count = 0;
594 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
597 int height = box.
height();
598 mean_height += height;
601 if (height_count > 0) mean_height /= height_count;
609 STATS gutters(0, max_gutter + 1);
613 int num_deleted_boxes = 0;
614 bool text_on_image =
false;
616 const TBOX* prev_good_box =
nullptr;
617 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
620 int mid_y = (box.
top() + box.
bottom()) / 2;
623 tprintf(
"After already deleting %d boxes, ", num_deleted_boxes);
624 Print(
"Starting evaluation");
632 int tab_x =
XAtY(mid_y);
635 finder->GutterWidthAndNeighbourGap(tab_x, mean_height, max_gutter, left,
636 bbox, &gutter_width, &neighbour_gap);
638 tprintf(
"Box (%d,%d)->(%d,%d) has gutter %d, ndist %d\n",
640 gutter_width, neighbour_gap);
646 gutters.add(gutter_width, 1);
650 if (prev_good_box !=
nullptr) {
651 int vertical_gap = box.
bottom() - prev_good_box->
top();
652 double size1 = sqrt(static_cast<double>(prev_good_box->
area()));
653 double size2 = sqrt(static_cast<double>(box.
area()));
655 good_length += vertical_gap;
657 tprintf(
"Box and prev good, gap=%d, target %g, goodlength=%d\n",
665 prev_good_box = &box;
667 text_on_image =
true;
671 tprintf(
"Bad Box (%d,%d)->(%d,%d) with gutter %d, ndist %d\n",
673 gutter_width, neighbour_gap);
680 Print(
"Evaluating:");
685 int search_top = endpt_.
y();
686 int search_bottom = startpt_.
y();
688 if (gutters.get_total() > 0) {
689 prev_good_box =
nullptr;
690 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
693 int mid_y = (box.
top() + box.
bottom()) / 2;
697 int tab_x =
XAtY(mid_y);
706 finder->GutterWidthAndNeighbourGap(tab_x, mean_height, max_gutter, left,
707 bbox, &gutter_width, &neighbour_gap);
710 if (prev_good_box ==
nullptr) {
713 search_bottom = box.
top();
715 prev_good_box = &box;
716 search_top = box.
bottom();
720 tprintf(
"Bad Box (%d,%d)->(%d,%d) with gutter %d, mean gutter %d\n",
722 gutter_width, median_gutter);
730 if (prev_good_box !=
nullptr) {
733 int length = endpt_.
y() - startpt_.
y();
734 percent_score_ = 100 * good_length / length;
735 if (num_deleted_boxes > 0) {
743 if (search_bottom > search_top) {
744 search_bottom = startpt_.
y();
745 search_top = endpt_.
y();
749 min_gutter_width *= mean_height;
751 if (median_gutter > max_gutter_width)
752 max_gutter_width = median_gutter;
753 int gutter_width = finder->GutterWidth(search_bottom, search_top, *
this,
754 text_on_image, max_gutter_width,
756 if (gutter_width < min_gutter_width) {
758 tprintf(
"Rejecting bad tab Vector with %d gutter vs %g min\n",
759 gutter_width, min_gutter_width);
761 boxes_.shallow_clear();
764 tprintf(
"Final gutter %d, vs limit of %g, required shift = %d\n",
765 gutter_width, min_gutter_width, required_shift);
773 Print(
"Evaluation complete:");
int IntCastRounded(double x)
void FitAndEvaluateIfNeeded(const ICOORD &vertical, TabFind *finder)
const double kMinGutterFraction
void Print(const char *prefix)
const TBOX & bounding_box() const
int16_t y() const
access_function
BlobTextFlowType flow() const
const int kGutterMultiple
const double kMinRaggedGutter
const int kMaxFillinMultiple
const double kLineCountReciprocal
void SetYStart(int start_y)
DLLSYM void tprintf(const char *format,...)
const double kMinAlignedGutter
const int kGutterToNeighbourRatio
static bool WithinTestRegion(int detail_level, int x, int y)