tesseract  4.00.00dev
ltrresultiterator.cpp
Go to the documentation of this file.
1 // File: ltrresultiterator.cpp
3 // Description: Iterator for tesseract results in strict left-to-right
4 // order that avoids using tesseract internal data structures.
5 // Author: Ray Smith
6 // Created: Fri Feb 26 14:32:09 PST 2010
7 //
8 // (C) Copyright 2010, Google Inc.
9 // Licensed under the Apache License, Version 2.0 (the "License");
10 // you may not use this file except in compliance with the License.
11 // You may obtain a copy of the License at
12 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
20 
21 #include "ltrresultiterator.h"
22 
23 #include "allheaders.h"
24 #include "pageres.h"
25 #include "strngs.h"
26 #include "tesseractclass.h"
27 
28 namespace tesseract {
29 
31  int scale, int scaled_yres,
32  int rect_left, int rect_top,
33  int rect_width, int rect_height)
34  : PageIterator(page_res, tesseract, scale, scaled_yres,
35  rect_left, rect_top, rect_width, rect_height),
36  line_separator_("\n"),
37  paragraph_separator_("\n") {
38 }
39 
41 }
42 
43 // Returns the null terminated UTF-8 encoded text string for the current
44 // object at the given level. Use delete [] to free after use.
46  if (it_->word() == NULL) return NULL; // Already at the end!
47  STRING text;
48  PAGE_RES_IT res_it(*it_);
49  WERD_CHOICE* best_choice = res_it.word()->best_choice;
50  ASSERT_HOST(best_choice != NULL);
51  if (level == RIL_SYMBOL) {
52  text = res_it.word()->BestUTF8(blob_index_, false);
53  } else if (level == RIL_WORD) {
54  text = best_choice->unichar_string();
55  } else {
56  bool eol = false; // end of line?
57  bool eop = false; // end of paragraph?
58  do { // for each paragraph in a block
59  do { // for each text line in a paragraph
60  do { // for each word in a text line
61  best_choice = res_it.word()->best_choice;
62  ASSERT_HOST(best_choice != NULL);
63  text += best_choice->unichar_string();
64  text += " ";
65  res_it.forward();
66  eol = res_it.row() != res_it.prev_row();
67  } while (!eol);
68  text.truncate_at(text.length() - 1);
69  text += line_separator_;
70  eop = res_it.block() != res_it.prev_block() ||
71  res_it.row()->row->para() != res_it.prev_row()->row->para();
72  } while (level != RIL_TEXTLINE && !eop);
73  if (eop) text += paragraph_separator_;
74  } while (level == RIL_BLOCK && res_it.block() == res_it.prev_block());
75  }
76  int length = text.length() + 1;
77  char* result = new char[length];
78  strncpy(result, text.string(), length);
79  return result;
80 }
81 
82 // Set the string inserted at the end of each text line. "\n" by default.
85 }
86 
87 // Set the string inserted at the end of each paragraph. "\n" by default.
88 void LTRResultIterator::SetParagraphSeparator(const char *new_para) {
89  paragraph_separator_ = new_para;
90 }
91 
92 // Returns the mean confidence of the current object at the given level.
93 // The number should be interpreted as a percent probability. (0.0f-100.0f)
95  if (it_->word() == NULL) return 0.0f; // Already at the end!
96  float mean_certainty = 0.0f;
97  int certainty_count = 0;
98  PAGE_RES_IT res_it(*it_);
99  WERD_CHOICE* best_choice = res_it.word()->best_choice;
100  ASSERT_HOST(best_choice != NULL);
101  switch (level) {
102  case RIL_BLOCK:
103  do {
104  best_choice = res_it.word()->best_choice;
105  ASSERT_HOST(best_choice != NULL);
106  mean_certainty += best_choice->certainty();
107  ++certainty_count;
108  res_it.forward();
109  } while (res_it.block() == res_it.prev_block());
110  break;
111  case RIL_PARA:
112  do {
113  best_choice = res_it.word()->best_choice;
114  ASSERT_HOST(best_choice != NULL);
115  mean_certainty += best_choice->certainty();
116  ++certainty_count;
117  res_it.forward();
118  } while (res_it.block() == res_it.prev_block() &&
119  res_it.row()->row->para() == res_it.prev_row()->row->para());
120  break;
121  case RIL_TEXTLINE:
122  do {
123  best_choice = res_it.word()->best_choice;
124  ASSERT_HOST(best_choice != NULL);
125  mean_certainty += best_choice->certainty();
126  ++certainty_count;
127  res_it.forward();
128  } while (res_it.row() == res_it.prev_row());
129  break;
130  case RIL_WORD:
131  mean_certainty += best_choice->certainty();
132  ++certainty_count;
133  break;
134  case RIL_SYMBOL:
135  mean_certainty += best_choice->certainty(blob_index_);
136  ++certainty_count;
137  }
138  if (certainty_count > 0) {
139  mean_certainty /= certainty_count;
140  float confidence = 100 + 5 * mean_certainty;
141  if (confidence < 0.0f) confidence = 0.0f;
142  if (confidence > 100.0f) confidence = 100.0f;
143  return confidence;
144  }
145  return 0.0f;
146 }
147 
148 void LTRResultIterator::RowAttributes(float* row_height, float* descenders,
149  float* ascenders) const {
150  *row_height = it_->row()->row->x_height() + it_->row()->row->ascenders() -
151  it_->row()->row->descenders();
152  *descenders = it_->row()->row->descenders();
153  *ascenders = it_->row()->row->ascenders();
154 }
155 
156 // Returns the font attributes of the current word. If iterating at a higher
157 // level object than words, eg textlines, then this will return the
158 // attributes of the first word in that textline.
159 // The actual return value is a string representing a font name. It points
160 // to an internal table and SHOULD NOT BE DELETED. Lifespan is the same as
161 // the iterator itself, ie rendered invalid by various members of
162 // TessBaseAPI, including Init, SetImage, End or deleting the TessBaseAPI.
163 // Pointsize is returned in printers points (1/72 inch.)
164 const char* LTRResultIterator::WordFontAttributes(bool* is_bold,
165  bool* is_italic,
166  bool* is_underlined,
167  bool* is_monospace,
168  bool* is_serif,
169  bool* is_smallcaps,
170  int* pointsize,
171  int* font_id) const {
172  if (it_->word() == NULL) return NULL; // Already at the end!
173  if (it_->word()->fontinfo == NULL) {
174  *font_id = -1;
175  return NULL; // No font information.
176  }
177  const FontInfo& font_info = *it_->word()->fontinfo;
178  *font_id = font_info.universal_id;
179  *is_bold = font_info.is_bold();
180  *is_italic = font_info.is_italic();
181  *is_underlined = false; // TODO(rays) fix this!
182  *is_monospace = font_info.is_fixed_pitch();
183  *is_serif = font_info.is_serif();
184  *is_smallcaps = it_->word()->small_caps;
185  float row_height = it_->row()->row->x_height() +
186  it_->row()->row->ascenders() - it_->row()->row->descenders();
187  // Convert from pixels to printers points.
188  *pointsize = scaled_yres_ > 0
189  ? static_cast<int>(row_height * kPointsPerInch / scaled_yres_ + 0.5)
190  : 0;
191 
192  return font_info.name;
193 }
194 
195 // Returns the name of the language used to recognize this word.
197  if (it_->word() == NULL || it_->word()->tesseract == NULL) return NULL;
198  return it_->word()->tesseract->lang.string();
199 }
200 
201 // Return the overall directionality of this word.
203  if (it_->word() == NULL) return DIR_NEUTRAL;
204  bool has_rtl = it_->word()->AnyRtlCharsInWord();
205  bool has_ltr = it_->word()->AnyLtrCharsInWord();
206  if (has_rtl && !has_ltr)
207  return DIR_RIGHT_TO_LEFT;
208  if (has_ltr && !has_rtl)
209  return DIR_LEFT_TO_RIGHT;
210  if (!has_ltr && !has_rtl)
211  return DIR_NEUTRAL;
212  return DIR_MIX;
213 }
214 
215 // Returns true if the current word was found in a dictionary.
217  if (it_->word() == NULL) return false; // Already at the end!
218  int permuter = it_->word()->best_choice->permuter();
219  return permuter == SYSTEM_DAWG_PERM || permuter == FREQ_DAWG_PERM ||
220  permuter == USER_DAWG_PERM;
221 }
222 
223 // Returns the number of blanks before the current word.
225  if (it_->word() == NULL) return 1;
226  return it_->word()->word->space();
227 }
228 
229 // Returns true if the current word is numeric.
231  if (it_->word() == NULL) return false; // Already at the end!
232  int permuter = it_->word()->best_choice->permuter();
233  return permuter == NUMBER_PERM;
234 }
235 
236 // Returns true if the word contains blamer information.
238  return it_->word() != NULL && it_->word()->blamer_bundle != NULL &&
240 }
241 
242 // Returns the pointer to ParamsTrainingBundle stored in the BlamerBundle
243 // of the current word.
245  return (it_->word() != NULL && it_->word()->blamer_bundle != NULL) ?
246  &(it_->word()->blamer_bundle->params_training_bundle()) : NULL;
247 }
248 
249 // Returns the pointer to the string with blamer information for this word.
250 // Assumes that the word's blamer_bundle is not NULL.
252  return it_->word()->blamer_bundle->debug().string();
253 }
254 
255 // Returns the pointer to the string with misadaption information for this word.
256 // Assumes that the word's blamer_bundle is not NULL.
259 }
260 
261 // Returns true if a truth string was recorded for the current word.
263  if (it_->word() == NULL) return false; // Already at the end!
264  if (it_->word()->blamer_bundle == NULL ||
265  it_->word()->blamer_bundle->NoTruth()) {
266  return false; // no truth information for this word
267  }
268  return true;
269 }
270 
271 // Returns true if the given string is equivalent to the truth string for
272 // the current word.
273 bool LTRResultIterator::EquivalentToTruth(const char *str) const {
274  if (!HasTruthString()) return false;
275  ASSERT_HOST(it_->word()->uch_set != NULL);
276  WERD_CHOICE str_wd(str, *(it_->word()->uch_set));
277  return it_->word()->blamer_bundle->ChoiceIsCorrect(&str_wd);
278 }
279 
280 // Returns the null terminated UTF-8 encoded truth string for the current word.
281 // Use delete [] to free after use.
283  if (!HasTruthString()) return NULL;
284  STRING truth_text = it_->word()->blamer_bundle->TruthString();
285  int length = truth_text.length() + 1;
286  char* result = new char[length];
287  strncpy(result, truth_text.string(), length);
288  return result;
289 }
290 
291 // Returns the null terminated UTF-8 encoded normalized OCR string for the
292 // current word. Use delete [] to free after use.
294  if (it_->word() == NULL) return NULL; // Already at the end!
295  STRING ocr_text;
296  WERD_CHOICE* best_choice = it_->word()->best_choice;
297  const UNICHARSET *unicharset = it_->word()->uch_set;
298  ASSERT_HOST(best_choice != NULL);
299  for (int i = 0; i < best_choice->length(); ++i) {
300  ocr_text += unicharset->get_normed_unichar(best_choice->unichar_id(i));
301  }
302  int length = ocr_text.length() + 1;
303  char* result = new char[length];
304  strncpy(result, ocr_text.string(), length);
305  return result;
306 }
307 
308 // Returns a pointer to serialized choice lattice.
309 // Fills lattice_size with the number of bytes in lattice data.
310 const char *LTRResultIterator::WordLattice(int *lattice_size) const {
311  if (it_->word() == NULL) return NULL; // Already at the end!
312  if (it_->word()->blamer_bundle == NULL) return NULL;
313  *lattice_size = it_->word()->blamer_bundle->lattice_size();
314  return it_->word()->blamer_bundle->lattice_data();
315 }
316 
317 // Returns true if the current symbol is a superscript.
318 // If iterating at a higher level object than symbols, eg words, then
319 // this will return the attributes of the first symbol in that word.
321  if (cblob_it_ == NULL && it_->word() != NULL)
324  return false;
325 }
326 
327 // Returns true if the current symbol is a subscript.
328 // If iterating at a higher level object than symbols, eg words, then
329 // this will return the attributes of the first symbol in that word.
331  if (cblob_it_ == NULL && it_->word() != NULL)
333  return false;
334 }
335 
336 // Returns true if the current symbol is a dropcap.
337 // If iterating at a higher level object than symbols, eg words, then
338 // this will return the attributes of the first symbol in that word.
340  if (cblob_it_ == NULL && it_->word() != NULL)
342  return false;
343 }
344 
346  ASSERT_HOST(result_it.it_->word() != NULL);
347  word_res_ = result_it.it_->word();
348  BLOB_CHOICE_LIST* choices = NULL;
349  if (word_res_->ratings != NULL)
350  choices = word_res_->GetBlobChoices(result_it.blob_index_);
351  if (choices != NULL && !choices->empty()) {
352  choice_it_ = new BLOB_CHOICE_IT(choices);
353  choice_it_->mark_cycle_pt();
354  } else {
355  choice_it_ = NULL;
356  }
357 }
358 
360  delete choice_it_;
361 }
362 
363 // Moves to the next choice for the symbol and returns false if there
364 // are none left.
366  if (choice_it_ == NULL)
367  return false;
368  choice_it_->forward();
369  return !choice_it_->cycled_list();
370 }
371 
372 // Returns the null terminated UTF-8 encoded text string for the current
373 // choice. Do NOT use delete [] to free after use.
374 const char* ChoiceIterator::GetUTF8Text() const {
375  if (choice_it_ == NULL)
376  return NULL;
377  UNICHAR_ID id = choice_it_->data()->unichar_id();
378  return word_res_->uch_set->id_to_unichar_ext(id);
379 }
380 
381 // Returns the confidence of the current choice.
382 // The number should be interpreted as a percent probability. (0.0f-100.0f)
384  if (choice_it_ == NULL)
385  return 0.0f;
386  float confidence = 100 + 5 * choice_it_->data()->certainty();
387  if (confidence < 0.0f) confidence = 0.0f;
388  if (confidence > 100.0f) confidence = 100.0f;
389  return confidence;
390 }
391 
392 
393 } // namespace tesseract.
const char * GetBlamerDebug() const
const char * WordFontAttributes(bool *is_bold, bool *is_italic, bool *is_underlined, bool *is_monospace, bool *is_serif, bool *is_smallcaps, int *pointsize, int *font_id) const
bool EquivalentToTruth(const char *str) const
void truncate_at(inT32 index)
Definition: strngs.cpp:269
const char * GetBlamerMisadaptionDebug() const
UNICHAR_ID unichar_id(int index) const
Definition: ratngs.h:313
int UNICHAR_ID
Definition: unichar.h:33
const char * lattice_data() const
Definition: blamer.h:138
int lattice_size() const
Definition: blamer.h:141
WERD_CHOICE * best_choice
Definition: pageres.h:219
int length() const
Definition: ratngs.h:301
ROW_RES * prev_row() const
Definition: pageres.h:730
BlamerBundle * blamer_bundle
Definition: pageres.h:230
bool is_bold() const
Definition: fontinfo.h:112
bool AnyRtlCharsInWord() const
Definition: pageres.h:375
float Confidence(PageIteratorLevel level) const
void SetLineSeparator(const char *new_line)
const char * string() const
Definition: strngs.cpp:198
ROW * row
Definition: pageres.h:127
tesseract::ScriptPos BlobPosition(int index) const
Definition: ratngs.h:320
const STRING & misadaption_debug() const
Definition: blamer.h:119
float x_height() const
Definition: ocrrow.h:61
inT32 length() const
Definition: strngs.cpp:193
const void * GetParamsTrainingBundle() const
tesseract::Tesseract * tesseract
Definition: pageres.h:266
ROW_RES * row() const
Definition: pageres.h:739
#define ASSERT_HOST(x)
Definition: errcode.h:84
const tesseract::ParamsTrainingBundle & params_training_bundle() const
Definition: blamer.h:150
STRING lang
Definition: ccutil.h:66
uinT8 permuter() const
Definition: ratngs.h:344
WERD_RES * forward()
Definition: pageres.h:716
const STRING & debug() const
Definition: blamer.h:116
Definition: strngs.h:45
const FontInfo * fontinfo
Definition: pageres.h:288
void RowAttributes(float *row_height, float *descenders, float *ascenders) const
float certainty() const
Definition: ratngs.h:328
StrongScriptDirection WordDirection() const
bool NoTruth() const
Definition: blamer.h:109
float ascenders() const
Definition: ocrrow.h:79
LTRResultIterator(PAGE_RES *page_res, Tesseract *tesseract, int scale, int scaled_yres, int rect_left, int rect_top, int rect_width, int rect_height)
const STRING & unichar_string() const
Definition: ratngs.h:539
void SetParagraphSeparator(const char *new_para)
bool ChoiceIsCorrect(const WERD_CHOICE *word_choice) const
Definition: blamer.cpp:111
bool HasDebugInfo() const
Definition: blamer.h:113
ChoiceIterator(const LTRResultIterator &result_it)
StrongScriptDirection
Definition: unichar.h:40
bool small_caps
Definition: pageres.h:283
WERD * word
Definition: pageres.h:175
BLOB_CHOICE_LIST * GetBlobChoices(int index) const
Definition: pageres.cpp:751
const char * BestUTF8(int blob_index, bool in_rtl_context) const
Definition: pageres.h:345
bool is_italic() const
Definition: fontinfo.h:111
WERD_RES * word() const
Definition: pageres.h:736
const char * GetUTF8Text() const
#define new_line()
Definition: cutil.h:83
const char * WordLattice(int *lattice_size) const
PARA * para() const
Definition: ocrrow.h:115
bool is_fixed_pitch() const
Definition: fontinfo.h:113
const UNICHARSET * uch_set
Definition: pageres.h:192
BLOCK_RES * prev_block() const
Definition: pageres.h:733
bool AnyLtrCharsInWord() const
Definition: pageres.h:392
const int kPointsPerInch
Definition: publictypes.h:33
uinT8 space()
Definition: werd.h:104
STRING TruthString() const
Definition: blamer.h:100
const char * get_normed_unichar(UNICHAR_ID unichar_id) const
Definition: unicharset.h:788
const char * WordRecognitionLanguage() const
BLOCK_RES * block() const
Definition: pageres.h:742
bool is_serif() const
Definition: fontinfo.h:114
float descenders() const
Definition: ocrrow.h:82
char * GetUTF8Text(PageIteratorLevel level) const