📄 topitch.cpp
字号:
else if ((pitsync_linear_version & 3) < 3 || sp_sd > 20 || mid_cuts > 0 || pitch_sd >= textord_words_pitchsd_threshold * row->fixed_pitch) { if (pitch_sd < textord_words_def_prop * row->fixed_pitch) row->pitch_decision = PITCH_MAYBE_PROP; else row->pitch_decision = PITCH_DEF_PROP; } else row->pitch_decision = PITCH_DUNNO; } if (textord_debug_pitch_metric) { res_string = "??"; switch (row->pitch_decision) { case PITCH_DEF_PROP: res_string = "DP"; break; case PITCH_MAYBE_PROP: res_string = "MP"; break; case PITCH_DEF_FIXED: res_string = "DF"; break; case PITCH_MAYBE_FIXED: res_string = "MF"; default: res_string = "??"; } tprintf (":sd/p=%g:occ=%g:init_res=%s\n", pitch_sd / row->fixed_pitch, sp_sd, res_string); } return TRUE;}/********************************************************************** * count_pitch_stats * * Count up the gap and pitch stats on the block to see if it is fixed pitch. * Blobs with gaps smaller than the lower threshold are assumed to be one. * The larger threshold is the word gap threshold. * The return value indicates whether there were any decent values to use. **********************************************************************/BOOL8 count_pitch_stats( //find lines TO_ROW *row, //row to do STATS *gap_stats, //blob gaps STATS *pitch_stats, //centre-centre stats float initial_pitch, //guess at pitch float min_space, //estimate space size BOOL8 ignore_outsize, //discard big objects BOOL8 split_outsize, //split big objects INT32 dm_gap //ignorable gaps ) { BOOL8 prev_valid; //not word broken BLOBNBOX *blob; //current blob //blobs BLOBNBOX_IT blob_it = row->blob_list (); INT32 prev_right; //end of prev blob INT32 prev_centre; //centre of previous blob INT32 x_centre; //centre of this blob INT32 blob_width; //width of blob INT32 width_units; //no of widths in blob float width; //blob width BOX blob_box; //bounding box BOX joined_box; //of super blob gap_stats->clear (); pitch_stats->clear (); if (blob_it.empty ()) return FALSE; prev_valid = FALSE; prev_centre = 0; prev_right = 0; //stop complier warning joined_box = blob_it.data ()->bounding_box (); do { blob_it.forward (); blob = blob_it.data (); if (!blob->joined_to_prev ()) { blob_box = blob->bounding_box (); if (blob_box.left () - joined_box.right () < dm_gap && !blob_it.at_first () || blob->cblob () == NULL && blob->blob () == NULL) joined_box += blob_box; //merge blobs else { blob_width = joined_box.width (); if (split_outsize) { width_units = (INT32) floor ((float) blob_width / initial_pitch + 0.5); if (width_units < 1) width_units = 1; width_units--; } else if (ignore_outsize) { width = (float) blob_width / initial_pitch; width_units = width < 1 + words_default_fixed_limit && width > 1 - words_default_fixed_limit ? 0 : -1; } else width_units = 0; //everything in x_centre = (INT32) (joined_box.left () + (blob_width - width_units * initial_pitch) / 2); if (prev_valid && width_units >= 0) { // if (width_units>0) // { // tprintf("wu=%d, width=%d, xc=%d, adding %d\n", // width_units,blob_width,x_centre,x_centre-prev_centre); // } gap_stats->add (joined_box.left () - prev_right, 1); pitch_stats->add (x_centre - prev_centre, 1); } prev_centre = (INT32) (x_centre + width_units * initial_pitch); prev_right = joined_box.right (); prev_valid = blob_box.left () - joined_box.right () < min_space; prev_valid = prev_valid && width_units >= 0; joined_box = blob_box; } } } while (!blob_it.at_first ()); return gap_stats->get_total () >= 3;}/********************************************************************** * tune_row_pitch * * Use a dp algorithm to fit the character cells and return the sd of * the cell size over the row. **********************************************************************/float tune_row_pitch( //find fp cells TO_ROW *row, //row to do STATS *projection, //vertical projection INT16 projection_left, //edge of projection INT16 projection_right, //edge of projection float space_size, //size of blank float &initial_pitch, //guess at pitch float &best_sp_sd, //space sd INT16 &best_mid_cuts, //no of cheap cuts ICOORDELT_LIST *best_cells, //row cells BOOL8 testing_on //inidividual words ) { int pitch_delta; //offset pitch INT16 mid_cuts; //cheap cuts float pitch_sd; //current sd float best_sd; //best result float best_pitch; //pitch for best result float initial_sd; //starting error float sp_sd; //space sd ICOORDELT_LIST test_cells; //row cells ICOORDELT_IT best_it; //start of best list if (textord_fast_pitch_test) return tune_row_pitch2 (row, projection, projection_left, projection_right, space_size, initial_pitch, best_sp_sd, //space sd best_mid_cuts, best_cells, testing_on); if (textord_disable_pitch_test) { best_sp_sd = initial_pitch; return initial_pitch; } initial_sd = compute_pitch_sd(row, projection, projection_left, projection_right, space_size, initial_pitch, best_sp_sd, best_mid_cuts, best_cells, testing_on); best_sd = initial_sd; best_pitch = initial_pitch; if (testing_on) tprintf ("tune_row_pitch:start pitch=%g, sd=%g\n", best_pitch, best_sd); for (pitch_delta = 1; pitch_delta <= textord_pitch_range; pitch_delta++) { pitch_sd = compute_pitch_sd (row, projection, projection_left, projection_right, space_size, initial_pitch + pitch_delta, sp_sd, mid_cuts, &test_cells, testing_on); if (testing_on) tprintf ("testing pitch at %g, sd=%g\n", initial_pitch + pitch_delta, pitch_sd); if (pitch_sd < best_sd) { best_sd = pitch_sd; best_mid_cuts = mid_cuts; best_sp_sd = sp_sd; best_pitch = initial_pitch + pitch_delta; best_cells->clear (); best_it.set_to_list (best_cells); best_it.add_list_after (&test_cells); } else test_cells.clear (); if (pitch_sd > initial_sd) break; //getting worse } for (pitch_delta = 1; pitch_delta <= textord_pitch_range; pitch_delta++) { pitch_sd = compute_pitch_sd (row, projection, projection_left, projection_right, space_size, initial_pitch - pitch_delta, sp_sd, mid_cuts, &test_cells, testing_on); if (testing_on) tprintf ("testing pitch at %g, sd=%g\n", initial_pitch - pitch_delta, pitch_sd); if (pitch_sd < best_sd) { best_sd = pitch_sd; best_mid_cuts = mid_cuts; best_sp_sd = sp_sd; best_pitch = initial_pitch - pitch_delta; best_cells->clear (); best_it.set_to_list (best_cells); best_it.add_list_after (&test_cells); } else test_cells.clear (); if (pitch_sd > initial_sd) break; } initial_pitch = best_pitch; if (textord_debug_pitch_metric) print_pitch_sd(row, projection, projection_left, projection_right, space_size, best_pitch); return best_sd;}/********************************************************************** * tune_row_pitch * * Use a dp algorithm to fit the character cells and return the sd of * the cell size over the row. **********************************************************************/float tune_row_pitch2( //find fp cells TO_ROW *row, //row to do STATS *projection, //vertical projection INT16 projection_left, //edge of projection INT16 projection_right, //edge of projection float space_size, //size of blank float &initial_pitch, //guess at pitch float &best_sp_sd, //space sd INT16 &best_mid_cuts, //no of cheap cuts ICOORDELT_LIST *best_cells, //row cells BOOL8 testing_on //inidividual words ) { int pitch_delta; //offset pitch INT16 pixel; //pixel coord INT16 best_pixel; //pixel coord INT16 best_delta; //best pitch INT16 best_pitch; //best pitch INT16 start; //of good range INT16 end; //of good range INT32 best_count; //lowest sum float best_sd; //best result STATS *sum_proj; //summed projection best_sp_sd = initial_pitch; if (textord_disable_pitch_test) { return initial_pitch; } sum_proj = new STATS[textord_pitch_range * 2 + 1]; if (sum_proj == NULL) return initial_pitch; best_pitch = (INT32) initial_pitch; for (pitch_delta = -textord_pitch_range; pitch_delta <= textord_pitch_range; pitch_delta++) sum_proj[textord_pitch_range + pitch_delta].set_range (0, best_pitch + pitch_delta + 1); for (pixel = projection_left; pixel <= projection_right; pixel++) { for (pitch_delta = -textord_pitch_range; pitch_delta <= textord_pitch_range; pitch_delta++) sum_proj[textord_pitch_range + pitch_delta].add ((pixel - projection_left) % (best_pitch + pitch_delta), projection->pile_count (pixel)); } best_count = sum_proj[textord_pitch_range].pile_count (0); best_delta = 0; best_pixel = 0; for (pitch_delta = -textord_pitch_range; pitch_delta <= textord_pitch_range; pitch_delta++) { for (pixel = 0; pixel < best_pitch + pitch_delta; pixel++) { if (sum_proj[textord_pitch_range + pitch_delta].pile_count (pixel) < best_count) { best_count = sum_proj[textord_pitch_range + pitch_delta].pile_count (pixel); best_delta = pitch_delta; best_pixel = pixel; } } } if (testing_on) tprintf ("tune_row_pitch:start pitch=%g, best_delta=%d, count=%d\n", initial_pitch, best_delta, best_count); best_pitch += best_delta; initial_pitch = best_pitch; best_count++; best_count += best_count; for (start = best_pixel - 2; start > best_pixel - best_pitch && sum_proj[textord_pitch_range + best_delta].pile_count (start % best_pitch) <= best_count; start--); for (end = best_pixel + 2; end < best_pixel + best_pitch && sum_proj[textord_pitch_range + best_delta].pile_count (end % best_pitch) <= best_count; end++); best_sd = compute_pitch_sd(row, projection, projection_left, projection_right, space_size, initial_pitch, best_sp_sd, best_mid_cuts, best_cells, testing_on, start, end); if (testing_on) tprintf ("tune_row_pitch:output pitch=%g, sd=%g\n", initial_pitch, best_sd); if (textord_debug_pitch_metric) print_pitch_sd(row, projection, projection_left, projection_right, space_size, initial_pitch); delete[]sum_proj; return best_sd;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -