581 needs_evaluation_ =
false;
582 int length = endpt_.
y() - startpt_.
y();
583 if (length == 0 || boxes_.empty()) {
585 Print(
"Zero length in evaluate");
589 BLOBNBOX_C_IT it(&boxes_);
591 int height_count = 0;
592 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
595 int height = box.
height();
596 mean_height += height;
599 if (height_count > 0) mean_height /= height_count;
607 STATS gutters(0, max_gutter + 1);
611 int num_deleted_boxes = 0;
612 bool text_on_image =
false;
614 const TBOX* prev_good_box =
nullptr;
615 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
618 int mid_y = (box.
top() + box.
bottom()) / 2;
621 tprintf(
"After already deleting %d boxes, ", num_deleted_boxes);
622 Print(
"Starting evaluation");
630 int tab_x =
XAtY(mid_y);
633 finder->GutterWidthAndNeighbourGap(tab_x, mean_height, max_gutter, left,
634 bbox, &gutter_width, &neighbour_gap);
636 tprintf(
"Box (%d,%d)->(%d,%d) has gutter %d, ndist %d\n",
638 gutter_width, neighbour_gap);
644 gutters.add(gutter_width, 1);
648 if (prev_good_box !=
nullptr) {
649 int vertical_gap = box.
bottom() - prev_good_box->
top();
650 double size1 = sqrt(static_cast<double>(prev_good_box->
area()));
651 double size2 = sqrt(static_cast<double>(box.
area()));
653 good_length += vertical_gap;
655 tprintf(
"Box and prev good, gap=%d, target %g, goodlength=%d\n",
663 prev_good_box = &box;
665 text_on_image =
true;
669 tprintf(
"Bad Box (%d,%d)->(%d,%d) with gutter %d, ndist %d\n",
671 gutter_width, neighbour_gap);
678 Print(
"Evaluating:");
683 int search_top = endpt_.
y();
684 int search_bottom = startpt_.
y();
686 if (gutters.get_total() > 0) {
687 prev_good_box =
nullptr;
688 for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
691 int mid_y = (box.
top() + box.
bottom()) / 2;
695 int tab_x =
XAtY(mid_y);
704 finder->GutterWidthAndNeighbourGap(tab_x, mean_height, max_gutter, left,
705 bbox, &gutter_width, &neighbour_gap);
708 if (prev_good_box ==
nullptr) {
711 search_bottom = box.
top();
713 prev_good_box = &box;
714 search_top = box.
bottom();
718 tprintf(
"Bad Box (%d,%d)->(%d,%d) with gutter %d, mean gutter %d\n",
720 gutter_width, median_gutter);
728 if (prev_good_box !=
nullptr) {
731 int length = endpt_.
y() - startpt_.
y();
732 percent_score_ = 100 * good_length / length;
733 if (num_deleted_boxes > 0) {
741 if (search_bottom > search_top) {
742 search_bottom = startpt_.
y();
743 search_top = endpt_.
y();
747 min_gutter_width *= mean_height;
749 if (median_gutter > max_gutter_width)
750 max_gutter_width = median_gutter;
751 int gutter_width = finder->GutterWidth(search_bottom, search_top, *
this,
752 text_on_image, max_gutter_width,
754 if (gutter_width < min_gutter_width) {
756 tprintf(
"Rejecting bad tab Vector with %d gutter vs %g min\n",
757 gutter_width, min_gutter_width);
759 boxes_.shallow_clear();
762 tprintf(
"Final gutter %d, vs limit of %g, required shift = %d\n",
763 gutter_width, min_gutter_width, required_shift);
771 Print(
"Evaluation complete:");
const int kGutterToNeighbourRatio
static bool WithinTestRegion(int detail_level, int x, int y)
const int kGutterMultiple
DLLSYM void tprintf(const char *format,...)
void SetYStart(int start_y)
void FitAndEvaluateIfNeeded(const ICOORD &vertical, TabFind *finder)
const TBOX & bounding_box() const
const double kMinGutterFraction
const double kMinRaggedGutter
BlobTextFlowType flow() const
void Print(const char *prefix)
const double kMinAlignedGutter
const int kMaxFillinMultiple
const double kLineCountReciprocal
int16_t y() const
access_function
int IntCastRounded(double x)