tesseract  4.00.00dev
tesseract::PageIterator Class Reference

#include <pageiterator.h>

Inheritance diagram for tesseract::PageIterator:
tesseract::LTRResultIterator tesseract::ResultIterator tesseract::MutableIterator

Public Member Functions

 PageIterator (PAGE_RES *page_res, Tesseract *tesseract, int scale, int scaled_yres, int rect_left, int rect_top, int rect_width, int rect_height)
 
virtual ~PageIterator ()
 
 PageIterator (const PageIterator &src)
 
const PageIteratoroperator= (const PageIterator &src)
 
bool PositionedAtSameWord (const PAGE_RES_IT *other) const
 
virtual void Begin ()
 
virtual void RestartParagraph ()
 
bool IsWithinFirstTextlineOfParagraph () const
 
virtual void RestartRow ()
 
virtual bool Next (PageIteratorLevel level)
 
virtual bool IsAtBeginningOf (PageIteratorLevel level) const
 
virtual bool IsAtFinalElement (PageIteratorLevel level, PageIteratorLevel element) const
 
int Cmp (const PageIterator &other) const
 
void SetBoundingBoxComponents (bool include_upper_dots, bool include_lower_dots)
 
bool BoundingBox (PageIteratorLevel level, int *left, int *top, int *right, int *bottom) const
 
bool BoundingBox (PageIteratorLevel level, const int padding, int *left, int *top, int *right, int *bottom) const
 
bool BoundingBoxInternal (PageIteratorLevel level, int *left, int *top, int *right, int *bottom) const
 
bool Empty (PageIteratorLevel level) const
 
PolyBlockType BlockType () const
 
Pta * BlockPolygon () const
 
Pix * GetBinaryImage (PageIteratorLevel level) const
 
Pix * GetImage (PageIteratorLevel level, int padding, Pix *original_img, int *left, int *top) const
 
bool Baseline (PageIteratorLevel level, int *x1, int *y1, int *x2, int *y2) const
 
void Orientation (tesseract::Orientation *orientation, tesseract::WritingDirection *writing_direction, tesseract::TextlineOrder *textline_order, float *deskew_angle) const
 
void ParagraphInfo (tesseract::ParagraphJustification *justification, bool *is_list_item, bool *is_crown, int *first_line_indent) const
 
bool SetWordBlamerBundle (BlamerBundle *blamer_bundle)
 

Protected Member Functions

TESS_LOCAL void BeginWord (int offset)
 

Protected Attributes

PAGE_RESpage_res_
 
Tesseracttesseract_
 
PAGE_RES_ITit_
 
WERDword_
 
int word_length_
 
int blob_index_
 
C_BLOB_IT * cblob_it_
 
bool include_upper_dots_
 
bool include_lower_dots_
 
int scale_
 
int scaled_yres_
 
int rect_left_
 
int rect_top_
 
int rect_width_
 
int rect_height_
 

Detailed Description

Class to iterate over tesseract page structure, providing access to all levels of the page hierarchy, without including any tesseract headers or having to handle any tesseract structures. WARNING! This class points to data held within the TessBaseAPI class, and therefore can only be used while the TessBaseAPI class still exists and has not been subjected to a call of Init, SetImage, Recognize, Clear, End DetectOS, or anything else that changes the internal PAGE_RES. See apitypes.h for the definition of PageIteratorLevel. See also ResultIterator, derived from PageIterator, which adds in the ability to access OCR output with text-specific methods.

Definition at line 52 of file pageiterator.h.

Constructor & Destructor Documentation

◆ PageIterator() [1/2]

tesseract::PageIterator::PageIterator ( PAGE_RES page_res,
Tesseract tesseract,
int  scale,
int  scaled_yres,
int  rect_left,
int  rect_top,
int  rect_width,
int  rect_height 
)

page_res and tesseract come directly from the BaseAPI. The rectangle parameters are copied indirectly from the Thresholder, via the BaseAPI. They represent the coordinates of some rectangle in an original image (in top-left-origin coordinates) and therefore the top-left needs to be added to any output boxes in order to specify coordinates in the original image. See TessBaseAPI::SetRectangle. The scale and scaled_yres are in case the Thresholder scaled the image rectangle prior to thresholding. Any coordinates in tesseract's image must be divided by scale before adding (rect_left, rect_top). The scaled_yres indicates the effective resolution of the binary image that tesseract has been given by the Thresholder. After the constructor, Begin has already been called.

Definition at line 29 of file pageiterator.cpp.

32  : page_res_(page_res),
34  word_(NULL),
35  word_length_(0),
36  blob_index_(0),
37  cblob_it_(NULL),
38  include_upper_dots_(false),
39  include_lower_dots_(false),
40  scale_(scale),
41  scaled_yres_(scaled_yres),
42  rect_left_(rect_left),
43  rect_top_(rect_top),
44  rect_width_(rect_width),
45  rect_height_(rect_height) {
46  it_ = new PAGE_RES_IT(page_res);
48 }

◆ ~PageIterator()

tesseract::PageIterator::~PageIterator ( )
virtual

Definition at line 50 of file pageiterator.cpp.

50  {
51  delete it_;
52  delete cblob_it_;
53 }

◆ PageIterator() [2/2]

tesseract::PageIterator::PageIterator ( const PageIterator src)

Page/ResultIterators may be copied! This makes it possible to iterate over all the objects at a lower level, while maintaining an iterator to objects at a higher level. These constructors DO NOT CALL Begin, so iterations will continue from the location of src.

PageIterators may be copied! This makes it possible to iterate over all the objects at a lower level, while maintaining an iterator to objects at a higher level.

Definition at line 60 of file pageiterator.cpp.

61  : page_res_(src.page_res_),
62  tesseract_(src.tesseract_),
63  word_(NULL),
64  word_length_(src.word_length_),
65  blob_index_(src.blob_index_),
66  cblob_it_(NULL),
67  include_upper_dots_(src.include_upper_dots_),
68  include_lower_dots_(src.include_lower_dots_),
69  scale_(src.scale_),
70  scaled_yres_(src.scaled_yres_),
71  rect_left_(src.rect_left_),
72  rect_top_(src.rect_top_),
73  rect_width_(src.rect_width_),
74  rect_height_(src.rect_height_) {
75  it_ = new PAGE_RES_IT(*src.it_);
76  BeginWord(src.blob_index_);
77 }
TESS_LOCAL void BeginWord(int offset)

Member Function Documentation

◆ Baseline()

bool tesseract::PageIterator::Baseline ( PageIteratorLevel  level,
int x1,
int y1,
int x2,
int y2 
) const

Returns the baseline of the current object at the given level. The baseline is the line that passes through (x1, y1) and (x2, y2). WARNING: with vertical text, baselines may be vertical! Returns false if there is no baseline at the current position.

Returns the baseline of the current object at the given level. The baseline is the line that passes through (x1, y1) and (x2, y2). WARNING: with vertical text, baselines may be vertical!

Definition at line 487 of file pageiterator.cpp.

488  {
489  if (it_->word() == NULL) return false; // Already at the end!
490  ROW* row = it_->row()->row;
491  WERD* word = it_->word()->word;
492  TBOX box = (level == RIL_WORD || level == RIL_SYMBOL)
493  ? word->bounding_box()
494  : row->bounding_box();
495  int left = box.left();
496  ICOORD startpt(left, static_cast<inT16>(row->base_line(left) + 0.5));
497  int right = box.right();
498  ICOORD endpt(right, static_cast<inT16>(row->base_line(right) + 0.5));
499  // Rotate to image coordinates and convert to global image coords.
500  startpt.rotate(it_->block()->block->re_rotation());
501  endpt.rotate(it_->block()->block->re_rotation());
502  *x1 = startpt.x() / scale_ + rect_left_;
503  *y1 = (rect_height_ - startpt.y()) / scale_ + rect_top_;
504  *x2 = endpt.x() / scale_ + rect_left_;
505  *y2 = (rect_height_ - endpt.y()) / scale_ + rect_top_;
506  return true;
507 }
void rotate(const FCOORD &vec)
Definition: ipoints.h:241
BLOCK * block
Definition: pageres.h:99
ROW * row
Definition: pageres.h:127
TBOX bounding_box() const
Definition: werd.cpp:160
ROW_RES * row() const
Definition: pageres.h:739
inT16 left() const
Definition: rect.h:68
TBOX bounding_box() const
Definition: ocrrow.h:85
Definition: rect.h:30
WERD * word
Definition: pageres.h:175
inT16 right() const
Definition: rect.h:75
FCOORD re_rotation() const
Definition: ocrblock.h:138
WERD_RES * word() const
Definition: pageres.h:736
float base_line(float xpos) const
Definition: ocrrow.h:56
Definition: werd.h:60
Definition: ocrrow.h:32
BLOCK_RES * block() const
Definition: pageres.h:742
integer coordinate
Definition: points.h:30

◆ Begin()

void tesseract::PageIterator::Begin ( )
virtual

Moves the iterator to point to the start of the page to begin an iteration.

Resets the iterator to point to the start of the page.

Reimplemented in tesseract::ResultIterator.

Definition at line 104 of file pageiterator.cpp.

104  {
106  BeginWord(0);
107 }
WERD_RES * restart_page_with_empties()
Definition: pageres.h:686
TESS_LOCAL void BeginWord(int offset)

◆ BeginWord()

void tesseract::PageIterator::BeginWord ( int  offset)
protected

Sets up the internal data for iterating the blobs of a new word, then moves the iterator to the given offset.

Definition at line 576 of file pageiterator.cpp.

576  {
577  WERD_RES* word_res = it_->word();
578  if (word_res == NULL) {
579  // This is a non-text block, so there is no word.
580  word_length_ = 0;
581  blob_index_ = 0;
582  word_ = NULL;
583  return;
584  }
585  if (word_res->best_choice != NULL) {
586  // Recognition has been done, so we are using the box_word, which
587  // is already baseline denormalized.
588  word_length_ = word_res->best_choice->length();
589  if (word_res->box_word != NULL) {
590  if (word_res->box_word->length() != word_length_) {
591  tprintf("Corrupted word! best_choice[len=%d] = %s, box_word[len=%d]: ",
593  word_res->box_word->length());
594  word_res->box_word->bounding_box().print();
595  }
596  ASSERT_HOST(word_res->box_word->length() == word_length_);
597  }
598  word_ = NULL;
599  // We will be iterating the box_word.
600  delete cblob_it_;
601  cblob_it_ = NULL;
602  } else {
603  // No recognition yet, so a "symbol" is a cblob.
604  word_ = word_res->word;
605  ASSERT_HOST(word_->cblob_list() != NULL);
606  word_length_ = word_->cblob_list()->length();
607  if (cblob_it_ == NULL) cblob_it_ = new C_BLOB_IT;
608  cblob_it_->set_to_list(word_->cblob_list());
609  }
610  for (blob_index_ = 0; blob_index_ < offset; ++blob_index_) {
611  if (cblob_it_ != NULL)
612  cblob_it_->forward();
613  }
614 }
WERD_CHOICE * best_choice
Definition: pageres.h:219
int length() const
Definition: ratngs.h:301
#define tprintf(...)
Definition: tprintf.h:31
const TBOX & bounding_box() const
Definition: boxword.h:82
const char * string() const
Definition: strngs.cpp:198
voidpf uLong offset
Definition: ioapi.h:42
tesseract::BoxWord * box_word
Definition: pageres.h:250
#define ASSERT_HOST(x)
Definition: errcode.h:84
const STRING & unichar_string() const
Definition: ratngs.h:539
C_BLOB_LIST * cblob_list()
Definition: werd.h:100
WERD * word
Definition: pageres.h:175
void print() const
Definition: rect.h:270
WERD_RES * word() const
Definition: pageres.h:736
int length() const
Definition: boxword.h:85

◆ BlockPolygon()

Pta * tesseract::PageIterator::BlockPolygon ( ) const

Returns the polygon outline of the current block. The returned Pta must be ptaDestroy-ed after use. Note that the returned Pta lists the vertices of the polygon, and the last edge is the line segment between the last point and the first point. NULL will be returned if the iterator is at the end of the document or layout analysis was not used.

Returns the polygon outline of the current block. The returned Pta must be ptaDestroy-ed after use.

Definition at line 367 of file pageiterator.cpp.

367  {
368  if (it_->block() == NULL || it_->block()->block == NULL)
369  return NULL; // Already at the end!
370  if (it_->block()->block->poly_block() == NULL)
371  return NULL; // No layout analysis used - no polygon.
372  ICOORDELT_IT it(it_->block()->block->poly_block()->points());
373  Pta* pta = ptaCreate(it.length());
374  int num_pts = 0;
375  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward(), ++num_pts) {
376  ICOORD* pt = it.data();
377  // Convert to top-down coords within the input image.
378  float x = static_cast<float>(pt->x()) / scale_ + rect_left_;
379  float y = rect_top_ + rect_height_ - static_cast<float>(pt->y()) / scale_;
380  ptaAddPt(pta, x, y);
381  }
382  return pta;
383 }
ICOORDELT_LIST * points()
Definition: polyblk.h:42
inT16 x() const
access function
Definition: points.h:52
BLOCK * block
Definition: pageres.h:99
inT16 y() const
access_function
Definition: points.h:56
POLY_BLOCK * poly_block() const
Definition: pdblock.h:55
BLOCK_RES * block() const
Definition: pageres.h:742
integer coordinate
Definition: points.h:30

◆ BlockType()

PolyBlockType tesseract::PageIterator::BlockType ( ) const

Returns the type of the current block. See apitypes.h for PolyBlockType.

Definition at line 357 of file pageiterator.cpp.

357  {
358  if (it_->block() == NULL || it_->block()->block == NULL)
359  return PT_UNKNOWN; // Already at the end!
360  if (it_->block()->block->poly_block() == NULL)
361  return PT_FLOWING_TEXT; // No layout analysis used - assume text.
362  return it_->block()->block->poly_block()->isA();
363 }
BLOCK * block
Definition: pageres.h:99
POLY_BLOCK * poly_block() const
Definition: pdblock.h:55
PolyBlockType isA() const
Definition: polyblk.h:48
BLOCK_RES * block() const
Definition: pageres.h:742

◆ BoundingBox() [1/2]

bool tesseract::PageIterator::BoundingBox ( PageIteratorLevel  level,
int left,
int top,
int right,
int bottom 
) const

Returns the bounding rectangle of the current object at the given level. See comment on coordinate system above. Returns false if there is no such object at the current position. The returned bounding box is guaranteed to match the size and position of the image returned by GetBinaryImage, but may clip foreground pixels from a grey image. The padding argument to GetImage can be used to expand the image to include more foreground pixels. See GetImage below.

Returns the bounding rectangle of the current object at the given level in coordinates of the original image. See comment on coordinate system above. Returns false if there is no such object at the current position.

Definition at line 324 of file pageiterator.cpp.

326  {
327  return BoundingBox(level, 0, left, top, right, bottom);
328 }
bool BoundingBox(PageIteratorLevel level, int *left, int *top, int *right, int *bottom) const

◆ BoundingBox() [2/2]

bool tesseract::PageIterator::BoundingBox ( PageIteratorLevel  level,
const int  padding,
int left,
int top,
int right,
int bottom 
) const

Definition at line 330 of file pageiterator.cpp.

332  {
333  if (!BoundingBoxInternal(level, left, top, right, bottom))
334  return false;
335  // Convert to the coordinate system of the original image.
336  *left = ClipToRange(*left / scale_ + rect_left_ - padding,
338  *top = ClipToRange(*top / scale_ + rect_top_ - padding,
340  *right = ClipToRange((*right + scale_ - 1) / scale_ + rect_left_ + padding,
341  *left, rect_left_ + rect_width_);
342  *bottom = ClipToRange((*bottom + scale_ - 1) / scale_ + rect_top_ + padding,
343  *top, rect_top_ + rect_height_);
344  return true;
345 }
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
Definition: helpers.h:122
bool BoundingBoxInternal(PageIteratorLevel level, int *left, int *top, int *right, int *bottom) const

◆ BoundingBoxInternal()

bool tesseract::PageIterator::BoundingBoxInternal ( PageIteratorLevel  level,
int left,
int top,
int right,
int bottom 
) const

Returns the bounding rectangle of the object in a coordinate system of the working image rectangle having its origin at (rect_left_, rect_top_) with respect to the original image and is scaled by a factor scale_.

Returns the bounding rectangle of the current object at the given level in the coordinates of the working image that is pix_binary(). See comment on coordinate system above. Returns false if there is no such object at the current position.

Definition at line 264 of file pageiterator.cpp.

266  {
267  if (Empty(level))
268  return false;
269  TBOX box;
270  PARA *para = NULL;
271  switch (level) {
272  case RIL_BLOCK:
275  break;
276  case RIL_PARA:
277  para = it_->row()->row->para();
278  // explicit fall-through.
279  case RIL_TEXTLINE:
282  break;
283  case RIL_WORD:
286  break;
287  case RIL_SYMBOL:
288  if (cblob_it_ == NULL)
289  box = it_->word()->box_word->BlobBox(blob_index_);
290  else
291  box = cblob_it_->data()->bounding_box();
292  }
293  if (level == RIL_PARA) {
294  PageIterator other = *this;
295  other.Begin();
296  do {
297  if (other.it_->block() &&
298  other.it_->block()->block == it_->block()->block &&
299  other.it_->row() && other.it_->row()->row &&
300  other.it_->row()->row->para() == para) {
301  box = box.bounding_union(other.it_->row()->row->bounding_box());
302  }
303  } while (other.Next(RIL_TEXTLINE));
304  }
305  if (level != RIL_SYMBOL || cblob_it_ != NULL)
306  box.rotate(it_->block()->block->re_rotation());
307  // Now we have a box in tesseract coordinates relative to the image rectangle,
308  // we have to convert the coords to a top-down system.
309  const int pix_height = pixGetHeight(tesseract_->pix_binary());
310  const int pix_width = pixGetWidth(tesseract_->pix_binary());
311  *left = ClipToRange(static_cast<int>(box.left()), 0, pix_width);
312  *top = ClipToRange(pix_height - box.top(), 0, pix_height);
313  *right = ClipToRange(static_cast<int>(box.right()), *left, pix_width);
314  *bottom = ClipToRange(pix_height - box.bottom(), *top, pix_height);
315  return true;
316 }
bool Empty(PageIteratorLevel level) const
const TBOX & BlobBox(int index) const
Definition: boxword.h:86
Pix * pix_binary() const
TBOX bounding_union(const TBOX &box) const
Definition: rect.cpp:129
BLOCK * block
Definition: pageres.h:99
ROW * row
Definition: pageres.h:127
TBOX restricted_bounding_box(bool upper_dots, bool lower_dots) const
Definition: ocrrow.cpp:85
PageIterator(PAGE_RES *page_res, Tesseract *tesseract, int scale, int scaled_yres, int rect_left, int rect_top, int rect_width, int rect_height)
tesseract::BoxWord * box_word
Definition: pageres.h:250
ROW_RES * row() const
Definition: pageres.h:739
inT16 left() const
Definition: rect.h:68
T ClipToRange(const T &x, const T &lower_bound, const T &upper_bound)
Definition: helpers.h:122
inT16 top() const
Definition: rect.h:54
TBOX restricted_bounding_box(bool upper_dots, bool lower_dots) const
Definition: werd.cpp:164
Definition: rect.h:30
WERD * word
Definition: pageres.h:175
inT16 right() const
Definition: rect.h:75
FCOORD re_rotation() const
Definition: ocrblock.h:138
Definition: ocrpara.h:29
WERD_RES * word() const
Definition: pageres.h:736
inT16 bottom() const
Definition: rect.h:61
PARA * para() const
Definition: ocrrow.h:115
void rotate(const FCOORD &vec)
Definition: rect.h:189
BLOCK_RES * block() const
Definition: pageres.h:742
TBOX restricted_bounding_box(bool upper_dots, bool lower_dots) const
Definition: ocrblock.cpp:92

◆ Cmp()

int tesseract::PageIterator::Cmp ( const PageIterator other) const

Returns whether this iterator is positioned before other: -1 equal to other: 0 after other: 1

Definition at line 234 of file pageiterator.cpp.

234  {
235  int word_cmp = it_->cmp(*other.it_);
236  if (word_cmp != 0)
237  return word_cmp;
238  if (blob_index_ < other.blob_index_)
239  return -1;
240  if (blob_index_ == other.blob_index_)
241  return 0;
242  return 1;
243 }
int cmp(const PAGE_RES_IT &other) const
Definition: pageres.cpp:1202

◆ Empty()

bool tesseract::PageIterator::Empty ( PageIteratorLevel  level) const

Returns whether there is no object of a given level.

Return that there is no such object at a given level.

Definition at line 348 of file pageiterator.cpp.

348  {
349  if (it_->block() == NULL) return true; // Already at the end!
350  if (it_->word() == NULL && level != RIL_BLOCK) return true; // image block
351  if (level == RIL_SYMBOL && blob_index_ >= word_length_)
352  return true; // Zero length word, or already at the end of it.
353  return false;
354 }
WERD_RES * word() const
Definition: pageres.h:736
BLOCK_RES * block() const
Definition: pageres.h:742

◆ GetBinaryImage()

Pix * tesseract::PageIterator::GetBinaryImage ( PageIteratorLevel  level) const

Returns a binary image of the current object at the given level. The position and size match the return from BoundingBoxInternal, and so this could be upscaled with respect to the original input image. Use pixDestroy to delete the image after use.

Returns a binary image of the current object at the given level. The position and size match the return from BoundingBoxInternal, and so this could be upscaled with respect to the original input image. Use pixDestroy to delete the image after use. The following methods are used to generate the images: RIL_BLOCK: mask the page image with the block polygon. RIL_TEXTLINE: Clip the rectangle of the line box from the page image. TODO(rays) fix this to generate and use a line polygon. RIL_WORD: Clip the rectangle of the word box from the page image. RIL_SYMBOL: Render the symbol outline to an image for cblobs (prior to recognition) or the bounding box otherwise. A reconstruction of the original image (using xor to check for double representation) should be reasonably accurate, apart from removed noise, at the block level. Below the block level, the reconstruction will be missing images and line separators. At the symbol level, kerned characters will be invade the bounding box if rendered after recognition, making an xor reconstruction inaccurate, but an or construction better. Before recognition, symbol-level reconstruction should be good, even with xor, since the images come from the connected components.

Definition at line 407 of file pageiterator.cpp.

407  {
408  int left, top, right, bottom;
409  if (!BoundingBoxInternal(level, &left, &top, &right, &bottom))
410  return NULL;
411  if (level == RIL_SYMBOL && cblob_it_ != NULL &&
412  cblob_it_->data()->area() != 0)
413  return cblob_it_->data()->render();
414  Box* box = boxCreate(left, top, right - left, bottom - top);
415  Pix* pix = pixClipRectangle(tesseract_->pix_binary(), box, NULL);
416  boxDestroy(&box);
417  if (level == RIL_BLOCK || level == RIL_PARA) {
418  // Clip to the block polygon as well.
419  TBOX mask_box;
420  Pix* mask = it_->block()->block->render_mask(&mask_box);
421  int mask_x = left - mask_box.left();
422  int mask_y = top - (tesseract_->ImageHeight() - mask_box.top());
423  // AND the mask and pix, putting the result in pix.
424  pixRasterop(pix, MAX(0, -mask_x), MAX(0, -mask_y), pixGetWidth(pix),
425  pixGetHeight(pix), PIX_SRC & PIX_DST, mask, MAX(0, mask_x),
426  MAX(0, mask_y));
427  pixDestroy(&mask);
428  }
429  return pix;
430 }
Pix * pix_binary() const
BLOCK * block
Definition: pageres.h:99
inT16 left() const
Definition: rect.h:68
Pix * render_mask(TBOX *mask_box)
Definition: ocrblock.h:164
inT16 top() const
Definition: rect.h:54
#define MAX(x, y)
Definition: ndminx.h:24
Definition: rect.h:30
bool BoundingBoxInternal(PageIteratorLevel level, int *left, int *top, int *right, int *bottom) const
BLOCK_RES * block() const
Definition: pageres.h:742

◆ GetImage()

Pix * tesseract::PageIterator::GetImage ( PageIteratorLevel  level,
int  padding,
Pix *  original_img,
int left,
int top 
) const

Returns an image of the current object at the given level in greyscale if available in the input. To guarantee a binary image use BinaryImage. NOTE that in order to give the best possible image, the bounds are expanded slightly over the binary connected component, by the supplied padding, so the top-left position of the returned image is returned in (left,top). These will most likely not match the coordinates returned by BoundingBox. If you do not supply an original image, you will get a binary one. Use pixDestroy to delete the image after use.

Definition at line 443 of file pageiterator.cpp.

445  {
446  int right, bottom;
447  if (!BoundingBox(level, left, top, &right, &bottom))
448  return NULL;
449  if (original_img == NULL)
450  return GetBinaryImage(level);
451 
452  // Expand the box.
453  *left = MAX(*left - padding, 0);
454  *top = MAX(*top - padding, 0);
455  right = MIN(right + padding, rect_width_);
456  bottom = MIN(bottom + padding, rect_height_);
457  Box* box = boxCreate(*left, *top, right - *left, bottom - *top);
458  Pix* grey_pix = pixClipRectangle(original_img, box, NULL);
459  boxDestroy(&box);
460  if (level == RIL_BLOCK || level == RIL_PARA) {
461  // Clip to the block polygon as well.
462  TBOX mask_box;
463  Pix* mask = it_->block()->block->render_mask(&mask_box);
464  // Copy the mask registered correctly into an image the size of grey_pix.
465  int mask_x = *left - mask_box.left();
466  int mask_y = *top - (pixGetHeight(original_img) - mask_box.top());
467  int width = pixGetWidth(grey_pix);
468  int height = pixGetHeight(grey_pix);
469  Pix* resized_mask = pixCreate(width, height, 1);
470  pixRasterop(resized_mask, MAX(0, -mask_x), MAX(0, -mask_y), width, height,
471  PIX_SRC, mask, MAX(0, mask_x), MAX(0, mask_y));
472  pixDestroy(&mask);
473  pixDilateBrick(resized_mask, resized_mask, 2 * padding + 1,
474  2 * padding + 1);
475  pixInvert(resized_mask, resized_mask);
476  pixSetMasked(grey_pix, resized_mask, MAX_UINT32);
477  pixDestroy(&resized_mask);
478  }
479  return grey_pix;
480 }
BLOCK * block
Definition: pageres.h:99
Pix * GetBinaryImage(PageIteratorLevel level) const
inT16 left() const
Definition: rect.h:68
Pix * render_mask(TBOX *mask_box)
Definition: ocrblock.h:164
inT16 top() const
Definition: rect.h:54
#define MAX(x, y)
Definition: ndminx.h:24
Definition: rect.h:30
#define MAX_UINT32
Definition: host.h:65
#define MIN(x, y)
Definition: ndminx.h:28
bool BoundingBox(PageIteratorLevel level, int *left, int *top, int *right, int *bottom) const
BLOCK_RES * block() const
Definition: pageres.h:742

◆ IsAtBeginningOf()

bool tesseract::PageIterator::IsAtBeginningOf ( PageIteratorLevel  level) const
virtual

Returns true if the iterator is at the start of an object at the given level.

For instance, suppose an iterator it is pointed to the first symbol of the first word of the third line of the second paragraph of the first block in a page, then: it.IsAtBeginningOf(RIL_BLOCK) = false it.IsAtBeginningOf(RIL_PARA) = false it.IsAtBeginningOf(RIL_TEXTLINE) = true it.IsAtBeginningOf(RIL_WORD) = true it.IsAtBeginningOf(RIL_SYMBOL) = true

Returns true if the iterator is at the start of an object at the given level. Possible uses include determining if a call to Next(RIL_WORD) moved to the start of a RIL_PARA.

Reimplemented in tesseract::ResultIterator.

Definition at line 184 of file pageiterator.cpp.

184  {
185  if (it_->block() == NULL) return false; // Already at the end!
186  if (it_->word() == NULL) return true; // In an image block.
187  switch (level) {
188  case RIL_BLOCK:
189  return blob_index_ == 0 && it_->block() != it_->prev_block();
190  case RIL_PARA:
191  return blob_index_ == 0 &&
192  (it_->block() != it_->prev_block() ||
193  it_->row()->row->para() != it_->prev_row()->row->para());
194  case RIL_TEXTLINE:
195  return blob_index_ == 0 && it_->row() != it_->prev_row();
196  case RIL_WORD:
197  return blob_index_ == 0;
198  case RIL_SYMBOL:
199  return true;
200  }
201  return false;
202 }
ROW_RES * prev_row() const
Definition: pageres.h:730
ROW * row
Definition: pageres.h:127
ROW_RES * row() const
Definition: pageres.h:739
WERD_RES * word() const
Definition: pageres.h:736
PARA * para() const
Definition: ocrrow.h:115
BLOCK_RES * prev_block() const
Definition: pageres.h:733
BLOCK_RES * block() const
Definition: pageres.h:742

◆ IsAtFinalElement()

bool tesseract::PageIterator::IsAtFinalElement ( PageIteratorLevel  level,
PageIteratorLevel  element 
) const
virtual

Returns whether the iterator is positioned at the last element in a given level. (e.g. the last word in a line, the last line in a block)

Here's some two-paragraph example

text. It starts off innocuously enough but quickly turns bizarre. The author inserts a cornucopia of words to guard against confused references.

Now take an iterator it pointed to the start of "bizarre." it.IsAtFinalElement(RIL_PARA, RIL_SYMBOL) = false it.IsAtFinalElement(RIL_PARA, RIL_WORD) = true it.IsAtFinalElement(RIL_BLOCK, RIL_WORD) = false

Returns whether the iterator is positioned at the last element in a given level. (e.g. the last word in a line, the last line in a block)

Reimplemented in tesseract::ResultIterator.

Definition at line 208 of file pageiterator.cpp.

209  {
210  if (Empty(element)) return true; // Already at the end!
211  // The result is true if we step forward by element and find we are
212  // at the the end of the page or at beginning of *all* levels in:
213  // [level, element).
214  // When there is more than one level difference between element and level,
215  // we could for instance move forward one symbol and still be at the first
216  // word on a line, so we also have to be at the first symbol in a word.
217  PageIterator next(*this);
218  next.Next(element);
219  if (next.Empty(element)) return true; // Reached the end of the page.
220  while (element > level) {
221  element = static_cast<PageIteratorLevel>(element - 1);
222  if (!next.IsAtBeginningOf(element))
223  return false;
224  }
225  return true;
226 }
bool Empty(PageIteratorLevel level) const
PageIterator(PAGE_RES *page_res, Tesseract *tesseract, int scale, int scaled_yres, int rect_left, int rect_top, int rect_width, int rect_height)

◆ IsWithinFirstTextlineOfParagraph()

bool tesseract::PageIterator::IsWithinFirstTextlineOfParagraph ( ) const

Return whether this iterator points anywhere in the first textline of a paragraph.

Definition at line 122 of file pageiterator.cpp.

122  {
123  PageIterator p_start(*this);
124  p_start.RestartParagraph();
125  return p_start.it_->row() == it_->row();
126 }
PageIterator(PAGE_RES *page_res, Tesseract *tesseract, int scale, int scaled_yres, int rect_left, int rect_top, int rect_width, int rect_height)
ROW_RES * row() const
Definition: pageres.h:739

◆ Next()

bool tesseract::PageIterator::Next ( PageIteratorLevel  level)
virtual

Moves to the start of the next object at the given level in the page hierarchy, and returns false if the end of the page was reached. NOTE that RIL_SYMBOL will skip non-text blocks, but all other PageIteratorLevel level values will visit each non-text block once. Think of non text blocks as containing a single para, with a single line, with a single imaginary word. Calls to Next with different levels may be freely intermixed. This function iterates words in right-to-left scripts correctly, if the appropriate language has been loaded into Tesseract.

Moves to the start of the next object at the given level in the page hierarchy, and returns false if the end of the page was reached. NOTE (CHANGED!) that ALL PageIteratorLevel level values will visit each non-text block at least once. Think of non text blocks as containing a single para, with at least one line, with a single imaginary word, containing a single symbol. The bounding boxes mark out any polygonal nature of the block, and PTIsTextType(BLockType()) is false for non-text blocks. Calls to Next with different levels may be freely intermixed. This function iterates words in right-to-left scripts correctly, if the appropriate language has been loaded into Tesseract.

Reimplemented in tesseract::ResultIterator.

Definition at line 146 of file pageiterator.cpp.

146  {
147  if (it_->block() == NULL) return false; // Already at the end!
148  if (it_->word() == NULL)
149  level = RIL_BLOCK;
150 
151  switch (level) {
152  case RIL_BLOCK:
153  it_->forward_block();
154  break;
155  case RIL_PARA:
157  break;
158  case RIL_TEXTLINE:
159  for (it_->forward_with_empties(); it_->row() == it_->prev_row();
161  break;
162  case RIL_WORD:
164  break;
165  case RIL_SYMBOL:
166  if (cblob_it_ != NULL)
167  cblob_it_->forward();
168  ++blob_index_;
169  if (blob_index_ >= word_length_)
171  else
172  return true;
173  break;
174  }
175  BeginWord(0);
176  return it_->block() != NULL;
177 }
WERD_RES * forward_paragraph()
Definition: pageres.cpp:1653
ROW_RES * prev_row() const
Definition: pageres.h:730
ROW_RES * row() const
Definition: pageres.h:739
WERD_RES * forward_with_empties()
Definition: pageres.h:720
WERD_RES * forward_block()
Definition: pageres.cpp:1668
TESS_LOCAL void BeginWord(int offset)
WERD_RES * word() const
Definition: pageres.h:736
BLOCK_RES * block() const
Definition: pageres.h:742

◆ operator=()

const PageIterator & tesseract::PageIterator::operator= ( const PageIterator src)

Definition at line 79 of file pageiterator.cpp.

79  {
80  page_res_ = src.page_res_;
81  tesseract_ = src.tesseract_;
82  include_upper_dots_ = src.include_upper_dots_;
83  include_lower_dots_ = src.include_lower_dots_;
84  scale_ = src.scale_;
85  scaled_yres_ = src.scaled_yres_;
86  rect_left_ = src.rect_left_;
87  rect_top_ = src.rect_top_;
88  rect_width_ = src.rect_width_;
89  rect_height_ = src.rect_height_;
90  delete it_;
91  it_ = new PAGE_RES_IT(*src.it_);
92  BeginWord(src.blob_index_);
93  return *this;
94 }
TESS_LOCAL void BeginWord(int offset)

◆ Orientation()

void tesseract::PageIterator::Orientation ( tesseract::Orientation orientation,
tesseract::WritingDirection writing_direction,
tesseract::TextlineOrder textline_order,
float *  deskew_angle 
) const

Returns orientation for the block the iterator points to. orientation, writing_direction, textline_order: see publictypes.h deskew_angle: after rotating the block so the text orientation is upright, how many radians does one have to rotate the block anti-clockwise for it to be level? -Pi/4 <= deskew_angle <= Pi/4

Definition at line 509 of file pageiterator.cpp.

512  {
513  BLOCK* block = it_->block()->block;
514 
515  // Orientation
516  FCOORD up_in_image(0.0, 1.0);
517  up_in_image.unrotate(block->classify_rotation());
518  up_in_image.rotate(block->re_rotation());
519 
520  if (up_in_image.x() == 0.0F) {
521  if (up_in_image.y() > 0.0F) {
522  *orientation = ORIENTATION_PAGE_UP;
523  } else {
524  *orientation = ORIENTATION_PAGE_DOWN;
525  }
526  } else if (up_in_image.x() > 0.0F) {
527  *orientation = ORIENTATION_PAGE_RIGHT;
528  } else {
529  *orientation = ORIENTATION_PAGE_LEFT;
530  }
531 
532  // Writing direction
533  bool is_vertical_text = (block->classify_rotation().x() == 0.0);
534  bool right_to_left = block->right_to_left();
535  *writing_direction =
536  is_vertical_text
538  : (right_to_left
541 
542  // Textline Order
543  bool is_mongolian = false; // TODO(eger): fix me
544  *textline_order = is_vertical_text
545  ? (is_mongolian
549 
550  // Deskew angle
551  FCOORD skew = block->skew(); // true horizontal for textlines
552  *deskew_angle = -skew.angle();
553 }
Definition: points.h:189
FCOORD skew() const
Definition: ocrblock.h:150
float angle() const
find angle
Definition: points.h:249
BLOCK * block
Definition: pageres.h:99
FCOORD re_rotation() const
Definition: ocrblock.h:138
bool right_to_left() const
Definition: ocrblock.h:83
float x() const
Definition: points.h:209
FCOORD classify_rotation() const
Definition: ocrblock.h:144
Definition: ocrblock.h:30
BLOCK_RES * block() const
Definition: pageres.h:742

◆ ParagraphInfo()

void tesseract::PageIterator::ParagraphInfo ( tesseract::ParagraphJustification justification,
bool *  is_list_item,
bool *  is_crown,
int first_line_indent 
) const

Returns information about the current paragraph, if available.

justification - LEFT if ragged right, or fully justified and script is left-to-right. RIGHT if ragged left, or fully justified and script is right-to-left. unknown if it looks like source code or we have very few lines. is_list_item - true if we believe this is a member of an ordered or unordered list. is_crown - true if the first line of the paragraph is aligned with the other lines of the paragraph even though subsequent paragraphs have first line indents. This typically indicates that this is the continuation of a previous paragraph or that it is the very first paragraph in the chapter. first_line_indent - For LEFT aligned paragraphs, the first text line of paragraphs of this kind are indented this many pixels from the left edge of the rest of the paragraph. for RIGHT aligned paragraphs, the first text line of paragraphs of this kind are indented this many pixels from the right edge of the rest of the paragraph. NOTE 1: This value may be negative. NOTE 2: if *is_crown == true, the first line of this paragraph is actually flush, and first_line_indent is set to the "common" first_line_indent for subsequent paragraphs in this block of text.

Definition at line 555 of file pageiterator.cpp.

558  {
560  if (!it_->row() || !it_->row()->row || !it_->row()->row->para() ||
561  !it_->row()->row->para()->model)
562  return;
563 
564  PARA *para = it_->row()->row->para();
565  *is_list_item = para->is_list_item;
566  *is_crown = para->is_very_first_or_continuation;
567  *first_line_indent = para->model->first_indent() -
568  para->model->body_indent();
569  *just = para->model->justification();
570 }
tesseract::ParagraphJustification justification() const
Definition: ocrpara.h:164
int body_indent() const
Definition: ocrpara.h:169
int first_indent() const
Definition: ocrpara.h:168
ROW * row
Definition: pageres.h:127
ROW_RES * row() const
Definition: pageres.h:739
const ParagraphModel * model
Definition: ocrpara.h:36
bool is_list_item
Definition: ocrpara.h:38
bool is_very_first_or_continuation
Definition: ocrpara.h:43
Definition: ocrpara.h:29
PARA * para() const
Definition: ocrrow.h:115

◆ PositionedAtSameWord()

bool tesseract::PageIterator::PositionedAtSameWord ( const PAGE_RES_IT other) const

Are we positioned at the same location as other?

Definition at line 96 of file pageiterator.cpp.

96  {
97  return (it_ == NULL && it_ == other) ||
98  ((other != NULL) && (it_ != NULL) && (*it_ == *other));
99 }

◆ RestartParagraph()

void tesseract::PageIterator::RestartParagraph ( )
virtual

Moves the iterator to the beginning of the paragraph. This class implements this functionality by moving it to the zero indexed blob of the first (leftmost) word on the first row of the paragraph.

Definition at line 109 of file pageiterator.cpp.

109  {
110  if (it_->block() == NULL) return; // At end of the document.
111  PAGE_RES_IT para(page_res_);
112  PAGE_RES_IT next_para(para);
113  next_para.forward_paragraph();
114  while (next_para.cmp(*it_) <= 0) {
115  para = next_para;
116  next_para.forward_paragraph();
117  }
118  *it_ = para;
119  BeginWord(0);
120 }
TESS_LOCAL void BeginWord(int offset)
BLOCK_RES * block() const
Definition: pageres.h:742

◆ RestartRow()

void tesseract::PageIterator::RestartRow ( )
virtual

Moves the iterator to the beginning of the text line. This class implements this functionality by moving it to the zero indexed blob of the first (leftmost) word of the row.

Definition at line 128 of file pageiterator.cpp.

128  {
129  it_->restart_row();
130  BeginWord(0);
131 }
WERD_RES * restart_row()
Definition: pageres.cpp:1638
TESS_LOCAL void BeginWord(int offset)

◆ SetBoundingBoxComponents()

void tesseract::PageIterator::SetBoundingBoxComponents ( bool  include_upper_dots,
bool  include_lower_dots 
)
inline

Controls what to include in a bounding box. Bounding boxes of all levels between RIL_WORD and RIL_BLOCK can include or exclude potential diacritics. Between layout analysis and recognition, it isn't known where all diacritics belong, so this control is used to include or exclude some diacritics that are above or below the main body of the word. In most cases where the placement is obvious, and after recognition, it doesn't make as much difference, as the diacritics will already be included in the word.

Definition at line 191 of file pageiterator.h.

192  {
193  include_upper_dots_ = include_upper_dots;
194  include_lower_dots_ = include_lower_dots;
195  }

◆ SetWordBlamerBundle()

bool tesseract::PageIterator::SetWordBlamerBundle ( BlamerBundle blamer_bundle)

Definition at line 616 of file pageiterator.cpp.

616  {
617  if (it_->word() != NULL) {
618  it_->word()->blamer_bundle = blamer_bundle;
619  return true;
620  } else {
621  return false;
622  }
623 }
BlamerBundle * blamer_bundle
Definition: pageres.h:230
WERD_RES * word() const
Definition: pageres.h:736

Member Data Documentation

◆ blob_index_

int tesseract::PageIterator::blob_index_
protected

The current blob index within the word.

Definition at line 343 of file pageiterator.h.

◆ cblob_it_

C_BLOB_IT* tesseract::PageIterator::cblob_it_
protected

Iterator to the blobs within the word. If NULL, then we are iterating OCR results in the box_word. Owned by this ResultIterator.

Definition at line 349 of file pageiterator.h.

◆ include_lower_dots_

bool tesseract::PageIterator::include_lower_dots_
protected

Definition at line 352 of file pageiterator.h.

◆ include_upper_dots_

bool tesseract::PageIterator::include_upper_dots_
protected

Control over what to include in bounding boxes.

Definition at line 351 of file pageiterator.h.

◆ it_

PAGE_RES_IT* tesseract::PageIterator::it_
protected

The iterator to the page_res_. Owned by this ResultIterator. A pointer just to avoid dragging in Tesseract includes.

Definition at line 334 of file pageiterator.h.

◆ page_res_

PAGE_RES* tesseract::PageIterator::page_res_
protected

Pointer to the page_res owned by the API.

Definition at line 327 of file pageiterator.h.

◆ rect_height_

int tesseract::PageIterator::rect_height_
protected

Definition at line 359 of file pageiterator.h.

◆ rect_left_

int tesseract::PageIterator::rect_left_
protected

Definition at line 356 of file pageiterator.h.

◆ rect_top_

int tesseract::PageIterator::rect_top_
protected

Definition at line 357 of file pageiterator.h.

◆ rect_width_

int tesseract::PageIterator::rect_width_
protected

Definition at line 358 of file pageiterator.h.

◆ scale_

int tesseract::PageIterator::scale_
protected

Parameters saved from the Thresholder. Needed to rebuild coordinates.

Definition at line 354 of file pageiterator.h.

◆ scaled_yres_

int tesseract::PageIterator::scaled_yres_
protected

Definition at line 355 of file pageiterator.h.

◆ tesseract_

Tesseract* tesseract::PageIterator::tesseract_
protected

Pointer to the Tesseract object owned by the API.

Definition at line 329 of file pageiterator.h.

◆ word_

WERD* tesseract::PageIterator::word_
protected

The current input WERD being iterated. If there is an output from OCR, then word_ is NULL. Owned by the API

Definition at line 339 of file pageiterator.h.

◆ word_length_

int tesseract::PageIterator::word_length_
protected

The length of the current word_.

Definition at line 341 of file pageiterator.h.


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