| 155 | } |
| 156 | |
| 157 | void EquationDetect::IdentifySpecialText( |
| 158 | BLOBNBOX *blobnbox, const int height_th) { |
| 159 | ASSERT_HOST(blobnbox != NULL); |
| 160 | if (blobnbox->bounding_box().height() < height_th && height_th > 0) { |
| 161 | // For small blob, we simply set to BSTT_NONE. |
| 162 | blobnbox->set_special_text_type(BSTT_NONE); |
| 163 | return; |
| 164 | } |
| 165 | |
| 166 | BLOB_CHOICE_LIST ratings_equ, ratings_lang; |
| 167 | C_BLOB* blob = blobnbox->cblob(); |
| 168 | // TODO(joeliu/rays) Fix this. We may have to normalize separately for |
| 169 | // each classifier here, as they may require different PolygonalCopy. |
| 170 | TBLOB* tblob = TBLOB::PolygonalCopy(false, blob); |
| 171 | const TBOX& box = tblob->bounding_box(); |
| 172 | |
| 173 | // Normalize the blob. Set the origin to the place we want to be the |
| 174 | // bottom-middle, and scaling is to make the height the x-height. |
| 175 | float scaling = static_cast<float>(kBlnXHeight) / box.height(); |
| 176 | float x_orig = (box.left() + box.right()) / 2.0f, y_orig = box.bottom(); |
| 177 | TBLOB* normed_blob = new TBLOB(*tblob); |
| 178 | normed_blob->Normalize(NULL, NULL, NULL, x_orig, y_orig, scaling, scaling, |
| 179 | 0.0f, static_cast<float>(kBlnBaselineOffset), |
| 180 | false, NULL); |
| 181 | equ_tesseract_.AdaptiveClassifier(normed_blob, &ratings_equ); |
| 182 | lang_tesseract_->AdaptiveClassifier(normed_blob, &ratings_lang); |
| 183 | delete normed_blob; |
| 184 | delete tblob; |
| 185 | |
| 186 | // Get the best choice from ratings_lang and rating_equ. As the choice in the |
| 187 | // list has already been sorted by the certainty, we simply use the first |
| 188 | // choice. |
| 189 | BLOB_CHOICE *lang_choice = NULL, *equ_choice = NULL; |
| 190 | if (ratings_lang.length() > 0) { |
| 191 | BLOB_CHOICE_IT choice_it(&ratings_lang); |
| 192 | lang_choice = choice_it.data(); |
| 193 | } |
| 194 | if (ratings_equ.length() > 0) { |
| 195 | BLOB_CHOICE_IT choice_it(&ratings_equ); |
| 196 | equ_choice = choice_it.data(); |
| 197 | } |
| 198 | |
| 199 | float lang_score = lang_choice ? lang_choice->certainty() : -FLT_MAX; |
| 200 | float equ_score = equ_choice ? equ_choice->certainty() : -FLT_MAX; |
| 201 | |
| 202 | const float kConfScoreTh = -5.0f, kConfDiffTh = 1.8; |
| 203 | // The scores here are negative, so the max/min == fabs(min/max). |
| 204 | // float ratio = fmax(lang_score, equ_score) / fmin(lang_score, equ_score); |
| 205 | float diff = fabs(lang_score - equ_score); |
| 206 | BlobSpecialTextType type = BSTT_NONE; |
| 207 | |
| 208 | // Classification. |
| 209 | if (fmax(lang_score, equ_score) < kConfScoreTh) { |
| 210 | // If both score are very small, then mark it as unclear. |
| 211 | type = BSTT_UNCLEAR; |
| 212 | } else if (diff > kConfDiffTh && equ_score > lang_score) { |
| 213 | // If equ_score is significantly higher, then we classify this character as |
| 214 | // math symbol. |
nothing calls this directly
no test coverage detected