makerow.cpp

来自「一OCR的相关资料。.希望对研究OCR的朋友有所帮助.」· C++ 代码 · 共 1,691 行 · 第 1/5 页

CPP
1,691
字号
/********************************************************************** * compute_row_xheight * * Estimate the xheight of this row. * Compute the ascender rise and descender drop at the same time. **********************************************************************/INT32 compute_row_xheight(                   //find lines                          TO_ROW *row,       //row to do                          INT32 min_height,  //min xheight                          INT32 max_height,  //max xheight                          float gradient     //global skew                         ) {  BOOL8 in_best_pile;            //control of mode size  INT32 prev_size;               //previous size  float xcentre;                 //centre of blob  float height;                  //height of blob  BLOBNBOX_IT blob_it = row->blob_list ();  BLOBNBOX *blob;                //current blob  INT32 blob_count;              //blobs in block  INT32 x;                       //xheight index  INT32 asc;                     //ascender index  INT32 blob_index;              //current blob  INT32 mode_count;              //no of modes  INT32 best_count;              //count of best x so far  float ratio;                   //size ratio  INT32 modes[MAX_HEIGHT_MODES]; //biggest piles  STATS heights (min_height, max_height + 1);  for (blob_it.mark_cycle_pt (); !blob_it.cycled_list (); blob_it.forward ()) {    blob = blob_it.data ();    if (!blob->joined_to_prev ()) {      xcentre =        (blob->bounding_box ().left () +        blob->bounding_box ().right ()) / 2.0f;      height = blob->bounding_box ().top ();      if (textord_fix_xheight_bug)        height -= row->baseline.y (xcentre);      else        height -= gradient * xcentre + row->parallel_c ();      if (height >= min_height && height <= max_height        && (!textord_xheight_tweak || height > textord_min_xheight))        heights.add ((INT32) floor (height + 0.5), 1);    }  }  blob_index = heights.mode ();  //find mode                                 //get count of mode  blob_count = heights.pile_count (blob_index);  if (textord_debug_xheights)    tprintf ("min_height=%d, max_height=%d, mode=%d, count=%d, total=%d,%d\n",      min_height, max_height, blob_index, blob_count,      heights.get_total (), row->blob_list ()->length ());  row->ascrise = 0.0f;  row->xheight = 0.0f;  row->descdrop = 0.0f;          //undefined;  in_best_pile = FALSE;  prev_size = -MAX_INT32;  best_count = 0;  if (blob_count > 0) {                                 //get biggest ones    mode_count = compute_height_modes (&heights, min_height, max_height, modes, MAX_HEIGHT_MODES);    for (x = 0; x < mode_count - 1; x++) {      if (modes[x] != prev_size + 1)        in_best_pile = FALSE;    //had empty height      if (heights.pile_count (modes[x])        >= blob_count * textord_xheight_mode_fraction      && (in_best_pile || heights.pile_count (modes[x]) > best_count)) {        for (asc = x + 1; asc < mode_count; asc++) {          ratio = (float) modes[asc] / modes[x];          if (textord_ascx_ratio_min < ratio            && ratio < textord_ascx_ratio_max            && heights.pile_count (modes[asc])          >= blob_count * textord_ascheight_mode_fraction) {            if (heights.pile_count (modes[x]) > best_count) {              in_best_pile = TRUE;              best_count = heights.pile_count (modes[x]);            }            //                                              tprintf("X=%d, asc=%d, count=%d,  ratio=%g\n",            //                                                      modes[x],modes[asc]-modes[x],            //                                                      heights.pile_count(modes[x]),            //                                                      ratio);            prev_size = modes[x];            row->xheight = (float) modes[x];            row->ascrise = (float) (modes[asc] - modes[x]);          }        }      }    }    if (row->xheight == 0) {                                 //single mode      row->xheight = (float) blob_index;      row->ascrise = 0.0f;      if (textord_debug_xheights)        tprintf ("Single mode xheight set to %g\n", row->xheight);    }    else if (textord_debug_xheights)      tprintf ("Multi-mode xheight set to %g, asc=%g\n",          row->xheight, row->ascrise);    row->descdrop = (float) compute_row_descdrop (row, gradient);    //find descenders  }  return best_count;}/********************************************************************** * compute_row_descdrop * * Estimate the descdrop of this row. **********************************************************************/INT32 compute_row_descdrop(                //find lines                           TO_ROW *row,    //row to do                           float gradient  //global skew                          ) {  INT32 min_height = (INT32) floor (row->xheight * textord_descx_ratio_min);  INT32 max_height = (INT32) floor (row->xheight * textord_descx_ratio_max);  float xcentre;                 //centre of blob  float height;                  //height of blob  BLOBNBOX_IT blob_it = row->blob_list ();  BLOBNBOX *blob;                //current blob  INT32 blob_count;              //blobs in block  INT32 blob_index;              //current blob  STATS heights (min_height, max_height + 1);  for (blob_it.mark_cycle_pt (); !blob_it.cycled_list (); blob_it.forward ()) {    blob = blob_it.data ();    if (!blob->joined_to_prev ()) {      xcentre =        (blob->bounding_box ().left () +        blob->bounding_box ().right ()) / 2.0f;      height =        gradient * xcentre + row->parallel_c () -        blob->bounding_box ().bottom ();      if (height >= min_height && height <= max_height)        heights.add ((INT32) floor (height + 0.5), 1);    }  }  blob_index = heights.mode ();  //find mode                                 //get count of mode  blob_count = heights.pile_count (blob_index);  return blob_count > 0 ? -blob_index : 0;}/********************************************************************** * compute_height_modes * * Find the top maxmodes values in the input array and put their * indices in the output in the order in which they occurred. **********************************************************************/INT32 compute_height_modes(                   //find lines                           STATS *heights,    //stats to search                           INT32 min_height,  //bottom of range                           INT32 max_height,  //top of range                           INT32 *modes,      //output array                           INT32 maxmodes     //size of modes                          ) {  INT32 pile_count;              //no in source pile  INT32 src_count;               //no of source entries  INT32 src_index;               //current entry  INT32 least_count;             //height of smalllest  INT32 least_index;             //index of least  INT32 dest_count;              //index in modes  src_count = max_height + 1 - min_height;  dest_count = 0;  least_count = MAX_INT32;  least_index = -1;  for (src_index = 0; src_index < src_count; src_index++) {    pile_count = heights->pile_count (min_height + src_index);    if (pile_count > 0) {      if (dest_count < maxmodes) {        if (pile_count < least_count) {                                 //find smallest in array          least_count = pile_count;          least_index = dest_count;        }        modes[dest_count++] = min_height + src_index;      }      else if (pile_count >= least_count) {        while (least_index < maxmodes - 1) {          modes[least_index] = modes[least_index + 1];          //shuffle up          least_index++;        }                                 //new one on end        modes[maxmodes - 1] = min_height + src_index;        if (pile_count == least_count) {                                 //new smallest          least_index = maxmodes - 1;        }        else {          least_count = heights->pile_count (modes[0]);          least_index = 0;          for (dest_count = 1; dest_count < maxmodes; dest_count++) {            pile_count = heights->pile_count (modes[dest_count]);            if (pile_count < least_count) {                                 //find smallest              least_count = pile_count;              least_index = dest_count;            }          }        }      }    }  }  return dest_count;}/********************************************************************** * correct_row_xheight * * Adjust the xheight etc of this row if not within reasonable limits * of the average for the block. **********************************************************************/void correct_row_xheight(                //fix bad values                         TO_ROW *row,    //row to fix                         float xheight,  //average values                         float ascrise,                         float descdrop) {  if (textord_row_xheights) {    if (row->xheight <= 0)      row->xheight = xheight;    if (row->ascrise < row->xheight * (textord_ascx_ratio_min - 1)) {      if (row->xheight >= xheight * (1 - textord_xheight_error_margin)      && row->xheight <= xheight * (1 + textord_xheight_error_margin)) {        row->all_caps = FALSE;        row->ascrise = ascrise;      }      else if (row->xheight >=        (xheight + ascrise) * (1 - textord_xheight_error_margin)        && row->xheight <=      (xheight + ascrise) * (1 + textord_xheight_error_margin)) {        row->all_caps = TRUE;                                 //it was caps        row->ascrise = row->xheight - xheight;        row->xheight = xheight;      }      else {        row->all_caps = TRUE;        row->ascrise = row->xheight * ascrise / (xheight + ascrise);        row->xheight -= row->ascrise;      }    }    else      row->all_caps = FALSE;    row->ascrise = ascrise;    if (row->descdrop >= -row->xheight * (textord_ascx_ratio_min - 1))      row->descdrop = descdrop;  }  else {    if (row->xheight < xheight * (1 - textord_xheight_error_margin)      || row->xheight > xheight * (1 + textord_xheight_error_margin))      row->xheight = xheight;    //set to average    row->all_caps = row->ascrise <= 0;    if (row->ascrise < ascrise * (1 - textord_xheight_error_margin)      || row->ascrise > ascrise * (1 + textord_xheight_error_margin))      row->ascrise = ascrise;    //set to average    if (row->descdrop < descdrop * (1 - textord_xheight_error_margin)      || row->descdrop > descdrop * (1 + textord_xheight_error_margin))      row->descdrop = descdrop;  //set to average  }}/********************************************************************** * separate_underlines * * Test wide objects for being potential underlines. If they are then * put them in a separate list in the block. **********************************************************************/void separate_underlines(                  //make rough chars                         TO_BLOCK *block,  //block to do                         float gradient,   //skew angle                         FCOORD rotation,  //inverse landscape                         BOOL8 testing_on  //correct orientation                        ) {  BLOBNBOX *blob;                //current blob  PBLOB *poly_blob;              //rotated blob  C_BLOB *rotated_blob;          //rotated blob  TO_ROW *row;                   //current row  float length;                  //of g_vec  BOX blob_box;  FCOORD blob_rotation;          //inverse of rotation  FCOORD g_vec;                  //skew rotation  BLOBNBOX_IT blob_it;           //iterator                                 //iterator  BLOBNBOX_IT under_it = &block->underlines;  TO_ROW_IT row_it = block->get_rows ();                                 //length of vector  length = sqrt (1 + gradient * gradient);  g_vec = FCOORD (1 / length, -gradient / length);  blob_rotation = FCOORD (rotation.x (), -rotation.y ());  blob_rotation.rotate (g_vec);  //unoding everything  for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) {    row = row_it.data ();                                 //get blobs    blob_it.set_to_list (row->blob_list ());    for (blob_it.mark_cycle_pt (); !blob_it.cycled_list ();    blob_it.forward ()) {      blob = blob_it.data ();      blob_box = blob->bounding_box ();      if (blob_box.width () > block->line_size * textord_underline_width) {        if (textord_cblob_blockocc && blob->cblob () != NULL) {          rotated_blob = crotate_cblob (blob->cblob (),            blob_rotation);          if (test_underline (testing_on && textord_show_final_rows,            rotated_blob, (INT16) row->intercept (),            (INT16) (block->line_size *            (textord_merge_x +          textord_merge_asc / 2.0f)))) {            under_it.add_after_then_move (blob_it.extract ());            if (testing_on && textord_show_final_rows) {              tprintf ("Underlined blob at (%d,%d)->(%d,%d) ",                rotated_blob->bounding_box ().left (),                rotated_blob->bounding_box ().bottom (),                rotated_blob->bounding_box ().right (),                rotated_blob->bounding_box ().top ());              tprintf ("(Was (%d,%d)->(%d,%d))\n",                blob_box.left (), blob_box.bottom (),                blob_box.right (), blob_box.top ());            }          }          delete rotated_blob;        }        else {          if (blob->blob () != NULL) {            //                                      if (testing_on && textord_show_final_rows)            //   

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?