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

📄 common_gfx.h

📁 《Visual C++数字图像识别技术典型案例》之光学字符识别技术源码
💻 H
字号:
/****************************************************************************** * 光学字符识别程序 * 文件名:commonv_gfx.h * 功能  :共用文件实现 * modified by PRTsinghua@hotmail.com******************************************************************************/#ifndef COMMON_GFX_H#define COMMON_GFX_H#include <math.h>#include <assert.h>#include <list>#include <vector>#include <qdialog.h>#include <qimage.h>#include "common_math.h"using std::list;using std::vector;// 点结构template<class T> struct point{	point( T init_x = 0, T init_y = 0 ) : x( init_x ), y( init_y ) {};	T x;	T y;			T get_x() const { return x; }	T get_y() const { return y; }		bool operator==(const point &p) const { return p.x == x && p.y == y; }};// 直线结构struct straight_line{	straight_line() : x( 0 ), y( 0 ), angle( 0 ) {}	straight_line( float x1, float y1, float ang ) : x( x1 ), y( y1 ), angle( ang ) {}	straight_line( float x1, float y1, float x2, float y2 ) : x( x1 ), y( y1 ), angle( atan2( y2 - y1, x2 - x1 ) ) {}	float x;		// 直线中心的x坐标	float y;		// 直线中心的y坐标	float angle;	// 直线的角度		float function( float xval ) const;		bool intersect( const straight_line &line2, float &x_intersect, float &y_intersect ) const;		// 两个直线的交点	straight_line normal( float x, float y ) const;		void construct_perpendicular( float px, float py, float &x_perpendicular, float &y_perpendicular ) const;};// 线段结构class line_segment{public:	line_segment() : p1( 0, 0 ), p2( 0, 0 ) {}	line_segment( float x1, float y1, float x2, float y2 ) : p1( x1, y1 ), p2( x2, y2 ) {}	line_segment( point<float> p1, point<float> p2 ) : p1( p1 ), p2( p2 ) {}		float get_angle() { return atan2( p2.y - p1.y, p2.x - p1.x ); }	bool intersect( const line_segment &seg2, bool touch_is_intersect = false, point<float> *pi = NULL );	private:	point<float> p1;	// 线段上的点1	point<float> p2;	// 线段上的点2	float ang;};// T 必须拥有函数 get_x() 和 get_y()template<class T> struct correlation : public straight_line{	private:		float cos_phi;				// 脉冲的参数		float sin_phi;				// 在线上添加新点	public:		int num_points;				// 序列中点的个数		typename list<T>::iterator first;	// 序列的起点		typename list<T>::iterator last;	// 序列终点		float sum_x;				// x坐标和		float sum_y;				// y坐标和		float mean_dist;			// 点到相关直线的平均距离		correlation() : cos_phi(2), num_points(0), sum_x(0), sum_y(0), mean_dist(0) {}		float distance(const T &p) const { return fabs((p.get_x()-x)*cos_phi+(p.get_y()-y)*sin_phi); }		bool need_correlate() const { return cos_phi==2; }		void set_need_correlate() { cos_phi=2; }		void correlate();		void update();};template<class T> void correlation<T>::correlate(){	assert( num_points > 0 );		// 仅有一个点的线,认为是水平的	if( num_points == 1 )	{		x = sum_x;		y = sum_y;		angle = 0;		cos_phi = cos(angle+M_PI_2);		sin_phi = sin(angle+M_PI_2);		mean_dist = 0;		return;	}		float x_average = sum_x / num_points;	float y_average = sum_y / num_points;	float sum_squares_x = 0;	float sum_squares_y = 0;	float sum_products = 0;	#ifdef GRANT_CORRELATE_INTEGRITY		float chk_sum_x = 0;		float chk_sum_y = 0;		float chk_num_points = 0;	#endif	typename list<T>::iterator i=first;	do {		#ifdef GRANT_CORRELATE_INTEGRITY			chk_sum_x += i->get_x();			chk_sum_y += i->get_y();			chk_num_points++;		#endif		float deltax = i->get_x() - x_average;		float deltay = i->get_y() - y_average;		sum_squares_x += deltax * deltax;		sum_squares_y += deltay * deltay;		sum_products  += deltax * deltay;	} while( i++!=last );	#ifdef GRANT_CORRELATE_INTEGRITY		assert( chk_sum_x == sum_x && chk_sum_y == sum_y && chk_num_points == num_points );	#endif	float t = sum_squares_x - sum_squares_y;	float u = ( sum_squares_x + sum_squares_y )/2.0;	float v = sqrt( t*t + 4*sum_products*sum_products)/2.0;	float lamda = u+v;			// 矩阵A的特征值	// 计算特征向量	float	x1=lamda - sum_squares_y,		x2=lamda - sum_squares_x;	if( fabs(x1)>fabs(x2) )		// 选择正确的方程计算特征向量		x2 = sum_products;	else		x1 = sum_products;	// 保存结果	x = x_average;	y = y_average;	angle = normalize_line_angle( atan2(x2,x1) );	// 计算平均距离	cos_phi = cos(angle+M_PI_2);	sin_phi = sin(angle+M_PI_2);	mean_dist = 0;	i = first;	do {		mean_dist += distance(*i);	} while( i++ != last );	mean_dist /= num_points;}template<class T> void correlation<T>::update(){	sum_x = 0;	sum_y = 0;	num_points = 0;	typename list<T>::iterator i = first;	do {		sum_x += i->get_x();		sum_y += i->get_y();		num_points++;	} while( i++ != last );	correlate();}class Histogram : public QDialog{public:	Histogram( QWidget *parent = 0, const char *name = 0 );	Histogram( const QImage &img, QWidget *parent = 0, const char *name = 0 );		void load( const QImage &img );		// 装载图像	void save();				// 保存直方图到文件	void print();				// 打印图像的统计信息	int get_bw_threshold() { return bw_threshold; } // 返回二值化的阈值	enum drawing_flags 	{		draw_max_white			= 0x00000001,		draw_max_black			= 0x00000002,		draw_threshold			= 0x00000004,		draw_middle			= 0x00000008,		draw_mean_value			= 0x00000010					};	private:	void clear();	void toggle_draw_flag( unsigned int flag );	void drawHistogram( QPixmap &pixmap );	void paintEvent( QPaintEvent * );	void keyPressEvent( QKeyEvent *e );												unsigned long	pix_count;		// 图像中的点数	int		min_value;				// 图像中的最小灰度	int		max_value;				// 图像中的最大灰度	int		mean_value;				// 灰度均值	int 		most_value;			// 最频繁出现的灰度值	int 		least_value;		// 最少出现的灰度值	int		std_deviation;			// 标准分割	double		entropy;			// 图像熵	int 	white_maximum;			// 直方图中白色最大值的位置	int		black_maximum;			// 直方图中黑色最大值的位置	int		bw_threshold;			// 分离阈值	unsigned int 	draw_flags;		// 画图	vector<int>	frequency;			// 灰度频率	vector<float>	log_frequency;	// 灰度频率对数向量	QWidget 	*parent;};class AbstractImage{public:	virtual int get_pixel( int /*x*/, int /*y*/ ) const { return 0; }	virtual void set_pixel( int /*x*/, int /*y*/, int /*color*/ ) { }	virtual bool is_background( int /*x*/, int /*y*/ ) const { return false; }	virtual bool is_border_pixel( int x, int y ) const;		virtual bool is_near_pixel( int x, int y ) const;	};class CharImage: public AbstractImage, public QImage{public:		// 缺省颜色	enum default_colors 	{		black = 0,		white = 255,		transparent = 0,		opaque = 255,		bw_thresh = 127	};	CharImage( int threshold = bw_thresh ) : QImage(), bw_threshold( threshold ) {}	CharImage( const QImage &img, int threshold = bw_thresh ) : QImage( img ), bw_threshold( threshold ) {}	CharImage( int width, int height, int depth, int threshold = bw_thresh, int numColors = 0, Endian bitOrder = IgnoreEndian ) :		QImage( width, height, depth, numColors, bitOrder ), bw_threshold( threshold ) {}	virtual ~CharImage() { }	virtual int get_pixel( int x, int y ) const;	virtual void set_pixel( int x, int y, int col, int transparency = opaque ) { setPixel( x, y, qRgba( col, col, col, transparency ) ); }	virtual bool is_background( int x, int y ) const { return is_background( x, y, bw_threshold ); }		void fill( int color, int transparency = opaque );	void clear() { fill( white ); }	void set_bw_threshold( int threshold = -1 );	int get_bw_threshold() { return bw_threshold; }	bool get_bw_pixel( int x, int y, int threshold = -1 ) const;	bool is_background( int x, int y, int threshold ) const { return !get_bw_pixel( x, y, threshold ); }	bool is_background( int color ) const { return color > bw_threshold; }	CharImage convert_bw( bool auto_threshold = false ) const; // 使用 bw_threshold 的特定转换函数	private:	int bw_threshold; // 二值化阈值};inline int CharImage::get_pixel( int x, int y ) const{	if( x < 0 || x >= width() || y < 0 || y >= height() )		return white;	else		return qGray( pixel( x, y ) );}inline void CharImage::set_bw_threshold( int threshold ){	if ( threshold < 0 ) // 自动检测阈值		threshold = Histogram( *this ).get_bw_threshold();		bw_threshold = threshold;}inline bool CharImage::get_bw_pixel( int x, int y, int threshold ) const{ 	if ( threshold < 0 ) // 使用保存的阈值		return ( get_pixel( x, y ) <= bw_threshold );	return ( get_pixel( x, y ) <= threshold );}inline void CharImage::fill( int color, int transparency ){	for ( int y = 0; y < height(); y++ )		for ( int x = 0; x < width(); x++ )			set_pixel( x, y, color, transparency );}enum direction { 	down, right, up, left};inline direction operator++( direction &d ){	if( d == left )		return ( d = down);	else		return ( d = static_cast<direction> ( static_cast<int>( d ) + 1 ) );}inline direction operator--( direction &d ){	if( d == down )		return ( d = left );	else		return ( d = static_cast<direction> ( static_cast<int>( d ) - 1 ) );}inline direction leftof( direction d ){	return ++d;}// 边缘跟踪class Walker{public:	Walker() {};	void walk_border( int start_x, int start_y );protected:	virtual bool is_border_pixel( int x, int y ) const = 0;	virtual bool is_good_walker_start( int x, int y ) const = 0;	virtual void walker_process( int /*x*/, int /*y*/ ) {};	virtual void walker_process2( int /*x*/, int /*y*/ ) {};};class CharImageWalker: public Walker{public:	CharImageWalker( CharImage &image ) : img( image ) {}	virtual ~CharImageWalker() {};private:	virtual bool is_border_pixel( int x, int y ) const { return img.is_border_pixel( x, y ); }	virtual bool is_good_walker_start( int x, int y ) const;protected:	CharImage &img;};// 一些滤波器int filter( int x, int y, CharImage src, float H[3][3] );CharImage filter( CharImage src, float H[3][3] );CharImage filter( CharImage src, float Hx[3][3], float Hy[3][3], int mode );#endif

⌨️ 快捷键说明

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