Skip to content

Commit

Permalink
Integrated Timesteps per symbol into ChoiceIterator
Browse files Browse the repository at this point in the history
Signed-off-by: Noah Metzger <noah.metzger@bib.uni-mannheim.de>
  • Loading branch information
noahmetzger committed Mar 11, 2019
1 parent 754e38d commit bc2b919
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 53 deletions.
110 changes: 57 additions & 53 deletions src/ccmain/ltrresultiterator.cpp
Expand Up @@ -28,14 +28,13 @@
namespace tesseract {

LTRResultIterator::LTRResultIterator(PAGE_RES* page_res, Tesseract* tesseract,
int scale, int scaled_yres,
int rect_left, int rect_top,
int rect_width, int rect_height)
: PageIterator(page_res, tesseract, scale, scaled_yres,
rect_left, rect_top, rect_width, rect_height),
line_separator_("\n"),
paragraph_separator_("\n") {
}
int scale, int scaled_yres, int rect_left,
int rect_top, int rect_width,
int rect_height)
: PageIterator(page_res, tesseract, scale, scaled_yres, rect_left, rect_top,
rect_width, rect_height),
line_separator_("\n"),
paragraph_separator_("\n") {}

// Destructor.
// It is defined here, so the compiler can create a single vtable
Expand All @@ -57,9 +56,9 @@ char* LTRResultIterator::GetUTF8Text(PageIteratorLevel level) const {
} else {
bool eol = false; // end of line?
bool eop = false; // end of paragraph?
do { // for each paragraph in a block
do { // for each text line in a paragraph
do { // for each word in a text line
do { // for each paragraph in a block
do { // for each text line in a paragraph
do { // for each word in a text line
best_choice = res_it.word()->best_choice;
ASSERT_HOST(best_choice != nullptr);
text += best_choice->unichar_string();
Expand All @@ -70,7 +69,7 @@ char* LTRResultIterator::GetUTF8Text(PageIteratorLevel level) const {
text.truncate_at(text.length() - 1);
text += line_separator_;
eop = res_it.block() != res_it.prev_block() ||
res_it.row()->row->para() != res_it.prev_row()->row->para();
res_it.row()->row->para() != res_it.prev_row()->row->para();
} while (level != RIL_TEXTLINE && !eop);
if (eop) text += paragraph_separator_;
} while (level == RIL_BLOCK && res_it.block() == res_it.prev_block());
Expand All @@ -82,12 +81,12 @@ char* LTRResultIterator::GetUTF8Text(PageIteratorLevel level) const {
}

// Set the string inserted at the end of each text line. "\n" by default.
void LTRResultIterator::SetLineSeparator(const char *new_line) {
void LTRResultIterator::SetLineSeparator(const char* new_line) {
line_separator_ = new_line;
}

// Set the string inserted at the end of each paragraph. "\n" by default.
void LTRResultIterator::SetParagraphSeparator(const char *new_para) {
void LTRResultIterator::SetParagraphSeparator(const char* new_para) {
paragraph_separator_ = new_para;
}

Expand Down Expand Up @@ -131,7 +130,7 @@ float LTRResultIterator::Confidence(PageIteratorLevel level) const {
break;
case RIL_WORD:
mean_certainty += best_choice->certainty();
++certainty_count;
++certainty_count;
break;
case RIL_SYMBOL:
mean_certainty += best_choice->certainty(blob_index_);
Expand Down Expand Up @@ -163,26 +162,23 @@ void LTRResultIterator::RowAttributes(float* row_height, float* descenders,
// the iterator itself, ie rendered invalid by various members of
// TessBaseAPI, including Init, SetImage, End or deleting the TessBaseAPI.
// Pointsize is returned in printers points (1/72 inch.)
const char* LTRResultIterator::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* LTRResultIterator::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* result = nullptr;

if (it_->word() == nullptr) {
// Already at the end!
*pointsize = 0;
} else {
float row_height = it_->row()->row->x_height() +
it_->row()->row->ascenders() - it_->row()->row->descenders();
it_->row()->row->ascenders() -
it_->row()->row->descenders();
// Convert from pixels to printers points.
*pointsize = scaled_yres_ > 0
? static_cast<int>(row_height * kPointsPerInch / scaled_yres_ + 0.5)
: 0;
*pointsize =
scaled_yres_ > 0
? static_cast<int>(row_height * kPointsPerInch / scaled_yres_ + 0.5)
: 0;
const FontInfo* font_info = it_->word()->fontinfo;
if (font_info) {
// Font information available.
Expand Down Expand Up @@ -212,7 +208,8 @@ const char* LTRResultIterator::WordFontAttributes(bool* is_bold,

// Returns the name of the language used to recognize this word.
const char* LTRResultIterator::WordRecognitionLanguage() const {
if (it_->word() == nullptr || it_->word()->tesseract == nullptr) return nullptr;
if (it_->word() == nullptr || it_->word()->tesseract == nullptr)
return nullptr;
return it_->word()->tesseract->lang.string();
}

Expand All @@ -221,12 +218,9 @@ StrongScriptDirection LTRResultIterator::WordDirection() const {
if (it_->word() == nullptr) return DIR_NEUTRAL;
bool has_rtl = it_->word()->AnyRtlCharsInWord();
bool has_ltr = it_->word()->AnyLtrCharsInWord();
if (has_rtl && !has_ltr)
return DIR_RIGHT_TO_LEFT;
if (has_ltr && !has_rtl)
return DIR_LEFT_TO_RIGHT;
if (!has_ltr && !has_rtl)
return DIR_NEUTRAL;
if (has_rtl && !has_ltr) return DIR_RIGHT_TO_LEFT;
if (has_ltr && !has_rtl) return DIR_LEFT_TO_RIGHT;
if (!has_ltr && !has_rtl) return DIR_NEUTRAL;
return DIR_MIX;
}

Expand Down Expand Up @@ -259,20 +253,21 @@ bool LTRResultIterator::HasBlamerInfo() const {

// Returns the pointer to ParamsTrainingBundle stored in the BlamerBundle
// of the current word.
const void *LTRResultIterator::GetParamsTrainingBundle() const {
return (it_->word() != nullptr && it_->word()->blamer_bundle != nullptr) ?
&(it_->word()->blamer_bundle->params_training_bundle()) : nullptr;
const void* LTRResultIterator::GetParamsTrainingBundle() const {
return (it_->word() != nullptr && it_->word()->blamer_bundle != nullptr)
? &(it_->word()->blamer_bundle->params_training_bundle())
: nullptr;
}

// Returns the pointer to the string with blamer information for this word.
// Assumes that the word's blamer_bundle is not nullptr.
const char *LTRResultIterator::GetBlamerDebug() const {
const char* LTRResultIterator::GetBlamerDebug() const {
return it_->word()->blamer_bundle->debug().string();
}

// Returns the pointer to the string with misadaption information for this word.
// Assumes that the word's blamer_bundle is not nullptr.
const char *LTRResultIterator::GetBlamerMisadaptionDebug() const {
const char* LTRResultIterator::GetBlamerMisadaptionDebug() const {
return it_->word()->blamer_bundle->misadaption_debug().string();
}

Expand All @@ -288,7 +283,7 @@ bool LTRResultIterator::HasTruthString() const {

// Returns true if the given string is equivalent to the truth string for
// the current word.
bool LTRResultIterator::EquivalentToTruth(const char *str) const {
bool LTRResultIterator::EquivalentToTruth(const char* str) const {
if (!HasTruthString()) return false;
ASSERT_HOST(it_->word()->uch_set != nullptr);
WERD_CHOICE str_wd(str, *(it_->word()->uch_set));
Expand All @@ -312,7 +307,7 @@ char* LTRResultIterator::WordNormedUTF8Text() const {
if (it_->word() == nullptr) return nullptr; // Already at the end!
STRING ocr_text;
WERD_CHOICE* best_choice = it_->word()->best_choice;
const UNICHARSET *unicharset = it_->word()->uch_set;
const UNICHARSET* unicharset = it_->word()->uch_set;
ASSERT_HOST(best_choice != nullptr);
for (int i = 0; i < best_choice->length(); ++i) {
ocr_text += unicharset->get_normed_unichar(best_choice->unichar_id(i));
Expand All @@ -325,7 +320,7 @@ char* LTRResultIterator::WordNormedUTF8Text() const {

// Returns a pointer to serialized choice lattice.
// Fills lattice_size with the number of bytes in lattice data.
const char *LTRResultIterator::WordLattice(int *lattice_size) const {
const char* LTRResultIterator::WordLattice(int* lattice_size) const {
if (it_->word() == nullptr) return nullptr; // Already at the end!
if (it_->word()->blamer_bundle == nullptr) return nullptr;
*lattice_size = it_->word()->blamer_bundle->lattice_size();
Expand All @@ -338,7 +333,7 @@ const char *LTRResultIterator::WordLattice(int *lattice_size) const {
bool LTRResultIterator::SymbolIsSuperscript() const {
if (cblob_it_ == nullptr && it_->word() != nullptr)
return it_->word()->best_choice->BlobPosition(blob_index_) ==
SP_SUPERSCRIPT;
SP_SUPERSCRIPT;
return false;
}

Expand Down Expand Up @@ -372,40 +367,49 @@ ChoiceIterator::ChoiceIterator(const LTRResultIterator& result_it) {
} else {
choice_it_ = nullptr;
}
if (&word_res_->symbol_steps != nullptr && !word_res_->symbol_steps.empty()) {
symbol_step_it_ = word_res_->symbol_steps.begin();
}
}

ChoiceIterator::~ChoiceIterator() {
delete choice_it_;
}
ChoiceIterator::~ChoiceIterator() { delete choice_it_; }

// Moves to the next choice for the symbol and returns false if there
// are none left.
bool ChoiceIterator::Next() {
if (choice_it_ == nullptr)
return false;
if (choice_it_ == nullptr) return false;
if (&word_res_->symbol_steps != nullptr) {
if (symbol_step_it_ == word_res_->symbol_steps.end()) {
symbol_step_it_ = word_res_->symbol_steps.begin();
} else {
symbol_step_it_++;
}
}
choice_it_->forward();
return !choice_it_->cycled_list();
}

// Returns the null terminated UTF-8 encoded text string for the current
// choice. Do NOT use delete [] to free after use.
const char* ChoiceIterator::GetUTF8Text() const {
if (choice_it_ == nullptr)
return nullptr;
if (choice_it_ == nullptr) return nullptr;
UNICHAR_ID id = choice_it_->data()->unichar_id();
return word_res_->uch_set->id_to_unichar_ext(id);
}

// Returns the confidence of the current choice.
// The number should be interpreted as a percent probability. (0.0f-100.0f)
float ChoiceIterator::Confidence() const {
if (choice_it_ == nullptr)
return 0.0f;
if (choice_it_ == nullptr) return 0.0f;
float confidence = 100 + 5 * choice_it_->data()->certainty();
if (confidence < 0.0f) confidence = 0.0f;
if (confidence > 100.0f) confidence = 100.0f;
return confidence;
}


std::vector<std::vector<std::pair<const char*, float>>>*
ChoiceIterator::Timesteps() const {
if (&word_res_->symbol_steps == nullptr) return nullptr;
return &*symbol_step_it_;
}
} // namespace tesseract.
10 changes: 10 additions & 0 deletions src/ccmain/ltrresultiterator.h
Expand Up @@ -212,11 +212,21 @@ class ChoiceIterator {
// The number should be interpreted as a percent probability. (0.0f-100.0f)
float Confidence() const;

// Returns a vector containing all timesteps, which belong to the currently
// selected symbol. A timestep is a vector containing pairs of symbols and
// floating point numbers. The number states the probability for the
// corresponding symbol.
std::vector<std::vector<std::pair<const char*, float>>>*
Timesteps() const;

private:
// Pointer to the WERD_RES object owned by the API.
WERD_RES* word_res_;
// Iterator over the blob choices.
BLOB_CHOICE_IT* choice_it_;
//Iterator over the symbol steps.
std::vector<std::vector<std::vector<std::pair<const char*, float>>>>::iterator
symbol_step_it_;
};

} // namespace tesseract.
Expand Down

0 comments on commit bc2b919

Please sign in to comment.