makerow.cpp
来自「一OCR的相关资料。.希望对研究OCR的朋友有所帮助.」· C++ 代码 · 共 1,691 行 · 第 1/5 页
CPP
1,691 行
* (textord_merge_x + textord_merge_asc); if (y_min > y_bottom) { //expansion allowed //expandable swallowed_row = TRUE; while (swallowed_row && !row_it.at_last ()) { swallowed_row = FALSE; //get next one test_row = row_it.data_relative (1); //overlaps space if (test_row->max_y () > y_bottom) { if (test_row->min_y () > y_bottom) { row_it.forward ();#ifndef GRAPHICS_DISABLED if (textord_show_expanded_rows && testing_on) plot_parallel_row(test_row, gradient, block_edge, WHITE, rotation);#endif blob_it.set_to_list (row->blob_list ()); blob_it.add_list_after (test_row->blob_list ()); //swallow complete row delete row_it.extract (); row_it.backward (); swallowed_row = TRUE; } else if (test_row->max_y () < y_min) //shorter limit y_bottom = test_row->max_y (); else y_bottom = y_min; //can't expand it } } y_min = y_bottom; //expand it } if (y_max < y_top) { //expansion allowed swallowed_row = TRUE; while (swallowed_row && !row_it.at_first ()) { swallowed_row = FALSE; //get one above test_row = row_it.data_relative (-1); if (test_row->min_y () < y_top) { if (test_row->max_y () < y_top) { row_it.backward (); blob_it.set_to_list (row->blob_list ());#ifndef GRAPHICS_DISABLED if (textord_show_expanded_rows && testing_on) plot_parallel_row(test_row, gradient, block_edge, WHITE, rotation);#endif blob_it.add_list_after (test_row->blob_list ()); //swallow complete row delete row_it.extract (); row_it.forward (); swallowed_row = TRUE; } else if (test_row->min_y () < y_max) //shorter limit y_top = test_row->min_y (); else y_top = y_max; //can't expand it } } y_max = y_top; } //new limits row->set_limits (y_min, y_max); row_it.backward (); } while (!row_it.at_last ());}/********************************************************************** * adjust_row_limits * * Change the limits of rows to suit the default fractions. **********************************************************************/void adjust_row_limits( //tidy limits TO_BLOCK *block //block to do ) { TO_ROW *row; //current row float size; //size of row float ymax; //top of row float ymin; //bottom of row TO_ROW_IT row_it = block->get_rows (); for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) { row = row_it.data (); size = row->max_y () - row->min_y (); size /= textord_merge_x + textord_merge_asc + textord_merge_desc; ymax = size * (textord_merge_x + textord_merge_asc); ymin = -size * textord_merge_desc; row->set_limits (row->intercept () + ymin, row->intercept () + ymax); row->merged = FALSE; }}/********************************************************************** * compute_row_stats * * Compute the linespacing and offset. **********************************************************************/void compute_row_stats( //find lines TO_BLOCK *block, //block to do BOOL8 testing_on //correct orientation ) { INT32 row_index; //of median TO_ROW *row; //current row TO_ROW *prev_row; //previous row float iqr; //inter quartile range TO_ROW_IT row_it = block->get_rows (); //number of rows INT16 rowcount = row_it.length (); TO_ROW **rows; //for choose nth rows = (TO_ROW **) alloc_mem (rowcount * sizeof (TO_ROW *)); if (rows == NULL) MEMORY_OUT.error ("compute_row_stats", ABORT, NULL); rowcount = 0; prev_row = NULL; row_it.move_to_last (); //start at bottom do { row = row_it.data (); if (prev_row != NULL) { rows[rowcount++] = prev_row; prev_row->spacing = row->intercept () - prev_row->intercept (); if (testing_on) tprintf ("Row at %g yields spacing of %g\n", row->intercept (), prev_row->spacing); } prev_row = row; row_it.backward (); } while (!row_it.at_last ()); block->key_row = prev_row; block->baseline_offset = fmod (prev_row->parallel_c (), block->line_spacing); if (testing_on) tprintf ("Blob based spacing=(%g,%g), offset=%g", block->line_size, block->line_spacing, block->baseline_offset); if (rowcount > 0) { row_index = choose_nth_item (rowcount * 3 / 4, rows, rowcount, sizeof (TO_ROW *), row_spacing_order); iqr = rows[row_index]->spacing; row_index = choose_nth_item (rowcount / 4, rows, rowcount, sizeof (TO_ROW *), row_spacing_order); iqr -= rows[row_index]->spacing; row_index = choose_nth_item (rowcount / 2, rows, rowcount, sizeof (TO_ROW *), row_spacing_order); block->key_row = rows[row_index]; if (testing_on) tprintf (" row based=%g(%g)", rows[row_index]->spacing, iqr); if (rowcount > 2 && iqr < rows[row_index]->spacing * textord_linespace_iqrlimit) { if (!textord_new_initial_xheight) { if (rows[row_index]->spacing < block->line_spacing && rows[row_index]->spacing > block->line_size) //within range block->line_size = rows[row_index]->spacing; //spacing=size else if (rows[row_index]->spacing > block->line_spacing) block->line_size = block->line_spacing; //too big so use max } else { if (rows[row_index]->spacing < block->line_spacing) block->line_size = rows[row_index]->spacing; else block->line_size = block->line_spacing; //too big so use max } if (block->line_size < textord_min_xheight) block->line_size = (float) textord_min_xheight; block->line_spacing = rows[row_index]->spacing; block->max_blob_size = block->line_spacing * textord_excess_blobsize; } block->baseline_offset = fmod (rows[row_index]->intercept (), block->line_spacing); } if (testing_on) tprintf ("\nEstimate line size=%g, spacing=%g, offset=%g\n", block->line_size, block->line_spacing, block->baseline_offset); free_mem(rows);}/********************************************************************** * compute_block_xheight * * Compute the xheight of the individual rows, then correlate them * and interpret ascenderless lines, correcting xheights. **********************************************************************/void compute_block_xheight( //find lines TO_BLOCK *block, //block to do float gradient //global skew ) { TO_ROW *row; //current row int xh_count, desc_count; //no of samples float block_median; //median blob size int asc_count, cap_count; INT32 min_size, max_size; //limits on xheight INT32 evidence; //no of samples on row float xh_sum, desc_sum; //for averages float asc_sum, cap_sum; TO_ROW_IT row_it = block->get_rows (); STATS row_heights; //block evidence if (row_it.empty ()) return; //no rows block_median = median_block_xheight (block, gradient); block_median *= 2; if (block_median < block->line_size) block_median = block->line_size; // tprintf("Block median=%g, linesize=%g\n", // block_median,block->line_size); max_size = (INT32) ceil (block_median); min_size = (INT32) floor (block_median * textord_minxh); row_heights.set_range (min_size, max_size + 1); xh_count = desc_count = asc_count = cap_count = 0; xh_sum = desc_sum = asc_sum = cap_sum = 0.0f; for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) { row = row_it.data (); evidence = compute_row_xheight (row, min_size, max_size, gradient); if (row->xheight > 0 && row->ascrise > 0) { row_heights.add ((INT32) row->xheight, evidence); xh_count += evidence; asc_sum += row->ascrise; asc_count++; } else if (row->xheight > 0) { cap_sum += row->xheight; //assume just caps cap_count++; } if (row->descdrop != 0) { desc_sum += row->descdrop; desc_count++; } } if (xh_count > 0) { //median xh_sum = row_heights.ile (0.5); asc_sum /= asc_count; } else if (cap_count > 0) { cap_sum /= cap_count; //must assume caps xh_sum = cap_sum * textord_merge_x / (textord_merge_x + textord_merge_asc); asc_sum = cap_sum * textord_merge_asc / (textord_merge_x + textord_merge_asc); } else { //default sizes xh_sum = block_median * textord_merge_x; asc_sum = block_median * textord_merge_asc; } if (desc_count > 0) { desc_sum /= desc_count; } else { desc_sum = xh_sum * textord_merge_desc / textord_merge_x; } // tprintf("Block average x height=%g, count=%d, asc=%g/%d, desc=%g/%d,cap=%g/%d\n", // xh_sum,xh_count,asc_sum,asc_count,desc_sum,desc_count, // cap_sum,cap_count); if (xh_sum < textord_min_xheight) xh_sum = (float) textord_min_xheight; block->xheight = xh_sum; for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) { correct_row_xheight (row_it.data (), xh_sum, asc_sum, desc_sum); }}/********************************************************************** * median_block_xheight * * Compute the linespacing and offset. **********************************************************************/float median_block_xheight( //find lines TO_BLOCK *block, //block to do float gradient //global skew ) { TO_ROW *row; //current row float result; //output size float xcentre; //centre of blob TO_ROW_IT row_it = block->get_rows (); BLOBNBOX_IT blob_it; BLOBNBOX *blob; //current blob float *heights; //for choose nth INT32 blob_count; //blobs in block INT32 blob_index; //current blob blob_count = 0; for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) blob_count += row_it.data ()->blob_list ()->length (); heights = (float *) alloc_mem (blob_count * sizeof (float)); if (heights == NULL) MEMORY_OUT.error ("compute_row_stats", ABORT, NULL); blob_index = 0; for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) { row = row_it.data (); 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 (); if (!blob->joined_to_prev ()) { xcentre = (blob->bounding_box ().left () + blob->bounding_box ().right ()) / 2.0f; heights[blob_index] = blob->bounding_box ().top () - gradient * xcentre - row->parallel_c (); if (heights[blob_index] > 0) blob_index++; } } } ASSERT_HOST (blob_index > 0); //dont expect 0 blob_count = blob_index; blob_index = choose_nth_item (blob_count / 2, heights, blob_count); result = heights[blob_index]; free_mem(heights); return result;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?