tesseract 4.1.1
Loading...
Searching...
No Matches
ltrresultiterator.cpp
Go to the documentation of this file.
1
2// 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//
7// (C) Copyright 2010, Google Inc.
8// Licensed under the Apache License, Version 2.0 (the "License");
9// you may not use this file except in compliance with the License.
10// You may obtain a copy of the License at
11// http://www.apache.org/licenses/LICENSE-2.0
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17//
19
20#include "ltrresultiterator.h"
21
22#include "allheaders.h"
23#include "pageres.h"
24#include "strngs.h"
25#include "tesseractclass.h"
26
27namespace tesseract {
28
30 int scale, int scaled_yres, int rect_left,
31 int rect_top, int rect_width,
32 int rect_height)
33 : PageIterator(page_res, tesseract, scale, scaled_yres, rect_left, rect_top,
34 rect_width, rect_height),
35 line_separator_("\n"),
36 paragraph_separator_("\n") {}
37
38// Destructor.
39// It is defined here, so the compiler can create a single vtable
40// instead of weak vtables in every compilation unit.
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() == nullptr) return nullptr; // 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 != nullptr);
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 != nullptr);
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.
83void LTRResultIterator::SetLineSeparator(const char* new_line) {
84 line_separator_ = new_line;
85}
86
87// Set the string inserted at the end of each paragraph. "\n" by default.
88void 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() == nullptr) 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 != nullptr);
101 switch (level) {
102 case RIL_BLOCK:
103 do {
104 best_choice = res_it.word()->best_choice;
105 ASSERT_HOST(best_choice != nullptr);
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 != nullptr);
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 != nullptr);
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
148void 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.)
165 bool* is_bold, bool* is_italic, bool* is_underlined, bool* is_monospace,
166 bool* is_serif, bool* is_smallcaps, int* pointsize, int* font_id) const {
167 const char* result = nullptr;
168
169 if (it_->word() == nullptr) {
170 // Already at the end!
171 *pointsize = 0;
172 } else {
173 float row_height = it_->row()->row->x_height() +
174 it_->row()->row->ascenders() -
175 it_->row()->row->descenders();
176 // Convert from pixels to printers points.
177 *pointsize =
178 scaled_yres_ > 0
179 ? static_cast<int>(row_height * kPointsPerInch / scaled_yres_ + 0.5)
180 : 0;
181
182 #ifndef DISABLED_LEGACY_ENGINE
183 const FontInfo* font_info = it_->word()->fontinfo;
184 if (font_info) {
185 // Font information available.
186 *font_id = font_info->universal_id;
187 *is_bold = font_info->is_bold();
188 *is_italic = font_info->is_italic();
189 *is_underlined = false; // TODO(rays) fix this!
190 *is_monospace = font_info->is_fixed_pitch();
191 *is_serif = font_info->is_serif();
192 result = font_info->name;
193 }
194 #endif // ndef DISABLED_LEGACY_ENGINE
195
196 *is_smallcaps = it_->word()->small_caps;
197 }
198
199 if (!result) {
200 *is_bold = false;
201 *is_italic = false;
202 *is_underlined = false;
203 *is_monospace = false;
204 *is_serif = false;
205 *is_smallcaps = false;
206 *font_id = -1;
207 }
208
209 return result;
210}
211
212// Returns the name of the language used to recognize this word.
214 if (it_->word() == nullptr || it_->word()->tesseract == nullptr)
215 return nullptr;
216 return it_->word()->tesseract->lang.string();
217}
218
219// Return the overall directionality of this word.
221 if (it_->word() == nullptr) return DIR_NEUTRAL;
222 bool has_rtl = it_->word()->AnyRtlCharsInWord();
223 bool has_ltr = it_->word()->AnyLtrCharsInWord();
224 if (has_rtl && !has_ltr) return DIR_RIGHT_TO_LEFT;
225 if (has_ltr && !has_rtl) return DIR_LEFT_TO_RIGHT;
226 if (!has_ltr && !has_rtl) return DIR_NEUTRAL;
227 return DIR_MIX;
228}
229
230// Returns true if the current word was found in a dictionary.
232 if (it_->word() == nullptr) return false; // Already at the end!
233 int permuter = it_->word()->best_choice->permuter();
234 return permuter == SYSTEM_DAWG_PERM || permuter == FREQ_DAWG_PERM ||
235 permuter == USER_DAWG_PERM;
236}
237
238// Returns the number of blanks before the current word.
240 if (it_->word() == nullptr) return 1;
241 return it_->word()->word->space();
242}
243
244// Returns true if the current word is numeric.
246 if (it_->word() == nullptr) return false; // Already at the end!
247 int permuter = it_->word()->best_choice->permuter();
248 return permuter == NUMBER_PERM;
249}
250
251// Returns true if the word contains blamer information.
253 return it_->word() != nullptr && it_->word()->blamer_bundle != nullptr &&
255}
256
257#ifndef DISABLED_LEGACY_ENGINE
258// Returns the pointer to ParamsTrainingBundle stored in the BlamerBundle
259// of the current word.
261 return (it_->word() != nullptr && it_->word()->blamer_bundle != nullptr)
263 : nullptr;
264}
265#endif // ndef DISABLED_LEGACY_ENGINE
266
267// Returns the pointer to the string with blamer information for this word.
268// Assumes that the word's blamer_bundle is not nullptr.
270 return it_->word()->blamer_bundle->debug().string();
271}
272
273// Returns the pointer to the string with misadaption information for this word.
274// Assumes that the word's blamer_bundle is not nullptr.
277}
278
279// Returns true if a truth string was recorded for the current word.
281 if (it_->word() == nullptr) return false; // Already at the end!
282 if (it_->word()->blamer_bundle == nullptr ||
283 it_->word()->blamer_bundle->NoTruth()) {
284 return false; // no truth information for this word
285 }
286 return true;
287}
288
289// Returns true if the given string is equivalent to the truth string for
290// the current word.
291bool LTRResultIterator::EquivalentToTruth(const char* str) const {
292 if (!HasTruthString()) return false;
293 ASSERT_HOST(it_->word()->uch_set != nullptr);
294 WERD_CHOICE str_wd(str, *(it_->word()->uch_set));
295 return it_->word()->blamer_bundle->ChoiceIsCorrect(&str_wd);
296}
297
298// Returns the null terminated UTF-8 encoded truth string for the current word.
299// Use delete [] to free after use.
301 if (!HasTruthString()) return nullptr;
302 STRING truth_text = it_->word()->blamer_bundle->TruthString();
303 int length = truth_text.length() + 1;
304 char* result = new char[length];
305 strncpy(result, truth_text.string(), length);
306 return result;
307}
308
309// Returns the null terminated UTF-8 encoded normalized OCR string for the
310// current word. Use delete [] to free after use.
312 if (it_->word() == nullptr) return nullptr; // Already at the end!
313 STRING ocr_text;
314 WERD_CHOICE* best_choice = it_->word()->best_choice;
315 const UNICHARSET* unicharset = it_->word()->uch_set;
316 ASSERT_HOST(best_choice != nullptr);
317 for (int i = 0; i < best_choice->length(); ++i) {
318 ocr_text += unicharset->get_normed_unichar(best_choice->unichar_id(i));
319 }
320 int length = ocr_text.length() + 1;
321 char* result = new char[length];
322 strncpy(result, ocr_text.string(), length);
323 return result;
324}
325
326// Returns a pointer to serialized choice lattice.
327// Fills lattice_size with the number of bytes in lattice data.
328const char* LTRResultIterator::WordLattice(int* lattice_size) const {
329 if (it_->word() == nullptr) return nullptr; // Already at the end!
330 if (it_->word()->blamer_bundle == nullptr) return nullptr;
331 *lattice_size = it_->word()->blamer_bundle->lattice_size();
332 return it_->word()->blamer_bundle->lattice_data();
333}
334
335// Returns true if the current symbol is a superscript.
336// If iterating at a higher level object than symbols, eg words, then
337// this will return the attributes of the first symbol in that word.
339 if (cblob_it_ == nullptr && it_->word() != nullptr)
342 return false;
343}
344
345// Returns true if the current symbol is a subscript.
346// If iterating at a higher level object than symbols, eg words, then
347// this will return the attributes of the first symbol in that word.
349 if (cblob_it_ == nullptr && it_->word() != nullptr)
351 return false;
352}
353
354// Returns true if the current symbol is a dropcap.
355// If iterating at a higher level object than symbols, eg words, then
356// this will return the attributes of the first symbol in that word.
358 if (cblob_it_ == nullptr && it_->word() != nullptr)
360 return false;
361}
362
364 ASSERT_HOST(result_it.it_->word() != nullptr);
365 word_res_ = result_it.it_->word();
366 BLOB_CHOICE_LIST* choices = nullptr;
367 if (word_res_->ratings != nullptr)
368 choices = word_res_->GetBlobChoices(result_it.blob_index_);
369 if (choices != nullptr && !choices->empty()) {
370 choice_it_ = new BLOB_CHOICE_IT(choices);
371 choice_it_->mark_cycle_pt();
372 } else {
373 choice_it_ = nullptr;
374 }
375}
376ChoiceIterator::~ChoiceIterator() { delete choice_it_; }
377
378// Moves to the next choice for the symbol and returns false if there
379// are none left.
381 if (choice_it_ == nullptr) return false;
382 choice_it_->forward();
383 return !choice_it_->cycled_list();
384}
385
386// Returns the null terminated UTF-8 encoded text string for the current
387// choice. Do NOT use delete [] to free after use.
388const char* ChoiceIterator::GetUTF8Text() const {
389 if (choice_it_ == nullptr) return nullptr;
390 UNICHAR_ID id = choice_it_->data()->unichar_id();
391 return word_res_->uch_set->id_to_unichar_ext(id);
392}
393
394// Returns the confidence of the current choice depending on the used language
395// data. If only LSTM traineddata is used the value range is 0.0f - 1.0f. All
396// choices for one symbol should roughly add up to 1.0f.
397// If only traineddata of the legacy engine is used, the number should be
398// interpreted as a percent probability. (0.0f-100.0f) In this case probabilities
399// won't add up to 100. Each one stands on its own.
401 if (choice_it_ == nullptr) return 0.0f;
402 float confidence = 100 + 5 * choice_it_->data()->certainty();
403 if (confidence < 0.0f) confidence = 0.0f;
404 if (confidence > 100.0f) confidence = 100.0f;
405 return confidence;
406}
407} // namespace tesseract.
constexpr int kPointsPerInch
Definition: publictypes.h:33
@ FREQ_DAWG_PERM
Definition: ratngs.h:244
@ USER_DAWG_PERM
Definition: ratngs.h:243
@ SYSTEM_DAWG_PERM
Definition: ratngs.h:241
@ NUMBER_PERM
Definition: ratngs.h:239
#define ASSERT_HOST(x)
Definition: errcode.h:88
StrongScriptDirection
Definition: unichar.h:41
@ DIR_MIX
Definition: unichar.h:45
@ DIR_RIGHT_TO_LEFT
Definition: unichar.h:44
@ DIR_LEFT_TO_RIGHT
Definition: unichar.h:43
@ DIR_NEUTRAL
Definition: unichar.h:42
int UNICHAR_ID
Definition: unichar.h:34
@ SP_SUBSCRIPT
Definition: ratngs.h:254
@ SP_DROPCAP
Definition: ratngs.h:256
@ SP_SUPERSCRIPT
Definition: ratngs.h:255
const char * GetBlamerDebug() const
char * GetUTF8Text(PageIteratorLevel level) const
const void * GetParamsTrainingBundle() const
StrongScriptDirection WordDirection() 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
const char * GetBlamerMisadaptionDebug() const
const char * WordRecognitionLanguage() const
void SetLineSeparator(const char *new_line)
const char * WordLattice(int *lattice_size) const
LTRResultIterator(PAGE_RES *page_res, Tesseract *tesseract, int scale, int scaled_yres, int rect_left, int rect_top, int rect_width, int rect_height)
void SetParagraphSeparator(const char *new_para)
float Confidence(PageIteratorLevel level) const
void RowAttributes(float *row_height, float *descenders, float *ascenders) const
bool EquivalentToTruth(const char *str) const
const char * GetUTF8Text() const
ChoiceIterator(const LTRResultIterator &result_it)
bool HasDebugInfo() const
Definition: blamer.h:127
const char * lattice_data() const
Definition: blamer.h:152
int lattice_size() const
Definition: blamer.h:155
const tesseract::ParamsTrainingBundle & params_training_bundle() const
Definition: blamer.h:165
STRING TruthString() const
Definition: blamer.h:114
bool ChoiceIsCorrect(const WERD_CHOICE *word_choice) const
Definition: blamer.cpp:119
bool NoTruth() const
Definition: blamer.h:123
const STRING & debug() const
Definition: blamer.h:130
const STRING & misadaption_debug() const
Definition: blamer.h:133
int32_t universal_id
Definition: fontinfo.h:123
float descenders() const
Definition: ocrrow.h:85
float ascenders() const
Definition: ocrrow.h:82
PARA * para() const
Definition: ocrrow.h:118
float x_height() const
Definition: ocrrow.h:64
ROW * row
Definition: pageres.h:140
const UNICHARSET * uch_set
Definition: pageres.h:203
BlamerBundle * blamer_bundle
Definition: pageres.h:252
tesseract::Tesseract * tesseract
Definition: pageres.h:280
const char * BestUTF8(int blob_index, bool in_rtl_context) const
Definition: pageres.h:363
const FontInfo * fontinfo
Definition: pageres.h:309
WERD_CHOICE * best_choice
Definition: pageres.h:241
bool AnyRtlCharsInWord() const
Definition: pageres.h:393
BLOB_CHOICE_LIST * GetBlobChoices(int index) const
Definition: pageres.cpp:759
bool small_caps
Definition: pageres.h:306
bool AnyLtrCharsInWord() const
Definition: pageres.h:409
MATRIX * ratings
Definition: pageres.h:237
WERD * word
Definition: pageres.h:186
WERD_RES * word() const
Definition: pageres.h:754
ROW_RES * row() const
Definition: pageres.h:757
BLOCK_RES * prev_block() const
Definition: pageres.h:751
ROW_RES * prev_row() const
Definition: pageres.h:748
BLOCK_RES * block() const
Definition: pageres.h:760
WERD_RES * forward()
Definition: pageres.h:734
const STRING & unichar_string() const
Definition: ratngs.h:531
UNICHAR_ID unichar_id(int index) const
Definition: ratngs.h:305
uint8_t permuter() const
Definition: ratngs.h:336
float certainty() const
Definition: ratngs.h:320
int length() const
Definition: ratngs.h:293
tesseract::ScriptPos BlobPosition(int index) const
Definition: ratngs.h:312
uint8_t space()
Definition: werd.h:99
STRING lang
Definition: ccutil.h:71
Definition: strngs.h:45
void truncate_at(int32_t index)
Definition: strngs.cpp:265
int32_t length() const
Definition: strngs.cpp:189
const char * string() const
Definition: strngs.cpp:194
const char * get_normed_unichar(UNICHAR_ID unichar_id) const
Definition: unicharset.h:828
const char * id_to_unichar_ext(UNICHAR_ID id) const
Definition: unicharset.cpp:299