wordseg.cpp
来自「一OCR的相关资料。.希望对研究OCR的朋友有所帮助.」· C++ 代码 · 共 621 行 · 第 1/2 页
CPP
621 行
/********************************************************************** * File: wordseg.cpp (Formerly wspace.c) * Description: Code to segment the blobs into words. * Author: Ray Smith * Created: Fri Oct 16 11:32:28 BST 1992 * * (C) Copyright 1992, Hewlett-Packard Ltd. ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** http://www.apache.org/licenses/LICENSE-2.0 ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. * **********************************************************************/#include "mfcpch.h"#ifdef __UNIX__#include <assert.h>#endif#include "stderr.h"#include "blobbox.h"#include "ocrclass.h"#include "lmedsq.h"#include "statistc.h"#include "drawtord.h"#include "makerow.h"#include "pitsync1.h"#include "blobcmpl.h"#include "tovars.h"#include "topitch.h"#include "tospace.h"#include "fpchop.h"#include "wordseg.h"#define EXTERNEXTERN BOOL_VAR (textord_fp_chopping, TRUE, "Do fixed pitch chopping");extern /*"C" */ ETEXT_DESC *global_monitor; //progress monitor#define FIXED_WIDTH_MULTIPLE 5#define BLOCK_STATS_CLUSTERS 10/********************************************************************** * make_words * * Arrange the blobs into words. **********************************************************************/void make_words( //make words ICOORD page_tr, //top right float gradient, //page skew BLOCK_LIST *blocks, //block list TO_BLOCK_LIST *land_blocks, //rotated for landscape TO_BLOCK_LIST *port_blocks //output list ) { TO_BLOCK_IT block_it; //iterator TO_BLOCK *block; //current block; compute_fixed_pitch (page_tr, port_blocks, gradient, FCOORD (0.0f, -1.0f), !(BOOL8) textord_test_landscape); if (global_monitor != NULL) { global_monitor->ocr_alive = TRUE; global_monitor->progress = 25; } to_spacing(page_tr, port_blocks); block_it.set_to_list (port_blocks); for (block_it.mark_cycle_pt (); !block_it.cycled_list (); block_it.forward ()) { block = block_it.data (); // set_row_spaces(block,FCOORD(1,0),!(BOOL8)textord_test_landscape); //make proper classes make_real_words (block, FCOORD (1.0f, 0.0f)); }}/********************************************************************** * set_row_spaces * * Set the min_space and max_nonspace members of the row so that * the blobs can be arranged into words. **********************************************************************/void set_row_spaces( //find space sizes TO_BLOCK *block, //block to do FCOORD rotation, //for drawing BOOL8 testing_on //correct orientation ) { INT32 maxwidth; //of widest space TO_ROW *row; //current row TO_ROW_IT row_it = block->get_rows (); if (row_it.empty ()) return; //empty block maxwidth = (INT32) ceil (block->xheight * textord_words_maxspace); for (row_it.mark_cycle_pt (); !row_it.cycled_list (); row_it.forward ()) { row = row_it.data (); if (row->fixed_pitch == 0) { // if (!textord_test_mode // && row_words(block,row,maxwidth,rotation,testing_on)==0 // || textord_test_mode // && row_words2(block,row,maxwidth,rotation,testing_on)==0) // { row->min_space = (INT32) ceil (row->pr_space - (row->pr_space - row->pr_nonsp) * textord_words_definite_spread); row->max_nonspace = (INT32) floor (row->pr_nonsp + (row->pr_space - row->pr_nonsp) * textord_words_definite_spread); if (testing_on && textord_show_initial_words) { tprintf ("Assigning defaults %d non, %d space to row at %g\n", row->max_nonspace, row->min_space, row->intercept ()); } row->space_threshold = (row->max_nonspace + row->min_space) / 2; row->space_size = row->pr_space; row->kern_size = row->pr_nonsp; // } }#ifndef GRAPHICS_DISABLED if (textord_show_initial_words && testing_on) { plot_word_decisions (to_win, (INT16) row->fixed_pitch, row); }#endif }}/********************************************************************** * row_words * * Compute the max nonspace and min space for the row. **********************************************************************/INT32 row_words( //compute space size TO_BLOCK *block, //block it came from TO_ROW *row, //row to operate on INT32 maxwidth, //max expected space size FCOORD rotation, //for drawing BOOL8 testing_on //for debug ) { BOOL8 testing_row; //contains testpt BOOL8 prev_valid; //if decent size BOOL8 this_valid; //current blob big enough INT32 prev_x; //end of prev blob INT32 min_gap; //min interesting gap INT32 cluster_count; //no of clusters INT32 gap_index; //which cluster INT32 smooth_factor; //for smoothing stats BLOBNBOX *blob; //current blob float lower, upper; //clustering parameters float gaps[3]; //gap clusers ICOORD testpt; BOX blob_box; //bounding box //iterator BLOBNBOX_IT blob_it = row->blob_list (); STATS gap_stats (0, maxwidth); STATS cluster_stats[4]; //clusters testpt = ICOORD (textord_test_x, textord_test_y); smooth_factor = (INT32) (block->xheight * textord_wordstats_smooth_factor + 1.5); // if (testing_on) // tprintf("Row smooth factor=%d\n",smooth_factor); prev_valid = FALSE; prev_x = -MAX_INT32; testing_row = FALSE; 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.contains (testpt)) testing_row = TRUE; gap_stats.add (blob_box.width (), 1); } min_gap = (INT32) floor (gap_stats.ile (textord_words_width_ile)); gap_stats.clear (); for (blob_it.mark_cycle_pt (); !blob_it.cycled_list (); blob_it.forward ()) { blob = blob_it.data (); if (!blob->joined_to_prev ()) { blob_box = blob->bounding_box (); // this_valid=blob_box.width()>=min_gap; this_valid = TRUE; if (this_valid && prev_valid && blob_box.left () - prev_x < maxwidth) { gap_stats.add (blob_box.left () - prev_x, 1); } prev_x = blob_box.right (); prev_valid = this_valid; } } if (gap_stats.get_total () == 0) { row->min_space = 0; //no evidence row->max_nonspace = 0; return 0; } gap_stats.smooth (smooth_factor); lower = row->xheight * textord_words_initial_lower; upper = row->xheight * textord_words_initial_upper; cluster_count = gap_stats.cluster (lower, upper, textord_spacesize_ratioprop, 3, cluster_stats); while (cluster_count < 2 && ceil (lower) < floor (upper)) { //shrink gap upper = (upper * 3 + lower) / 4; lower = (lower * 3 + upper) / 4; cluster_count = gap_stats.cluster (lower, upper, textord_spacesize_ratioprop, 3, cluster_stats); } if (cluster_count < 2) { row->min_space = 0; //no evidence row->max_nonspace = 0; return 0; } for (gap_index = 0; gap_index < cluster_count; gap_index++) gaps[gap_index] = cluster_stats[gap_index + 1].ile (0.5); //get medians if (cluster_count > 2) { if (testing_on && textord_show_initial_words) { tprintf ("Row at %g has 3 sizes of gap:%g,%g,%g\n", row->intercept (), cluster_stats[1].ile (0.5), cluster_stats[2].ile (0.5), cluster_stats[3].ile (0.5)); } lower = gaps[0]; if (gaps[1] > lower) { upper = gaps[1]; //prefer most frequent if (upper < block->xheight * textord_words_min_minspace && gaps[2] > gaps[1]) { upper = gaps[2]; } } else if (gaps[2] > lower && gaps[2] >= block->xheight * textord_words_min_minspace) upper = gaps[2]; else if (lower >= block->xheight * textord_words_min_minspace) { upper = lower; //not nice lower = gaps[1]; if (testing_on && textord_show_initial_words) { tprintf ("Had to switch most common from lower to upper!!\n"); gap_stats.print (stdout, TRUE); } } else { row->min_space = 0; //no evidence row->max_nonspace = 0; return 0; } } else { if (gaps[1] < gaps[0]) { if (testing_on && textord_show_initial_words) { tprintf ("Had to switch most common from lower to upper!!\n"); gap_stats.print (stdout, TRUE); } lower = gaps[1]; upper = gaps[0]; } else { upper = gaps[1]; lower = gaps[0]; } } if (upper < block->xheight * textord_words_min_minspace) { row->min_space = 0; //no evidence row->max_nonspace = 0; return 0; } if (upper * 3 < block->min_space * 2 + block->max_nonspace || lower * 3 > block->min_space * 2 + block->max_nonspace) { if (testing_on && textord_show_initial_words) { tprintf ("Disagreement between block and row at %g!!\n", row->intercept ()); tprintf ("Lower=%g, upper=%g, Stats:\n", lower, upper); gap_stats.print (stdout, TRUE); } } row->min_space = (INT32) ceil (upper - (upper - lower) * textord_words_definite_spread); row->max_nonspace = (INT32) floor (lower + (upper - lower) * textord_words_definite_spread); row->space_threshold = (row->max_nonspace + row->min_space) / 2; row->space_size = upper; row->kern_size = lower; if (testing_on && textord_show_initial_words) { if (testing_row) { tprintf ("GAP STATS\n"); gap_stats.print (stdout, TRUE); tprintf ("SPACE stats\n"); cluster_stats[2].print (stdout, FALSE); tprintf ("NONSPACE stats\n"); cluster_stats[1].print (stdout, FALSE); } tprintf ("Row at %g has minspace=%d(%g), max_non=%d(%g)\n", row->intercept (), row->min_space, upper, row->max_nonspace, lower); } return cluster_stats[2].get_total ();}/********************************************************************** * row_words2 * * Compute the max nonspace and min space for the row. **********************************************************************/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?