mirror of
https://github.com/tesseract-ocr/tesseract.git
synced 2025-06-07 18:02:40 +08:00
Merge 4035a7f3cd
into 3b7c70e34d
This commit is contained in:
commit
93998816c5
@ -34,6 +34,11 @@ const int RecodeBeamSearch::kBeamWidths[RecodedCharID::kMaxCodeLen + 1] = {
|
||||
|
||||
static const char *kNodeContNames[] = {"Anything", "OnlyDup", "NoDup"};
|
||||
|
||||
// The minimum diplopia key is the minimum score (key) from
|
||||
// the network output to qualify as a likely 'real' character
|
||||
// for the purposes of identifying possible diplopia.
|
||||
static const float kMinDiplopiaKey = 0.25f;
|
||||
|
||||
// Prints debug details of the node.
|
||||
void RecodeNode::Print(int null_char, const UNICHARSET &unicharset,
|
||||
int depth) const {
|
||||
@ -188,7 +193,7 @@ void RecodeBeamSearch::calculateCharBoundaries(std::vector<int> *starts,
|
||||
std::vector<int> *ends,
|
||||
std::vector<int> *char_bounds_,
|
||||
int maxWidth) {
|
||||
char_bounds_->push_back(0);
|
||||
char_bounds_->push_back((*starts)[0]);
|
||||
for (unsigned i = 0; i < ends->size(); ++i) {
|
||||
int middle = ((*starts)[i + 1] - (*ends)[i]) / 2;
|
||||
char_bounds_->push_back((*ends)[i] + middle);
|
||||
@ -588,8 +593,8 @@ void RecodeBeamSearch::ExtractPathAsUnicharIds(
|
||||
}
|
||||
rating -= cert;
|
||||
}
|
||||
starts.push_back(t);
|
||||
if (t < width) {
|
||||
starts.push_back(t);
|
||||
int unichar_id = best_nodes[t]->unichar_id;
|
||||
if (unichar_id == UNICHAR_SPACE && !certs->empty() &&
|
||||
best_nodes[t]->permuter != NO_PERM) {
|
||||
@ -604,8 +609,9 @@ void RecodeBeamSearch::ExtractPathAsUnicharIds(
|
||||
}
|
||||
unichar_ids->push_back(unichar_id);
|
||||
xcoords->push_back(t);
|
||||
do {
|
||||
double cert = best_nodes[t++]->certainty;
|
||||
t++;
|
||||
while (t < width && best_nodes[t]->duplicate) {
|
||||
double cert = best_nodes[t]->certainty;
|
||||
// Special-case NO-PERM space to forget the certainty of the previous
|
||||
// nulls. See long comment in ContinueContext.
|
||||
if (cert < certainty || (unichar_id == UNICHAR_SPACE &&
|
||||
@ -613,7 +619,8 @@ void RecodeBeamSearch::ExtractPathAsUnicharIds(
|
||||
certainty = cert;
|
||||
}
|
||||
rating -= cert;
|
||||
} while (t < width && best_nodes[t]->duplicate);
|
||||
t++;
|
||||
}
|
||||
ends.push_back(t);
|
||||
certs->push_back(certainty);
|
||||
ratings->push_back(rating);
|
||||
@ -685,20 +692,48 @@ void RecodeBeamSearch::ComputeTopN(const float *outputs, int num_outputs,
|
||||
}
|
||||
}
|
||||
}
|
||||
float top_key = 0.0f;
|
||||
float second_key = 0.0f;
|
||||
bool found_first_code = false;
|
||||
bool found_second_code = false;
|
||||
while (!top_heap_.empty()) {
|
||||
TopPair entry;
|
||||
top_heap_.Pop(&entry);
|
||||
if (in_possible_diplopia_ && entry.data() == first_diplopia_code_) {
|
||||
found_first_code = true;
|
||||
}
|
||||
if (in_possible_diplopia_ && entry.data() == second_diplopia_code_) {
|
||||
found_second_code = true;
|
||||
}
|
||||
if (top_heap_.size() > 1) {
|
||||
top_n_flags_[entry.data()] = TN_TOPN;
|
||||
} else {
|
||||
top_n_flags_[entry.data()] = TN_TOP2;
|
||||
if (top_heap_.empty()) {
|
||||
top_code_ = entry.data();
|
||||
top_key = entry.key();
|
||||
} else {
|
||||
second_code_ = entry.data();
|
||||
second_key = entry.key();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Need to identify if we are in a potential diplopia situation
|
||||
// or if we already are, then determine if it is ended.
|
||||
if (in_possible_diplopia_) {
|
||||
if (!found_first_code && !found_second_code) {
|
||||
in_possible_diplopia_ = false;
|
||||
first_diplopia_code_ = -1;
|
||||
second_diplopia_code_ = -1;
|
||||
}
|
||||
}
|
||||
if (!in_possible_diplopia_) {
|
||||
if (top_code_ != null_char_ && second_code_ != null_char_ && top_key > kMinDiplopiaKey && second_key > kMinDiplopiaKey) {
|
||||
in_possible_diplopia_ = true;
|
||||
first_diplopia_code_ = top_code_;
|
||||
second_diplopia_code_ = second_code_;
|
||||
}
|
||||
}
|
||||
top_n_flags_[null_char_] = TN_TOP2;
|
||||
}
|
||||
|
||||
@ -1204,6 +1239,10 @@ void RecodeBeamSearch::PushHeapIfBetter(int max_size, int code, int unichar_id,
|
||||
if (UpdateHeapIfMatched(&node, heap)) {
|
||||
return;
|
||||
}
|
||||
// Check to see if node is possible diplopia.
|
||||
if (!AddToHeapIsAllowed(&node)) {
|
||||
return;
|
||||
}
|
||||
RecodePair entry(score, node);
|
||||
heap->Push(&entry);
|
||||
ASSERT_HOST(entry.data().dawgs == nullptr);
|
||||
@ -1258,6 +1297,21 @@ bool RecodeBeamSearch::UpdateHeapIfMatched(RecodeNode *new_node,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Determines if node can be added to heap based on possible diplopia status.
|
||||
bool RecodeBeamSearch::AddToHeapIsAllowed(RecodeNode *new_node) {
|
||||
if (!in_possible_diplopia_) {
|
||||
return true;
|
||||
}
|
||||
const RecodeNode *prev_node = new_node->prev;
|
||||
if (prev_node != nullptr && prev_node->code == first_diplopia_code_ && new_node->code == second_diplopia_code_) {
|
||||
return false;
|
||||
}
|
||||
if (prev_node != nullptr && prev_node->code == second_diplopia_code_ && new_node->code == first_diplopia_code_) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Computes and returns the code-hash for the given code and prev.
|
||||
uint64_t RecodeBeamSearch::ComputeCodeHash(int code, bool dup,
|
||||
const RecodeNode *prev) const {
|
||||
|
@ -374,6 +374,9 @@ private:
|
||||
// Searches the heap for an entry matching new_node, and updates the entry
|
||||
// with reshuffle if needed. Returns true if there was a match.
|
||||
bool UpdateHeapIfMatched(RecodeNode *new_node, RecodeHeap *heap);
|
||||
// Determines if new node can be added to the heap for the current beam.
|
||||
// Returns false if we are in possible diplopia situation.
|
||||
bool AddToHeapIsAllowed(RecodeNode *new_node);
|
||||
// Computes and returns the code-hash for the given code and prev.
|
||||
uint64_t ComputeCodeHash(int code, bool dup, const RecodeNode *prev) const;
|
||||
// Backtracks to extract the best path through the lattice that was built
|
||||
@ -420,6 +423,11 @@ private:
|
||||
// True if the input is simple text, ie adjacent equal chars are not to be
|
||||
// eliminated.
|
||||
bool is_simple_text_;
|
||||
// Variables used in tracking possible diplopia case.
|
||||
// Refer to ComputeTopN routine for use of these variables.
|
||||
bool in_possible_diplopia_ = false;
|
||||
int first_diplopia_code_ = -1;
|
||||
int second_diplopia_code_ = -1;
|
||||
// The encoded (class label) of the null/reject character.
|
||||
int null_char_;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user