⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 image.cpp

📁 vc++数字图像识别技术典型案例
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************** * 光学字符识别程序 * 文件名:image.cpp * 功能  :图像处理相关函数实现 * modified by PRTsinghua@hotmail.com******************************************************************************/#include <stdlib.h>#include <assert.h>#include <math.h>#include <algorithm>#include <iostream>#include <qpixmap.h>#include <qimage.h>#include <qcolor.h>#include <klocale.h>#include <klineeditdlg.h>#include <kconfig.h>#include "common.h"#include "image.h"#include "segimage.h"#include "character.h"#include "page.h"#include "abstract_character.h"#include "global.h"#include <kmessagebox.h>using std::max;using std::ios;using std::istream;const float Image::cs_angle_treshold = degtorad( 30 );// 构造函数Image::Image( KognitionApp *app, const char *name ) : 	QDialog( app, name ), 	draw_flags( 0 ), 	border_list_number( 0 ), 	match_char_pos( 1 ), 	mark_cs( -1 ), 	pen_size( 1 ), 	avg_line_thickness( 0 ), 	segimage( NULL ), 	skeleton( NULL ), 	abstract_char( NULL ), 	app( app ){	setCaption( "character" );	setMouseTracking( true );	setBackgroundMode( NoBackground );}// 析构函数Image::~Image(){	clear();}// 清理函数void Image::clear(){	if ( segimage )		delete segimage;	segimage = NULL;		if ( skeleton )		delete skeleton;	skeleton = NULL;	if ( abstract_char )		delete abstract_char;	abstract_char = NULL;	char_group.clear();	bl.clear();	spl.clear();	cssl.clear();	border_list_number = 0;	match_char_pos    = 1;	avg_line_thickness = 0;}// 向量化abstract_character Image::vectorize( const CharImage &char_scan, float base_line_pos, float reference_height, float angle ){	scan = char_scan;	scan_bw = char_scan.convert_bw();	clear();	segimage = new Segimage( scan );	build_cssg();	skeleton = new character( *segimage, spl );	abstract_char = new abstract_character( *skeleton, base_line_pos, reference_height, angle );	repaint();	return *abstract_char;}// 识别recognized_char_group Image::recognize( const CharImage &char_scan, float base_line_pos, float reference_height, float angle ){	scan = char_scan;	scan_bw = char_scan.convert_bw();	clear();	segimage = new Segimage( scan );		#ifdef SPEED_MEASURE		struct timeval curtime;		seconds_passed( curtime );	#endif	build_cssg();	#ifdef SPEED_MEASURE		cout << "build_cssg() total ( in s ): " << seconds_passed( curtime ) << endl;	#endif		skeleton = new character( *segimage, spl );	#ifdef SPEED_MEASURE		seconds_passed( curtime );	#endif		abstract_char = new abstract_character( *skeleton, base_line_pos, reference_height, angle );	#ifdef SPEED_MEASURE		cout << "abstract_character() total ( in s ): " << seconds_passed( curtime ) << endl;	#endif		char_group = char_db.match( *abstract_char );	#ifdef SPEED_MEASURE		cout << "match_character() total ( in s ): " << seconds_passed( curtime ) << endl;	#endif		repaint();	return char_group;}// 获得图像的最大高度float Image::get_max_height( const CharImage &char_scan, float angle ){	scan = char_scan;	clear();	segimage = new Segimage( scan );		build_cssg();	skeleton = new character( *segimage, spl );	return abstract_character::get_real_height( *skeleton, angle );}// 点的方向double Image::direction( Segimage::point p ){	float Hx[3][3] = { { -1,  0,  1 }, 			   { -2,  0,  2 }, 			   { -1,  0,  1 } };		float Hy[3][3] = { { -1, -2, -1 }, 			   {  0,  0,  0 }, 			   {  1,  2,  1 } };		 	return atan2( -filter( p.x, p.y, scan, Hy ), filter( p.x, p.y, scan, Hx ) );}// 计算角度double Image::calc_dang( double prev, double curr ){	double dangle = normalize_angle_pi( curr - prev );		if ( fabs( dangle ) < degtorad( 2 ) )		dangle = 0;		return dangle;}// 平滑void Image::smooth_points( ringlist_iterator< Segimage::point > first, ringlist_iterator< Segimage::point > last, int num_points ){	ringlist_iterator< Segimage::point > pre_first = first;	--pre_first;		ringlist_iterator< Segimage::point > post_last = last;	++post_last;		ringlist_iterator< Segimage::point > post_post_last = post_last;	++post_post_last;				if ( ( pre_first->dang < 0 ) == ( post_post_last->dang < 0 ) )	{		double base_angle = pre_first->ang;		double delta = normalize_angle_pi( post_last->ang-base_angle ) / ( num_points + 1 );		int n = 0;				while( n++ < num_points )		{			first->good_smoothed = true;			first->oang = first->ang;	// 记住初始角度			( first++ )->ang = normalize_angle_pi( base_angle + delta * n );		}	}	else	{		// 迭代循环		for ( int i = 0; i < max_iter; i++ )		{			ringlist_iterator< Segimage::point > f = first;			int np = num_points;			double prev_ang = pre_first->ang;						while( np-- > 0 )			{				Segimage::point &p = *( f++ );				p.dang = calc_dang( prev_ang, p.ang );								if ( p.oang == 0 ) 		// 记住初始角度					p.oang = p.ang; 				// ang( p(i) ) = ang( p(i-1) ) + ( dang( p(i) ) + dang( p(i+1) ) ) / 2				p.ang = normalize_angle_pi( prev_ang + ( p.dang + f->dang ) / 2 );				prev_ang = p.ang;			}						f->dang = calc_dang( prev_ang, f->ang );		}	}}// 判断相对的边界是否标以同样的方向: => true = 同样的方向bool Image::opposite_same_direction( ringlist_iterator< Segimage::point > &start ){	bool same_dir = false;	// 检查两个边界	// |   |   /    /	// +---+  /    /	// |   | *    /	// +--s+/    /	// *        /	// --------/	for ( int dir = 0; dir <= 1; dir++ )	// dir == 0 => 后向; dir == 1 => 前向	{		ringlist_iterator< Segimage::point > i = start;		ringlist_iterator< Segimage::point > j = start->opp;				if ( dir ) {			++i; ++j;		} else {			--i; --j;		}				Segimage::point p = *i;		p.set_opposite( j );		// 检测是否x、y都相等		if ( ( ( start->x >= p.x ) == ( start->opp->x >= p.opp->x ) ) && 		     ( ( start->y >= p.y ) == ( start->opp->y >= p.opp->y ) ) )		{			same_dir = true;			break;		}	}	return same_dir;}// 创建图像序列int Image::construct_sequence( ringlist_iterator< Segimage::point > &start, Segimage &simage, Segimage::cs_sequence &seq ){	// 计算阈值	avg_line_thickness = simage.avg_line_thickness();	int outer_threshold = max( static_cast<int>( ceil( avg_line_thickness ) ), 3 );	start->processed = true;	seq.push_back( &( *start ) );	int num_sequences = 1;	bool opp_same_dir = opposite_same_direction( start );	for ( int dir = 0; dir <= 1; dir++ ) // dir == false => 后向; dir == true => 前向	{		ringlist_iterator< Segimage::point > done = start; // 上一个交叉片断的起点		ringlist_iterator< Segimage::point > p[2] = { start, start->opp };		ringlist_iterator< Segimage::point > stop_point[2] = { start.end(), start.end() };		bool found[2] = { true, true }; 				do {			ringlist_iterator< Segimage::point > q[4] = { p[0], p[1] };			bool reset_found[2] = { false, false }; 						for ( int i = 0; i <= 1; i++ ) 			{				if ( !found[i] ) // 没有更多的交叉区段					continue;				int n = min( static_cast<int>( q[i].get_corresponding_list()->size() ), outer_threshold );				int n_old = n;								bool pass = false;				if ( q[i]->processed ) 					pass = true; // 不检查最后一个交叉区段的起点				// 检查起点的相反点方向是否正确				else if ( q[i] == start->opp && q[i]->length != -1 )				{					ringlist_iterator< Segimage::point > forward = q[i];										if ( dir == ( !opp_same_dir && i ) )						--forward;					else						++forward;										Segimage::point pt( forward->x, forward->y );					pt.set_opposite( q[i]->opp );					if ( line_segment( start->x, start->y, start->opp->x, start->opp->y ).intersect( 						line_segment( pt.x, pt.y, pt.opp->x, pt.opp->y ), true ) )							pass = true;				}				//寻找下一个起点				while( n-- && q[i] != p[1-i] && ( pass || q[i]->length == -1 ) ) 				{					pass = false;					if ( dir == ( !opp_same_dir && i ) )						--q[i];					else						++q[i];				}				bool stop_case =				      q[i]->processed ||	// 已经处理的交叉段				      q[i] == p[1-i]  ||				    ( q[i]->length != -1 &&                                      q[i]->opp.get_corresponding_list() != p[1-i].get_corresponding_list() ); // cross section to other list                                if ( n <= 0 || // 列表中没有其它的交叉段了				    stop_case )				{                                        found[i] = false;					if ( stop_case )						stop_point[i] = q[i];	// 定义终止点					else if ( n <= 0 && n_old == outer_threshold )	// 确信下一次搜索此边						reset_found[i] = true;			// 该交叉段可能在阈值内				}			}			if ( !found[0] && !found[1] )	// 没有发现更多的交叉段				break;			bool got_len[4] = { false, false, false, false };			int len[4] = { 0, 0, 0, 0 };			if ( !found[0] )			{				got_len[0] = got_len[3] = true;				len[0] = len[3] = outer_threshold+1;				q[0] = q[1];			}			if ( !found[1] )			{				got_len[1] = got_len[2]=true;				len[1] = len[2] = outer_threshold+1;				q[1] = q[0];			}			q[2] = q[1]->opp;	// q[0] 和 q[2] 在 side 1			q[3] = q[0]->opp;	// q[1] 和 q[3] 在 side 2			bool stop_now = false;						for ( int i = 0; i <= 1; i++ ) // i == 0 => side 1; i == 1 => side 2			{				for ( ringlist_iterator< Segimage::point > m = p[i];					!got_len[i] || !got_len[i+2]; dir == ( !opp_same_dir && i ) ? --m : ++m )				{					for ( int j = 0; j <= 1; j++ )					{						int pos = i+2*j;						if ( !got_len[pos] )						{							if ( m == stop_point[i] )								stop_now = true;							if ( m == q[pos] )								got_len[pos] = true;							else								len[pos]++;						}					}				}			}			if ( stop_now )				break;			// 比较长度,判断该旋转哪个交叉段			int min_dist_q0_index = len[0] < len[3] ? 0 : 3;			int min_dist_q0 = len[min_dist_q0_index];			int sum_q0 = len[0] + len[3];						int min_dist_q1_index = len[1] < len[2] ? 1 : 2;			int min_dist_q1 = len[min_dist_q1_index];			int sum_q1 = len[1] + len[2];			if ( min_dist_q0<min_dist_q1 || ( min_dist_q0 == min_dist_q1 && sum_q0<sum_q1 ) )			{				// 选择两个cs间距离大点的点				if ( len[min_dist_q0_index == 0 ? 3 : 0] > outer_threshold )					break;				p[0] = q[0];				p[1] = q[3];				done = q[0];			}			else			{						if ( len[min_dist_q1_index == 1 ? 2 : 1] > outer_threshold ) // 曲率太大					break;				p[0] = q[2];				p[1] = q[1];				done = q[1];			}			assert( !done->processed );			done->processed = true;	// 确信交叉段在列表里只有一份						if ( dir )				seq.push_back( &( *done ) );			else				seq.push_front( &( *done ) );						num_sequences++;							for ( int i = 0; i <= 1; i++ )				if ( reset_found[i] )					found[i] = true;		} while( true );	}	return num_sequences;}void Image::build_cssg(){

⌨️ 快捷键说明

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