Tesseract  3.02
tesseract::TabFind Class Reference

#include <tabfind.h>

Inheritance diagram for tesseract::TabFind:
tesseract::AlignedBlob tesseract::BlobGrid tesseract::BBGrid< BLOBNBOX, BLOBNBOX_CLIST, BLOBNBOX_C_IT > tesseract::GridBase tesseract::ColumnFinder

List of all members.

Public Member Functions

 TabFind (int gridsize, const ICOORD &bleft, const ICOORD &tright, TabVector_LIST *vlines, int vertical_x, int vertical_y, int resolution)
virtual ~TabFind ()
void InsertBlobsToGrid (bool h_spread, bool v_spread, BLOBNBOX_LIST *blobs, BBGrid< BLOBNBOX, BLOBNBOX_CLIST, BLOBNBOX_C_IT > *grid)
bool InsertBlob (bool h_spread, bool v_spread, BLOBNBOX *blob, BBGrid< BLOBNBOX, BLOBNBOX_CLIST, BLOBNBOX_C_IT > *grid)
void SetBlockRuleEdges (TO_BLOCK *block)
void SetBlobRuleEdges (BLOBNBOX_LIST *blobs)
int GutterWidth (int bottom_y, int top_y, const TabVector &v, bool ignore_unmergeables, int max_gutter_width, int *required_shift)
void GutterWidthAndNeighbourGap (int tab_x, int mean_height, int max_gutter, bool left, BLOBNBOX *bbox, int *gutter_width, int *neighbour_gap)
int RightEdgeForBox (const TBOX &box, bool crossing, bool extended)
int LeftEdgeForBox (const TBOX &box, bool crossing, bool extended)
TabVectorRightTabForBox (const TBOX &box, bool crossing, bool extended)
TabVectorLeftTabForBox (const TBOX &box, bool crossing, bool extended)
bool CommonWidth (int width)
WidthCallbackWidthCB ()
const ICOORDimage_origin () const

Static Public Member Functions

static bool DifferentSizes (int size1, int size2)
static bool VeryDifferentSizes (int size1, int size2)

Protected Member Functions

TabVector_LIST * vectors ()
TabVector_LIST * dead_vectors ()
bool FindTabVectors (TabVector_LIST *hlines, BLOBNBOX_LIST *image_blobs, TO_BLOCK *block, int min_gutter_width, ColPartitionGrid *part_grid, FCOORD *deskew, FCOORD *reskew)
void DontFindTabVectors (BLOBNBOX_LIST *image_blobs, TO_BLOCK *block, FCOORD *deskew, FCOORD *reskew)
void TidyBlobs (TO_BLOCK *block)
void SetupTabSearch (int x, int y, int *min_key, int *max_key)
ScrollViewDisplayTabVectors (ScrollView *tab_win)
ScrollViewFindInitialTabVectors (BLOBNBOX_LIST *image_blobs, int min_gutter_width, TO_BLOCK *block)
void ResetForVerticalText (const FCOORD &rotate, const FCOORD &rerotate, TabVector_LIST *horizontal_lines, int *min_gutter_width)
void Reset ()
void ReflectInYAxis ()

Static Protected Member Functions

static void RotateBlobList (const FCOORD &rotation, BLOBNBOX_LIST *blobs)

Protected Attributes

ICOORD vertical_skew_
int resolution_

Detailed Description

The TabFind class contains code to find tab-stops and maintain the vectors_ list of tab vectors. Also provides an interface to find neighbouring blobs in the grid of BLOBNBOXes that is used by multiple subclasses. Searching is a complex operation because of the need to enforce rule/separator lines, and tabstop boundaries, (when available), so as the holder of the list of TabVectors this class provides the functions.

Definition at line 62 of file tabfind.h.


Constructor & Destructor Documentation

tesseract::TabFind::TabFind ( int  gridsize,
const ICOORD bleft,
const ICOORD tright,
TabVector_LIST *  vlines,
int  vertical_x,
int  vertical_y,
int  resolution 
)

Definition at line 89 of file tabfind.cpp.

  : AlignedBlob(gridsize, bleft, tright),
    resolution_(resolution),
    image_origin_(0, tright.y() - 1) {
  width_cb_ = NULL;
  v_it_.set_to_list(&vectors_);
  v_it_.add_list_after(vlines);
  SetVerticalSkewAndParellelize(vertical_x, vertical_y);
  width_cb_ = NewPermanentTessCallback(this, &TabFind::CommonWidth);
}
tesseract::TabFind::~TabFind ( ) [virtual]

Definition at line 102 of file tabfind.cpp.

                  {
  if (width_cb_ != NULL)
    delete width_cb_;
}

Member Function Documentation

bool tesseract::TabFind::CommonWidth ( int  width)

Return true if the given width is close to one of the common widths in column_widths_.

Definition at line 419 of file tabfind.cpp.

                                   {
  width /= kColumnWidthFactor;
  ICOORDELT_IT it(&column_widths_);
  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
    ICOORDELT* w = it.data();
    if (NearlyEqual<int>(width, w->x(), 1))
      return true;
  }
  return false;
}
TabVector_LIST* tesseract::TabFind::dead_vectors ( ) [inline, protected]

Definition at line 185 of file tabfind.h.

                                 {
    return &dead_vectors_;
  }
bool tesseract::TabFind::DifferentSizes ( int  size1,
int  size2 
) [static]

Return true if the sizes are more than a factor of 2 different.

Definition at line 432 of file tabfind.cpp.

                                                 {
  return size1 > size2 * 2 || size2 > size1 * 2;
}
ScrollView * tesseract::TabFind::DisplayTabVectors ( ScrollView tab_win) [protected]

Display the tab vectors found in this grid.

Definition at line 525 of file tabfind.cpp.

                                                          {
#ifndef GRAPHICS_DISABLED
  // For every vector, display it.
  TabVector_IT it(&vectors_);
  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
    TabVector* vector = it.data();
    vector->Display(tab_win);
  }
  tab_win->Update();
#endif
  return tab_win;
}
void tesseract::TabFind::DontFindTabVectors ( BLOBNBOX_LIST *  image_blobs,
TO_BLOCK block,
FCOORD deskew,
FCOORD reskew 
) [protected]

Definition at line 480 of file tabfind.cpp.

                                                                 {
  InsertBlobsToGrid(false, false, image_blobs, this);
  InsertBlobsToGrid(true, false, &block->blobs, this);
  deskew->set_x(1.0f);
  deskew->set_y(0.0f);
  reskew->set_x(1.0f);
  reskew->set_y(0.0f);
}
ScrollView * tesseract::TabFind::FindInitialTabVectors ( BLOBNBOX_LIST *  image_blobs,
int  min_gutter_width,
TO_BLOCK block 
) [protected]

Definition at line 542 of file tabfind.cpp.

                                                            {
  if (textord_tabfind_show_initialtabs) {
    ScrollView* line_win = MakeWindow(0, 0, "VerticalLines");
    line_win = DisplayTabVectors(line_win);
  }
  // Prepare the grid.
  if (image_blobs != NULL)
    InsertBlobsToGrid(true, false, image_blobs, this);
  InsertBlobsToGrid(true, false, &block->blobs, this);
  ScrollView* initial_win = FindTabBoxes(min_gutter_width);
  FindAllTabVectors(min_gutter_width);

  TabVector::MergeSimilarTabVectors(vertical_skew_, &vectors_, this);
  SortVectors();
  EvaluateTabs();
  if (textord_tabfind_show_initialtabs && initial_win != NULL)
    initial_win = DisplayTabVectors(initial_win);
  MarkVerticalText();
  return initial_win;
}
bool tesseract::TabFind::FindTabVectors ( TabVector_LIST *  hlines,
BLOBNBOX_LIST *  image_blobs,
TO_BLOCK block,
int  min_gutter_width,
ColPartitionGrid part_grid,
FCOORD deskew,
FCOORD reskew 
) [protected]

Top-level function to find TabVectors in an input page block. Returns false if the detected skew angle is impossible. Applies the detected skew angle to deskew the tabs, blobs and part_grid.

Definition at line 447 of file tabfind.cpp.

                                                             {
  ScrollView* tab_win = FindInitialTabVectors(image_blobs, min_gutter_width,
                                                  block);
  ComputeColumnWidths(tab_win, part_grid);
  TabVector::MergeSimilarTabVectors(vertical_skew_, &vectors_, this);
  SortVectors();
  CleanupTabs();
  if (!Deskew(hlines, image_blobs, block, deskew, reskew))
    return false;  // Skew angle is too large.
  part_grid->Deskew(*deskew);
  ApplyTabConstraints();
  #ifndef GRAPHICS_DISABLED
  if (textord_tabfind_show_finaltabs) {
    tab_win = MakeWindow(640, 50, "FinalTabs");
    if (textord_debug_images) {
      tab_win->Image(AlignedBlob::textord_debug_pix().string(),
                     image_origin_.x(), image_origin_.y());
    } else {
      DisplayBoxes(tab_win);
      DisplayTabs("FinalTabs", tab_win);
    }
    tab_win = DisplayTabVectors(tab_win);
  }
  #endif  // GRAPHICS_DISABLED
  return true;
}
int tesseract::TabFind::GutterWidth ( int  bottom_y,
int  top_y,
const TabVector v,
bool  ignore_unmergeables,
int  max_gutter_width,
int *  required_shift 
)

Definition at line 186 of file tabfind.cpp.

                                              {
  bool right_to_left = v.IsLeftTab();
  int bottom_x = v.XAtY(bottom_y);
  int top_x = v.XAtY(top_y);
  int start_x = right_to_left ? MAX(top_x, bottom_x) : MIN(top_x, bottom_x);
  BlobGridSearch sidesearch(this);
  sidesearch.StartSideSearch(start_x, bottom_y, top_y);
  int min_gap = max_gutter_width;
  *required_shift = 0;
  BLOBNBOX* blob = NULL;
  while ((blob = sidesearch.NextSideSearch(right_to_left)) != NULL) {
    const TBOX& box = blob->bounding_box();
    if (box.bottom() >= top_y || box.top() <= bottom_y)
      continue;  // Doesn't overlap enough.
    if (box.height() >= gridsize() * 2 &&
        box.height() > box.width() * kLineFragmentAspectRatio) {
      // Skip likely separator line residue.
      continue;
    }
    if (ignore_unmergeables && BLOBNBOX::UnMergeableType(blob->region_type()))
      continue;  // Skip non-text if required.
    int mid_y = (box.bottom() + box.top()) / 2;
    // We use the x at the mid-y so that the required_shift guarantees
    // to clear all the blobs on the tab-stop. If we use the min/max
    // of x at top/bottom of the blob, then exactness would be required,
    // which is not a good thing.
    int tab_x = v.XAtY(mid_y);
    int gap;
    if (right_to_left) {
      gap = tab_x - box.right();
      if (gap < 0 && box.left() - tab_x < *required_shift)
        *required_shift = box.left() - tab_x;
    } else {
      gap = box.left() - tab_x;
      if (gap < 0 && box.right() - tab_x > *required_shift)
        *required_shift = box.right() - tab_x;
    }
    if (gap > 0 && gap < min_gap)
      min_gap = gap;
  }
  // Result may be negative, in which case,  this is a really bad tabstop.
  return min_gap - abs(*required_shift);
}
void tesseract::TabFind::GutterWidthAndNeighbourGap ( int  tab_x,
int  mean_height,
int  max_gutter,
bool  left,
BLOBNBOX bbox,
int *  gutter_width,
int *  neighbour_gap 
)

Find the gutter width and distance to inner neighbour for the given blob.

Definition at line 233 of file tabfind.cpp.

                                                              {
  const TBOX& box = bbox->bounding_box();
  // The gutter and internal sides of the box.
  int gutter_x = left ? box.left() : box.right();
  int internal_x = left ? box.right() : box.left();
  // On ragged edges, the gutter side of the box is away from the tabstop.
  int tab_gap = left ? gutter_x - tab_x : tab_x - gutter_x;
  *gutter_width = max_gutter;
  // If the box is away from the tabstop, we need to increase
  // the allowed gutter width.
  if (tab_gap > 0)
    *gutter_width += tab_gap;
  bool debug = WithinTestRegion(2, box.left(), box.bottom());
  if (debug)
    tprintf("Looking in gutter\n");
  // Find the nearest blob on the outside of the column.
  BLOBNBOX* gutter_bbox = AdjacentBlob(bbox, left,
                                       bbox->flow() == BTFT_TEXT_ON_IMAGE, 0.0,
                                       *gutter_width, box.top(), box.bottom());
  if (gutter_bbox != NULL) {
    TBOX gutter_box = gutter_bbox->bounding_box();
    *gutter_width = left ? tab_x - gutter_box.right()
                        : gutter_box.left() - tab_x;
  }
  if (*gutter_width >= max_gutter) {
    // If there is no box because a tab was in the way, get the tab coord.
    TBOX gutter_box(box);
    if (left) {
      gutter_box.set_left(tab_x - max_gutter - 1);
      gutter_box.set_right(tab_x - max_gutter);
      int tab_gutter = RightEdgeForBox(gutter_box, true, false);
      if (tab_gutter < tab_x - 1)
        *gutter_width = tab_x - tab_gutter;
    } else {
      gutter_box.set_left(tab_x + max_gutter);
      gutter_box.set_right(tab_x + max_gutter + 1);
      int tab_gutter = LeftEdgeForBox(gutter_box, true, false);
      if (tab_gutter > tab_x + 1)
        *gutter_width = tab_gutter - tab_x;
    }
  }
  if (*gutter_width > max_gutter)
    *gutter_width = max_gutter;
  // Now look for a neighbour on the inside.
  if (debug)
    tprintf("Looking for neighbour\n");
  BLOBNBOX* neighbour = AdjacentBlob(bbox, !left,
                                     bbox->flow() == BTFT_TEXT_ON_IMAGE, 0.0,
                                     *gutter_width, box.top(), box.bottom());
  int neighbour_edge = left ? RightEdgeForBox(box, true, false)
                            : LeftEdgeForBox(box, true, false);
  if (neighbour != NULL) {
    TBOX n_box = neighbour->bounding_box();
    if (debug) {
      tprintf("Found neighbour:");
      n_box.print();
    }
    if (left && n_box.left() < neighbour_edge)
      neighbour_edge = n_box.left();
    else if (!left && n_box.right() > neighbour_edge)
      neighbour_edge = n_box.right();
  }
  *neighbour_gap = left ? neighbour_edge - internal_x
                        : internal_x - neighbour_edge;
}
const ICOORD& tesseract::TabFind::image_origin ( ) const [inline]

Return the coords at which to draw the image backdrop.

Definition at line 174 of file tabfind.h.

                                     {
    return image_origin_;
  }
bool tesseract::TabFind::InsertBlob ( bool  h_spread,
bool  v_spread,
BLOBNBOX blob,
BBGrid< BLOBNBOX, BLOBNBOX_CLIST, BLOBNBOX_C_IT > *  grid 
)

Insert a single blob into the given grid (not necessarily this). If h_spread, then all cells covered horizontally by the box are used, otherwise, just the bottom-left. Similarly for v_spread. A side effect is that the left and right rule edges of the blob are set according to the tab vectors in this (not grid).

Definition at line 143 of file tabfind.cpp.

                                                      {
  TBOX box = blob->bounding_box();
  blob->set_left_rule(LeftEdgeForBox(box, false, false));
  blob->set_right_rule(RightEdgeForBox(box, false, false));
  blob->set_left_crossing_rule(LeftEdgeForBox(box, true, false));
  blob->set_right_crossing_rule(RightEdgeForBox(box, true, false));
  if (blob->joined_to_prev())
    return false;
  grid->InsertBBox(h_spread, v_spread, blob);
  return true;
}
void tesseract::TabFind::InsertBlobsToGrid ( bool  h_spread,
bool  v_spread,
BLOBNBOX_LIST *  blobs,
BBGrid< BLOBNBOX, BLOBNBOX_CLIST, BLOBNBOX_C_IT > *  grid 
)

Insert a list of blobs into the given grid (not necessarily this). See InsertBlob for the other arguments. It would seem to make more sense to swap this and grid, but this way around allows grid to not be derived from TabFind, eg a ColPartitionGrid, while the grid that provides the tab stops(this) has to be derived from TabFind.

Definition at line 116 of file tabfind.cpp.

                                                             {
  BLOBNBOX_IT blob_it(blobs);
  int b_count = 0;
  int reject_count = 0;
  for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
    BLOBNBOX* blob = blob_it.data();
//    if (InsertBlob(true, true, blob, grid)) {
    if (InsertBlob(h_spread, v_spread, blob, grid)) {
      ++b_count;
    } else {
      ++reject_count;
    }
  }
  if (textord_debug_tabfind) {
    tprintf("Inserted %d blobs into grid, %d rejected.\n",
            b_count, reject_count);
  }
}
int tesseract::TabFind::LeftEdgeForBox ( const TBOX box,
bool  crossing,
bool  extended 
)

As RightEdgeForBox, but finds the left Edge instead.

Definition at line 311 of file tabfind.cpp.

                                                                         {
  TabVector* v = LeftTabForBox(box, crossing, extended);
  return v == NULL ? bleft_.x() : v->XAtY((box.top() + box.bottom()) / 2);
}
TabVector * tesseract::TabFind::LeftTabForBox ( const TBOX box,
bool  crossing,
bool  extended 
)

As RightTabForBox, but finds the left TabVector instead.

Definition at line 373 of file tabfind.cpp.

                                                 {
  if (v_it_.empty())
    return NULL;
  int top_y = box.top();
  int bottom_y = box.bottom();
  int mid_y = (top_y + bottom_y) / 2;
  int left = crossing ? (box.left() + box.right()) / 2 : box.left();
  int min_key, max_key;
  SetupTabSearch(left, mid_y, &min_key, &max_key);
  // Position the iterator at the last TabVector with sort_key <= max_key.
  while (!v_it_.at_last() && v_it_.data()->sort_key() <= max_key)
    v_it_.forward();
  while (!v_it_.at_first() && v_it_.data()->sort_key() > max_key) {
    v_it_.backward();
  }
  // Find the rightmost tab vector that overlaps and has XAtY(mid_y) <= left.
  TabVector* best_v = NULL;
  int best_x = -1;
  int key_limit = -1;
  do {
    TabVector* v = v_it_.data();
    int x = v->XAtY(mid_y);
    if (x <= left &&
        (v->VOverlap(top_y, bottom_y) > 0 ||
         (extended && v->ExtendedOverlap(top_y, bottom_y) > 0))) {
      if (best_v == NULL || x > best_x) {
        best_v = v;
        best_x = x;
        // We can guarantee that no better vector can be found if the
        // sort key is less than that of the best by max_key - min_key.
        key_limit = v->sort_key() - (max_key - min_key);
      }
    }
    // Break when the search is done to avoid wrapping the iterator and
    // thereby potentially slowing the next search.
    if (v_it_.at_first() ||
        (best_v != NULL && v->sort_key() < key_limit))
      break;  // Prevent restarting list for next call.
    v_it_.backward();
  } while (!v_it_.at_last());
  return best_v;
}
void tesseract::TabFind::ReflectInYAxis ( ) [protected]

Definition at line 1382 of file tabfind.cpp.

                             {
  TabVector_LIST temp_list;
  TabVector_IT temp_it(&temp_list);
  v_it_.move_to_first();
  // The TabVector list only contains vertical lines, but they need to be
  // reflected and the list needs to be reversed, so they are still in
  // sort_key order.
  while (!v_it_.empty()) {
    TabVector* v = v_it_.extract();
    v_it_.forward();
    v->ReflectInYAxis();
    temp_it.add_before_then_move(v);
  }
  v_it_.add_list_after(&temp_list);
  v_it_.move_to_first();
  // Reset this grid with reflected bounding boxes.
  TBOX grid_box(bleft(), tright());
  int tmp = grid_box.left();
  grid_box.set_left(-grid_box.right());
  grid_box.set_right(-tmp);
  Init(gridsize(), grid_box.botleft(), grid_box.topright());
}
void tesseract::TabFind::Reset ( ) [protected]

Definition at line 1371 of file tabfind.cpp.

                    {
  v_it_.move_to_first();
  for (v_it_.mark_cycle_pt(); !v_it_.cycled_list(); v_it_.forward()) {
    if (!v_it_.data()->IsSeparator())
      delete v_it_.extract();
  }
  Clear();
}
void tesseract::TabFind::ResetForVerticalText ( const FCOORD rotate,
const FCOORD rerotate,
TabVector_LIST *  horizontal_lines,
int *  min_gutter_width 
) [protected]

Definition at line 1326 of file tabfind.cpp.

                                                          {
  // Rotate the horizontal and vertical vectors and swap them over.
  // Only the separators are kept and rotated; other tabs are used
  // to estimate the gutter width then thrown away.
  TabVector_LIST ex_verticals;
  TabVector_IT ex_v_it(&ex_verticals);
  TabVector_LIST vlines;
  TabVector_IT v_it(&vlines);
  while (!v_it_.empty()) {
    TabVector* v = v_it_.extract();
    if (v->IsSeparator()) {
      v->Rotate(rotate);
      ex_v_it.add_after_then_move(v);
    } else {
      v_it.add_after_then_move(v);
    }
    v_it_.forward();
  }

  // Adjust the min gutter width for better tabbox selection
  // in 2nd call to FindInitialTabVectors().
  int median_gutter = FindMedianGutterWidth(&vlines);
  if (median_gutter > *min_gutter_width)
    *min_gutter_width = median_gutter;

  TabVector_IT h_it(horizontal_lines);
  for (h_it.mark_cycle_pt(); !h_it.cycled_list(); h_it.forward()) {
    TabVector* h = h_it.data();
    h->Rotate(rotate);
  }
  v_it_.add_list_after(horizontal_lines);
  v_it_.move_to_first();
  h_it.set_to_list(horizontal_lines);
  h_it.add_list_after(&ex_verticals);

  // Rebuild the grid to the new size.
  TBOX grid_box(bleft(), tright());
  grid_box.rotate_large(rotate);
  Init(gridsize(), grid_box.botleft(), grid_box.topright());
}
int tesseract::TabFind::RightEdgeForBox ( const TBOX box,
bool  crossing,
bool  extended 
)

Return the x-coord that corresponds to the right edge for the given box. If there is a rule line to the right that vertically overlaps it, then return the x-coord of the rule line, otherwise return the right edge of the page. For details see RightTabForBox below.

Definition at line 306 of file tabfind.cpp.

                                                                          {
  TabVector* v = RightTabForBox(box, crossing, extended);
  return v == NULL ? tright_.x() : v->XAtY((box.top() + box.bottom()) / 2);
}
TabVector * tesseract::TabFind::RightTabForBox ( const TBOX box,
bool  crossing,
bool  extended 
)

Return the TabVector that corresponds to the right edge for the given box. If there is a TabVector to the right that vertically overlaps it, then return it, otherwise return NULL. Note that Right and Left refer to the position of the TabVector, not its type, ie RightTabForBox returns the nearest TabVector to the right of the box, regardless of its type. If a TabVector crosses right through the box (as opposed to grazing one edge or missing entirely), then crossing false will ignore such a line. Crossing true will return the line for BOTH left and right edges. If extended is true, then TabVectors are considered to extend to their extended_start/end_y, otherwise, just the startpt_ and endpt_. These functions make use of an internal iterator to the vectors_ list for speed when used repeatedly on neighbouring boxes. The caveat is that the iterator must be updated whenever the list is modified.

Definition at line 329 of file tabfind.cpp.

                                                  {
  if (v_it_.empty())
    return NULL;
  int top_y = box.top();
  int bottom_y = box.bottom();
  int mid_y = (top_y + bottom_y) / 2;
  int right = crossing ? (box.left() + box.right()) / 2 : box.right();
  int min_key, max_key;
  SetupTabSearch(right, mid_y, &min_key, &max_key);
  // Position the iterator at the first TabVector with sort_key >= min_key.
  while (!v_it_.at_first() && v_it_.data()->sort_key() >= min_key)
    v_it_.backward();
  while (!v_it_.at_last() && v_it_.data()->sort_key() < min_key)
    v_it_.forward();
  // Find the leftmost tab vector that overlaps and has XAtY(mid_y) >= right.
  TabVector* best_v = NULL;
  int best_x = -1;
  int key_limit = -1;
  do {
    TabVector* v = v_it_.data();
    int x = v->XAtY(mid_y);
    if (x >= right &&
        (v->VOverlap(top_y, bottom_y) > 0 ||
         (extended && v->ExtendedOverlap(top_y, bottom_y) > 0))) {
      if (best_v == NULL || x < best_x) {
        best_v = v;
        best_x = x;
        // We can guarantee that no better vector can be found if the
        // sort key exceeds that of the best by max_key - min_key.
        key_limit = v->sort_key() + max_key - min_key;
      }
    }
    // Break when the search is done to avoid wrapping the iterator and
    // thereby potentially slowing the next search.
    if (v_it_.at_last() ||
        (best_v != NULL && v->sort_key() > key_limit))
      break;  // Prevent restarting list for next call.
    v_it_.forward();
  } while (!v_it_.at_first());
  return best_v;
}
void tesseract::TabFind::RotateBlobList ( const FCOORD rotation,
BLOBNBOX_LIST *  blobs 
) [static, protected]

Definition at line 1256 of file tabfind.cpp.

                                                                         {
  BLOBNBOX_IT it(blobs);
  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
    it.data()->rotate_box(rotation);
  }
}
void tesseract::TabFind::SetBlobRuleEdges ( BLOBNBOX_LIST *  blobs)

Definition at line 167 of file tabfind.cpp.

                                                   {
  BLOBNBOX_IT blob_it(blobs);
  for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
    BLOBNBOX* blob = blob_it.data();
    TBOX box = blob->bounding_box();
    blob->set_left_rule(LeftEdgeForBox(box, false, false));
    blob->set_right_rule(RightEdgeForBox(box, false, false));
    blob->set_left_crossing_rule(LeftEdgeForBox(box, true, false));
    blob->set_right_crossing_rule(RightEdgeForBox(box, true, false));
  }
}
void tesseract::TabFind::SetBlockRuleEdges ( TO_BLOCK block)

Definition at line 158 of file tabfind.cpp.

void tesseract::TabFind::SetupTabSearch ( int  x,
int  y,
int *  min_key,
int *  max_key 
) [protected]

Definition at line 518 of file tabfind.cpp.

                                                                     {
  int key1 = TabVector::SortKey(vertical_skew_, x, (y + tright_.y()) / 2);
  int key2 = TabVector::SortKey(vertical_skew_, x, (y + bleft_.y()) / 2);
  *min_key = MIN(key1, key2);
  *max_key = MAX(key1, key2);
}
void tesseract::TabFind::TidyBlobs ( TO_BLOCK block) [protected]

Definition at line 493 of file tabfind.cpp.

                                       {
  BLOBNBOX_IT large_it = &block->large_blobs;
  BLOBNBOX_IT blob_it = &block->blobs;
  int b_count = 0;
  for (large_it.mark_cycle_pt(); !large_it.cycled_list(); large_it.forward()) {
    BLOBNBOX* large_blob = large_it.data();
    if (large_blob->owner() != NULL) {
      blob_it.add_to_end(large_it.extract());
      ++b_count;
    }
  }
  if (textord_debug_tabfind) {
    tprintf("Moved %d large blobs to normal list\n",
            b_count);
    #ifndef GRAPHICS_DISABLED
    ScrollView* rej_win = MakeWindow(500, 300, "Image blobs");
    block->plot_graded_blobs(rej_win);
    block->plot_noise_blobs(rej_win);
    rej_win->Update();
    #endif  // GRAPHICS_DISABLED
  }
  block->DeleteUnownedNoise();
}
TabVector_LIST* tesseract::TabFind::vectors ( ) [inline, protected]

Accessors

Definition at line 182 of file tabfind.h.

                            {
    return &vectors_;
  }
bool tesseract::TabFind::VeryDifferentSizes ( int  size1,
int  size2 
) [static]

Return true if the sizes are more than a factor of 5 different.

Definition at line 438 of file tabfind.cpp.

                                                     {
  return size1 > size2 * 5 || size2 > size1 * 5;
}
WidthCallback* tesseract::TabFind::WidthCB ( ) [inline]

Return a callback for testing CommonWidth.

Definition at line 167 of file tabfind.h.

                           {
    return width_cb_;
  }

Member Data Documentation

Definition at line 360 of file tabfind.h.

Definition at line 359 of file tabfind.h.


The documentation for this class was generated from the following files: