584 needs_evaluation_ =
false;
585 int length = endpt_.
y() - startpt_.
y();
586 if (length == 0 || boxes_.empty()) {
588 Print(
"Zero length in evaluate");
592 BLOBNBOX_C_IT it(&boxes_);
594 int height_count = 0;
595 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
598 int height = box.
height();
599 mean_height += height;
602 if (height_count > 0) mean_height /= height_count;
610 STATS gutters(0, max_gutter + 1);
614 int num_deleted_boxes = 0;
615 bool text_on_image =
false;
617 const TBOX* prev_good_box =
nullptr;
618 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
621 int mid_y = (box.
top() + box.
bottom()) / 2;
624 tprintf(
"After already deleting %d boxes, ", num_deleted_boxes);
625 Print(
"Starting evaluation");
633 int tab_x =
XAtY(mid_y);
636 finder->GutterWidthAndNeighbourGap(tab_x, mean_height, max_gutter, left,
637 bbox, &gutter_width, &neighbour_gap);
639 tprintf(
"Box (%d,%d)->(%d,%d) has gutter %d, ndist %d\n",
641 gutter_width, neighbour_gap);
647 gutters.add(gutter_width, 1);
651 if (prev_good_box !=
nullptr) {
652 int vertical_gap = box.
bottom() - prev_good_box->
top();
653 double size1 = sqrt(static_cast<double>(prev_good_box->
area()));
654 double size2 = sqrt(static_cast<double>(box.
area()));
656 good_length += vertical_gap;
658 tprintf(
"Box and prev good, gap=%d, target %g, goodlength=%d\n",
666 prev_good_box = &box;
668 text_on_image =
true;
672 tprintf(
"Bad Box (%d,%d)->(%d,%d) with gutter %d, ndist %d\n",
674 gutter_width, neighbour_gap);
681 Print(
"Evaluating:");
686 int search_top = endpt_.
y();
687 int search_bottom = startpt_.
y();
689 if (gutters.get_total() > 0) {
690 prev_good_box =
nullptr;
691 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
694 int mid_y = (box.
top() + box.
bottom()) / 2;
698 int tab_x =
XAtY(mid_y);
707 finder->GutterWidthAndNeighbourGap(tab_x, mean_height, max_gutter, left,
708 bbox, &gutter_width, &neighbour_gap);
711 if (prev_good_box ==
nullptr) {
714 search_bottom = box.
top();
716 prev_good_box = &box;
717 search_top = box.
bottom();
721 tprintf(
"Bad Box (%d,%d)->(%d,%d) with gutter %d, mean gutter %d\n",
723 gutter_width, median_gutter);
731 if (prev_good_box !=
nullptr) {
734 int length = endpt_.
y() - startpt_.
y();
735 percent_score_ = 100 * good_length / length;
736 if (num_deleted_boxes > 0) {
744 if (search_bottom > search_top) {
745 search_bottom = startpt_.
y();
746 search_top = endpt_.
y();
750 min_gutter_width *= mean_height;
752 if (median_gutter > max_gutter_width)
753 max_gutter_width = median_gutter;
754 int gutter_width = finder->GutterWidth(search_bottom, search_top, *
this,
755 text_on_image, max_gutter_width,
757 if (gutter_width < min_gutter_width) {
759 tprintf(
"Rejecting bad tab Vector with %d gutter vs %g min\n",
760 gutter_width, min_gutter_width);
762 boxes_.shallow_clear();
765 tprintf(
"Final gutter %d, vs limit of %g, required shift = %d\n",
766 gutter_width, min_gutter_width, required_shift);
774 Print(
"Evaluation complete:");
int16_t y() const
access_function
const double kMinGutterFraction
BlobTextFlowType flow() const
static bool WithinTestRegion(int detail_level, int x, int y)
const int kGutterMultiple
const double kMinAlignedGutter
int IntCastRounded(double x)
const double kMinRaggedGutter
DLLSYM void tprintf(const char *format,...)
const double kLineCountReciprocal
const int kGutterToNeighbourRatio
const TBOX & bounding_box() const
const int kMaxFillinMultiple
void FitAndEvaluateIfNeeded(const ICOORD &vertical, TabFind *finder)
void SetYStart(int start_y)
void Print(const char *prefix)