/** * @name call_matcher * * Called from Tess with a blob in tess form. * The blob may need rotating to the correct orientation for classification. */ BLOB_CHOICE_LIST *Wordrec::call_matcher(TBLOB *tessblob) { // Rotate the blob for classification if necessary. TBLOB* rotated_blob = tessblob->ClassifyNormalizeIfNeeded(); if (rotated_blob == nullptr) { rotated_blob = tessblob; } BLOB_CHOICE_LIST *ratings = new BLOB_CHOICE_LIST(); // matcher result AdaptiveClassifier(rotated_blob, ratings); if (rotated_blob != tessblob) { delete rotated_blob; } return ratings; }
/** * @name call_matcher * * Called from Tess with a blob in tess form. * The blob may need rotating to the correct orientation for classification. */ BLOB_CHOICE_LIST *Wordrec::call_matcher(const DENORM* denorm, TBLOB *tessblob) { // Rotate the blob for classification if necessary. TBLOB* rotated_blob = tessblob->ClassifyNormalizeIfNeeded(&denorm); if (rotated_blob == NULL) { rotated_blob = tessblob; } BLOB_CHOICE_LIST *ratings = new BLOB_CHOICE_LIST(); // matcher result AdaptiveClassifier(rotated_blob, *denorm, ratings, NULL); if (rotated_blob != tessblob) { delete rotated_blob; delete denorm; } return ratings; }
void Tesseract::tess_bn_matcher( //call tess PBLOB *pblob, //previous blob PBLOB *blob, //blob to match PBLOB *nblob, //next blob WERD *word, //word it came from DENORM *denorm, //de-normaliser BLOB_CHOICE_LIST *ratings //list of results ) { TBLOB *tessblob; //converted blob TEXTROW tessrow; //dummy row tess_bn_matching.set_value(true); //turn it on tess_cn_matching.set_value(false); //convert blob tessblob = make_rotated_tess_blob(denorm, blob, true); //make dummy row make_tess_row(denorm, &tessrow); //classify AdaptiveClassifier(tessblob, NULL, &tessrow, ratings, NULL); free_blob(tessblob); }
void tess_default_matcher( //call tess PBLOB *pblob, //previous blob PBLOB *blob, //blob to match PBLOB *nblob, //next blob WERD *word, //word it came from DENORM *denorm, //de-normaliser BLOB_CHOICE_LIST &ratings //list of results ) { LIST result; //tess output TBLOB *tessblob; //converted blob TEXTROW tessrow; //dummy row tess_bn_matching = FALSE; //turn it off tess_cn_matching = FALSE; //convert blob tessblob = make_tess_blob (blob, TRUE); //make dummy row make_tess_row(denorm, &tessrow); //classify result = AdaptiveClassifier (tessblob, NULL, &tessrow); free_blob(tessblob); //make our format convert_choice_list(result, ratings); }
// Adapt to recognize the current image as the given character. // The image must be preloaded and be just an image of a single character. void TessBaseAPI::AdaptToCharacter(const char *unichar_repr, int length, float baseline, float xheight, float descender, float ascender) { UNICHAR_ID id = unicharset.unichar_to_id(unichar_repr, length); LINE_STATS LineStats; TEXTROW row; fill_dummy_row(baseline, xheight, descender, ascender, &row); GetLineStatsFromRow(&row, &LineStats); TBLOB *blob = make_tesseract_blob(baseline, xheight, descender, ascender); float threshold; int best_class = 0; float best_rating = -100; // Classify to get a raw choice. LIST result = AdaptiveClassifier(blob, NULL, &row); LIST p; for (p = result; p != NULL; p = p->next) { A_CHOICE *tesschoice = (A_CHOICE *) p->node; if (tesschoice->rating > best_rating) { best_rating = tesschoice->rating; best_class = tesschoice->string[0]; } } FLOAT32 GetBestRatingFor(TBLOB *Blob, LINE_STATS *LineStats, CLASS_ID ClassId); // We have to use char-level adaptation because otherwise // someone should do forced alignment somewhere. void AdaptToChar(TBLOB *Blob, LINE_STATS *LineStats, CLASS_ID ClassId, FLOAT32 Threshold); if (id == best_class) threshold = GoodAdaptiveMatch; else { /* the blob was incorrectly classified - find the rating threshold needed to create a template which will correct the error with some margin. However, don't waste time trying to make templates which are too tight. */ threshold = GetBestRatingFor(blob, &LineStats, id); threshold *= .9; const float max_threshold = .125; const float min_threshold = .02; if (threshold > max_threshold) threshold = max_threshold; // I have cuddled the following line to set it out of the strike // of the coverage testing tool. I have no idea how to trigger // this situation nor I have any necessity to do it. --mezhirov if (threshold < min_threshold) threshold = min_threshold; } if (blob->outlines) AdaptToChar(blob, &LineStats, id, threshold); free_blob(blob); }