tesseract  4.0.0-1-g2a2b
osdetect.cpp File Reference
#include <algorithm>
#include <cmath>
#include <memory>
#include "osdetect.h"
#include "blobbox.h"
#include "blread.h"
#include "colfind.h"
#include "fontinfo.h"
#include "imagefind.h"
#include "linefind.h"
#include "oldlist.h"
#include "qrsequence.h"
#include "ratngs.h"
#include "strngs.h"
#include "tabvector.h"
#include "tesseractclass.h"
#include "textord.h"

Go to the source code of this file.

Functions

int orientation_and_script_detection (STRING &filename, OSResults *osr, tesseract::Tesseract *tess)
 
int os_detect (TO_BLOCK_LIST *port_blocks, OSResults *osr, tesseract::Tesseract *tess)
 
int os_detect_blobs (const GenericVector< int > *allowed_scripts, BLOBNBOX_CLIST *blob_list, OSResults *osr, tesseract::Tesseract *tess)
 
bool os_detect_blob (BLOBNBOX *bbox, OrientationDetector *o, ScriptDetector *s, OSResults *osr, tesseract::Tesseract *tess)
 
int OrientationIdToValue (const int &id)
 

Variables

const float kSizeRatioToReject = 2.0
 
const int kMinAcceptableBlobHeight = 10
 
const float kScriptAcceptRatio = 1.3
 
const float kHanRatioInKorean = 0.7
 
const float kHanRatioInJapanese = 0.3
 
const float kNonAmbiguousMargin = 1.0
 

Function Documentation

◆ orientation_and_script_detection()

int orientation_and_script_detection ( STRING filename,
OSResults osr,
tesseract::Tesseract tess 
)

Definition at line 190 of file osdetect.cpp.

192  {
193  STRING name = filename; //truncated name
194  const char *lastdot; //of name
195  TBOX page_box;
196 
197  lastdot = strrchr (name.string (), '.');
198  if (lastdot != nullptr)
199  name[lastdot-name.string()] = '\0';
200 
201  ASSERT_HOST(tess->pix_binary() != nullptr)
202  int width = pixGetWidth(tess->pix_binary());
203  int height = pixGetHeight(tess->pix_binary());
204 
205  BLOCK_LIST blocks;
206  if (!read_unlv_file(name, width, height, &blocks))
207  FullPageBlock(width, height, &blocks);
208 
209  // Try to remove non-text regions from consideration.
210  TO_BLOCK_LIST land_blocks, port_blocks;
211  remove_nontext_regions(tess, &blocks, &port_blocks);
212 
213  if (port_blocks.empty()) {
214  // page segmentation did not succeed, so we need to find_components first.
215  tess->mutable_textord()->find_components(tess->pix_binary(),
216  &blocks, &port_blocks);
217  } else {
218  page_box.set_left(0);
219  page_box.set_bottom(0);
220  page_box.set_right(width);
221  page_box.set_top(height);
222  // Filter_blobs sets up the TO_BLOCKs the same as find_components does.
223  tess->mutable_textord()->filter_blobs(page_box.topright(),
224  &port_blocks, true);
225  }
226 
227  return os_detect(&port_blocks, osr, tess);
228 }
const ICOORD & topright() const
Definition: rect.h:104
void set_top(int y)
Definition: rect.h:61
void set_bottom(int y)
Definition: rect.h:68
const char * string() const
Definition: strngs.cpp:196
int os_detect(TO_BLOCK_LIST *port_blocks, OSResults *osr, tesseract::Tesseract *tess)
Definition: osdetect.cpp:233
Definition: rect.h:34
void find_components(Pix *pix, BLOCK_LIST *blocks, TO_BLOCK_LIST *to_blocks)
Definition: tordmain.cpp:219
void set_right(int x)
Definition: rect.h:82
Pix * pix_binary() const
Textord * mutable_textord()
void set_left(int x)
Definition: rect.h:75
void filter_blobs(ICOORD page_tr, TO_BLOCK_LIST *blocks, bool testing_on)
Definition: tordmain.cpp:250
Definition: strngs.h:45
bool read_unlv_file(STRING name, int32_t xsize, int32_t ysize, BLOCK_LIST *blocks)
Definition: blread.cpp:34
void FullPageBlock(int width, int height, BLOCK_LIST *blocks)
Definition: blread.cpp:65
#define ASSERT_HOST(x)
Definition: errcode.h:84

◆ OrientationIdToValue()

int OrientationIdToValue ( const int &  id)

Definition at line 568 of file osdetect.cpp.

568  {
569  switch (id) {
570  case 0:
571  return 0;
572  case 1:
573  return 270;
574  case 2:
575  return 180;
576  case 3:
577  return 90;
578  default:
579  return -1;
580  }
581 }

◆ os_detect()

int os_detect ( TO_BLOCK_LIST *  port_blocks,
OSResults osr,
tesseract::Tesseract tess 
)

Definition at line 233 of file osdetect.cpp.

234  {
235  int blobs_total = 0;
236  TO_BLOCK_IT block_it;
237  block_it.set_to_list(port_blocks);
238 
239  BLOBNBOX_CLIST filtered_list;
240  BLOBNBOX_C_IT filtered_it(&filtered_list);
241 
242  for (block_it.mark_cycle_pt(); !block_it.cycled_list();
243  block_it.forward ()) {
244  TO_BLOCK* to_block = block_it.data();
245  if (to_block->block->pdblk.poly_block() &&
246  !to_block->block->pdblk.poly_block()->IsText()) continue;
247  BLOBNBOX_IT bbox_it;
248  bbox_it.set_to_list(&to_block->blobs);
249  for (bbox_it.mark_cycle_pt (); !bbox_it.cycled_list ();
250  bbox_it.forward ()) {
251  BLOBNBOX* bbox = bbox_it.data();
252  C_BLOB* blob = bbox->cblob();
253  TBOX box = blob->bounding_box();
254  ++blobs_total;
255 
256  // Catch illegal value of box width and avoid division by zero.
257  if (box.width() == 0) continue;
258  // TODO: Can height and width be negative? If not, remove fabs.
259  float y_x = std::fabs((box.height() * 1.0f) / box.width());
260  float x_y = 1.0f / y_x;
261  // Select a >= 1.0 ratio
262  float ratio = x_y > y_x ? x_y : y_x;
263  // Blob is ambiguous
264  if (ratio > kSizeRatioToReject) continue;
265  if (box.height() < kMinAcceptableBlobHeight) continue;
266  filtered_it.add_to_end(bbox);
267  }
268  }
269  return os_detect_blobs(nullptr, &filtered_list, osr, tess);
270 }
Definition: rect.h:34
int16_t width() const
Definition: rect.h:115
POLY_BLOCK * poly_block() const
Definition: pdblock.h:56
bool IsText() const
Definition: polyblk.h:49
const float kSizeRatioToReject
Definition: osdetect.cpp:40
BLOCK * block
Definition: blobbox.h:790
TBOX bounding_box() const
Definition: stepblob.cpp:255
BLOBNBOX_LIST blobs
Definition: blobbox.h:785
const int kMinAcceptableBlobHeight
Definition: osdetect.cpp:41
PDBLK pdblk
Definition: ocrblock.h:192
int16_t height() const
Definition: rect.h:108
C_BLOB * cblob() const
Definition: blobbox.h:269
int os_detect_blobs(const GenericVector< int > *allowed_scripts, BLOBNBOX_CLIST *blob_list, OSResults *osr, tesseract::Tesseract *tess)
Definition: osdetect.cpp:278

◆ os_detect_blob()

bool os_detect_blob ( BLOBNBOX bbox,
OrientationDetector o,
ScriptDetector s,
OSResults osr,
tesseract::Tesseract tess 
)

Definition at line 329 of file osdetect.cpp.

331  {
332  tess->tess_cn_matching.set_value(true); // turn it on
333  tess->tess_bn_matching.set_value(false);
334  C_BLOB* blob = bbox->cblob();
335  TBLOB* tblob = TBLOB::PolygonalCopy(tess->poly_allow_detailed_fx, blob);
336  TBOX box = tblob->bounding_box();
337  FCOORD current_rotation(1.0f, 0.0f);
338  FCOORD rotation90(0.0f, 1.0f);
339  BLOB_CHOICE_LIST ratings[4];
340  // Test the 4 orientations
341  for (int i = 0; i < 4; ++i) {
342  // Normalize the blob. Set the origin to the place we want to be the
343  // bottom-middle after rotation.
344  // Scaling is to make the rotated height the x-height.
345  float scaling = static_cast<float>(kBlnXHeight) / box.height();
346  float x_origin = (box.left() + box.right()) / 2.0f;
347  float y_origin = (box.bottom() + box.top()) / 2.0f;
348  if (i == 0 || i == 2) {
349  // Rotation is 0 or 180.
350  y_origin = i == 0 ? box.bottom() : box.top();
351  } else {
352  // Rotation is 90 or 270.
353  scaling = static_cast<float>(kBlnXHeight) / box.width();
354  x_origin = i == 1 ? box.left() : box.right();
355  }
356  std::unique_ptr<TBLOB> rotated_blob(new TBLOB(*tblob));
357  rotated_blob->Normalize(nullptr, &current_rotation, nullptr,
358  x_origin, y_origin, scaling, scaling,
359  0.0f, static_cast<float>(kBlnBaselineOffset),
360  false, nullptr);
361  tess->AdaptiveClassifier(rotated_blob.get(), ratings + i);
362  current_rotation.rotate(rotation90);
363  }
364  delete tblob;
365 
366  bool stop = o->detect_blob(ratings);
367  s->detect_blob(ratings);
368  int orientation = o->get_orientation();
369  stop = s->must_stop(orientation) && stop;
370  return stop;
371 }
bool must_stop(int orientation)
Definition: osdetect.cpp:560
static TBLOB * PolygonalCopy(bool allow_detailed_fx, C_BLOB *src)
Definition: blobs.cpp:337
void AdaptiveClassifier(TBLOB *Blob, BLOB_CHOICE_LIST *Choices)
Definition: adaptmatch.cpp:192
Definition: rect.h:34
const int kBlnXHeight
Definition: normalis.h:24
const int kBlnBaselineOffset
Definition: normalis.h:25
int16_t width() const
Definition: rect.h:115
int16_t left() const
Definition: rect.h:72
int16_t top() const
Definition: rect.h:58
void detect_blob(BLOB_CHOICE_LIST *scores)
Definition: osdetect.cpp:471
TBOX bounding_box() const
Definition: blobs.cpp:478
Definition: points.h:189
bool detect_blob(BLOB_CHOICE_LIST *scores)
Definition: osdetect.cpp:382
int16_t right() const
Definition: rect.h:79
Definition: blobs.h:268
int16_t bottom() const
Definition: rect.h:65
int16_t height() const
Definition: rect.h:108
C_BLOB * cblob() const
Definition: blobbox.h:269

◆ os_detect_blobs()

int os_detect_blobs ( const GenericVector< int > *  allowed_scripts,
BLOBNBOX_CLIST *  blob_list,
OSResults osr,
tesseract::Tesseract tess 
)

Definition at line 278 of file osdetect.cpp.

280  {
281  OSResults osr_;
282  int minCharactersToTry = tess->min_characters_to_try;
283  int maxCharactersToTry = 5 * minCharactersToTry;
284  if (osr == nullptr)
285  osr = &osr_;
286 
287  osr->unicharset = &tess->unicharset;
288  OrientationDetector o(allowed_scripts, osr);
289  ScriptDetector s(allowed_scripts, osr, tess);
290 
291  BLOBNBOX_C_IT filtered_it(blob_list);
292  int real_max = std::min(filtered_it.length(), maxCharactersToTry);
293  // tprintf("Total blobs found = %d\n", blobs_total);
294  // tprintf("Number of blobs post-filtering = %d\n", filtered_it.length());
295  // tprintf("Number of blobs to try = %d\n", real_max);
296 
297  // If there are too few characters, skip this page entirely.
298  if (real_max < minCharactersToTry / 2) {
299  tprintf("Too few characters. Skipping this page\n");
300  return 0;
301  }
302 
303  BLOBNBOX** blobs = new BLOBNBOX*[filtered_it.length()];
304  int number_of_blobs = 0;
305  for (filtered_it.mark_cycle_pt (); !filtered_it.cycled_list ();
306  filtered_it.forward ()) {
307  blobs[number_of_blobs++] = (BLOBNBOX*)filtered_it.data();
308  }
309  QRSequenceGenerator sequence(number_of_blobs);
310  int num_blobs_evaluated = 0;
311  for (int i = 0; i < real_max; ++i) {
312  if (os_detect_blob(blobs[sequence.GetVal()], &o, &s, osr, tess)
313  && i > minCharactersToTry) {
314  break;
315  }
316  ++num_blobs_evaluated;
317  }
318  delete [] blobs;
319 
320  // Make sure the best_result is up-to-date
321  int orientation = o.get_orientation();
322  osr->update_best_script(orientation);
323  return num_blobs_evaluated;
324 }
UNICHARSET * unicharset
Definition: osdetect.h:80
bool os_detect_blob(BLOBNBOX *bbox, OrientationDetector *o, ScriptDetector *s, OSResults *osr, tesseract::Tesseract *tess)
Definition: osdetect.cpp:329
void update_best_script(int orientation_id)
Definition: osdetect.cpp:89
UNICHARSET unicharset
Definition: ccutil.h:68
DLLSYM void tprintf(const char *format,...)
Definition: tprintf.cpp:37

Variable Documentation

◆ kHanRatioInJapanese

const float kHanRatioInJapanese = 0.3

Definition at line 46 of file osdetect.cpp.

◆ kHanRatioInKorean

const float kHanRatioInKorean = 0.7

Definition at line 45 of file osdetect.cpp.

◆ kMinAcceptableBlobHeight

const int kMinAcceptableBlobHeight = 10

Definition at line 41 of file osdetect.cpp.

◆ kNonAmbiguousMargin

const float kNonAmbiguousMargin = 1.0

Definition at line 48 of file osdetect.cpp.

◆ kScriptAcceptRatio

const float kScriptAcceptRatio = 1.3

Definition at line 43 of file osdetect.cpp.

◆ kSizeRatioToReject

const float kSizeRatioToReject = 2.0

Definition at line 40 of file osdetect.cpp.