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

📄 page.cpp

📁 vc++数字图像识别技术典型案例
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		lines.push_back( char_line() );	for ( int y = 0; y < scan.height(); y++ )		// 行数	{		for ( int x = 0; x < scan.width(); x++ )	// 列数		{			if ( scan.is_background( x, y ) )		// 搜索黑点				continue;							list<char_line>::iterator line = lines.end();			for ( list<char_line>::iterator l = lines.begin(); l != lines.end(); ++l ) // 判断正确的行			{				// 清空旧的已经识别行				if ( l->is_done() )					l->clear();								// 检验字符是否在另一行上				if ( line == lines.end() )				{					if (  l->empty() ) 						line = l;					else if ( l->same_line( x, y, true ) )						line = l;				}			}			if ( line != lines.end() )			// 发现匹配行			{				BoundingBox bb;				extract_part( x, y, scan, bb );		// 构建包围盒				assert( bb.width() > 0 && bb.height() > 0 );								// 忽略变形				if ( ( ( bb.width() / bb.height() < very_long_character_ratio &&				         bb.height() / bb.width() < very_long_character_ratio*1.5 ) ) &&				     ( bb.area > bb.width()*bb.height() * min_area_divisor )				   )				{					last_x = x;					line->add_char( bb );			// 添加字符到行				}			}		}		// 行分割完成后,识别字符		if ( !lines.begin()->is_done() && ( !( --lines.end() )->same_line( last_x, y ) || y == scan.height()-1 ) )		{			if ( y != scan.height()-1 )			{				bool got_fooled = false;								for ( list<char_line>::iterator l = lines.begin(); l != lines.end(); ++l )					if ( l->same_line( l->get_last_x(), y )  )					{						got_fooled = true;						break;					}								if ( got_fooled ) // 发现点所属于的行					continue;			}						repaint();						list<char_line>::iterator line1, line2;			for( line1 = line2 = lines.begin(), ++line2; line1 != lines.end(); ++line1, ++line2 )			{				if ( line1->empty() || line1->is_done() )	// 为空的情况					continue;								else if ( ( line2 != lines.end() && 					    !line2->empty() &&					    line1->get_avg_height() < line2->get_avg_height()*base_line::diaresis_ratio ) ||					  line1->intersects( *line2 ) )				{					if ( !line2->merge_line( &( *line1 ) ) )	// 合并					{						--line1;						--line2;					}					continue;				}				base_line baseline( *line1 );								// 计算字符旋转后的最高高度				guarded_ptr<CharImage> part = line1->get_max_part()->part;				float max_height = max_height_img.get_max_height( 					const_cast<const CharImage&>( *part ), -baseline.get_angle() );				collector.set_char_height( max_height );								// 计算行中的字符数目				for ( char_line::iterator mb = line1->begin(); mb != line1->end(); ++mb )				{										QPixmap character( mb->width()+2, mb->height()+2 );					QPainter painter( &character );					painter.fillRect( 0, 0, mb->width()+2, mb->height()+2, QColor( "white" ) );										for ( list< BoundingBox >::iterator bb = mb->parts.begin(); bb != mb->parts.end(); ++bb )					{						QPixmap part;						assert( part.convertFromImage( *bb->part ) );						painter.drawPixmap( bb->min_x - mb->min_x, bb->min_y - mb->min_y, part );					}					painter.end();										if ( char_count++ > 0 ) 					{						int chosen = KMessageBox::warningYesNoCancel( NULL, "Continue to next character?" 							"\n" "Press 'Cancel' to cycle through all." );												if ( chosen == KMessageBox::No )							return;						else if ( chosen == KMessageBox::Cancel )							char_count = INT_MIN; // 不再询问					}										if ( !img )						return;										CharImage char_img = character.convertToImage();					char_img.set_bw_threshold( hist->get_bw_threshold() );										if( data_base_def ) 	// 数据库定义模式					{											abstract_character ac = img->vectorize( 							char_img, baseline.get_base_y( *mb ), max_height, -baseline.get_angle() );												if( *data_base_def )							char_db.append_char_def( ac, *( data_base_def++ ) );					}					else			// OCR 模式					{						// 识别字符						recognized_char_group group = img->recognize( 							char_img, baseline.get_base_y( *mb ), max_height, -baseline.get_angle() );												group.set_geometrics( mb->min_x, mb->min_y, mb->width(), mb->height() );						collector.append_char( group );					}				}								if( !data_base_def ) // OCR 模式					collector.append_newline(); // 行结束的地方								if ( y < scan.height()-1 && ( line2 == lines.end() || line2->empty() ) && line1->get_next_line() )					y = line1->get_next_line();								if ( line2 == --lines.end() && !line2->empty() &&				     line2->get_avg_height() < line1->get_avg_height()*base_line::diaresis_ratio )				{					line1->clear();					++line1, ++line2;					lines.splice( lines.begin(), lines, line1 );				}				else					line1->set_done();			} // 缓冲区结尾		last_x = 0;		}	}	if( !data_base_def )	// OCR 模式		collector.finish();}// 提取特征void Page::extract_part( int start_x, int start_y, CharImage &source, BoundingBox &bb ){	SizeWalker sizewalker( source, bb );	sizewalker.walk_border( start_x, start_y );	// 创建空图像	bb.part = guarded_ptr<CharImage>( new CharImage( bb.width(), bb.height(), 32, hist->get_bw_threshold() ) );	bb.part->setAlphaBuffer( true );		// 以一定透明度填充图像	bb.part->fill( CharImage::white, CharImage::transparent );		CopyWalker copywalker( source, bb );	copywalker.walk_border( start_x, start_y );		// 从字符部分到新图像移动像素	for ( int y = 0; y < bb.height(); y++ )	{		int mode = 0;		for ( int x = 0; x < bb.width(); x++ )		{			int color = bb.part->get_pixel( x, y );						if ( color == CharImage::white && ( mode == 1 || mode == 3 ) )				mode--;		// 搜索模式或拷贝模式			else if ( !bb.part->is_background( color ) )			{				if ( mode == 1 || mode == 2 )					mode++;	// 拷贝模式或监听模式								bb.area++; 	// 记住黑色像素的数目				source.set_pixel( x + bb.min_x, y + bb.min_y, CharImage::white ); // clear pixel from original image				continue;			}						else if ( color < CharImage::white && bb.part->is_background( color ) )			{				mode = 1;	// 监听模式				continue;			}						if ( mode == 2 ) 	// 拷贝模式			{				int scolor = source.get_pixel( x + bb.min_x, y + bb.min_y ); // 源像素颜色				bb.part->set_pixel( x, y, scolor ); // 拷贝像素				source.set_pixel( x + bb.min_x, y + bb.min_y, CharImage::white ); // 从源图像中清空像素								if ( !bb.part->is_background( scolor ) )					bb.area++; // 记住黑色像素的数目			}				}	}	bb.min_x++;	bb.min_y++;	bb.max_x--;	bb.max_y--;}// 设置缩放比率void Page::setScale( float scale ){	if ( scale > 0 )	{		assure_range( 0, 3000/width(), scale );		int max_xpos = qRound( pix.width() * scale - width() );		int max_ypos = qRound( pix.height() * scale - height() );		assure_range( 0, max_xpos < 0 ? 0 : max_xpos, pix_xpos ); 		assure_range( 0, max_ypos < 0 ? 0 : max_ypos, pix_ypos );	}	else		pix_xpos = pix_ypos = 0;		float min_scale = min( min( static_cast<float>( width() ) / ( pix.width() - pix_xpos ), 			            static_cast<float>( height() ) / ( pix.height() - pix_ypos ) ), static_cast<float>( 1 ) );	pix_scale = scale < 0 ? scale : scale < min_scale ? min_scale : scale;	repaint();}// 获取缩放比率float Page::getScale( bool realScale ) {	float scale;		if ( realScale )				switch ( static_cast<int>( pix_scale ) )		{			case -1:	scale = min( static_cast<float>( width() ) / ( pix.width() - pix_xpos ), 						     static_cast<float>( height() ) / ( pix.height() - pix_ypos ) );					break;			case -2:	scale = static_cast<float>( width() ) / ( pix.width() - pix_xpos );					break;			case -3:	scale = static_cast<float>( height() ) / ( pix.height() - pix_ypos );					break;			case -4:	scale = 1;					break;			default:	scale = pix_scale;		}	else		scale = pix_scale;		return scale; }// 设置 x 坐标void Page::setXPos( int xpos ){	if ( pix_scale != -1 && pix_scale != -2 )	{		int max_xpos = qRound( pix.width() * getScale() - width() );		assure_range( 0, max_xpos < 0 ? 0 : max_xpos, xpos ); 		pix_xpos = xpos;		repaint();	}}// 设置 y 坐标void Page::setYPos( int ypos ){	if ( pix_scale != -1 && pix_scale != -3 )	{		int max_ypos = qRound( pix.height() * getScale() - height() );		assure_range( 0, max_ypos < 0 ? 0 : max_ypos, ypos );		pix_ypos = ypos;		repaint();	}}// 画矩形void Page::drawRectangle( QPainter &p, float scale, int min_x, int min_y, int max_x, int max_y ){	p.drawRect( QRect( QPoint( qRound( min_x * scale - pix_xpos ), qRound( min_y * scale - pix_ypos ) ), 			   QPoint( qRound( ++max_x * scale - pix_xpos ), qRound( ++max_y * scale - pix_ypos ) ) ) );}// 绘制事件void Page::paintEvent( QPaintEvent * ){	QPixmap pixmap( size() );	// 画背景	pixmap.fill( "grey" );	// 在pixmap上绘制信息	drawRecognitionState( pixmap, getScale(), pix_xpos, pix_ypos );	// 在窗口上实际绘制	bitBlt( this, 0, 0, &pixmap );}// 绘制识别状态void Page::drawRecognitionState( QPixmap &pixmap, float scale, int pix_xpos, int pix_ypos ){		QWMatrix m;		m.scale( scale, scale );		QPixmap scaledPix;		if ( draw_flags & draw_bw )	{		if ( pix_bw.isNull() )		{			CharImage img = pix.convertToImage();			img.set_bw_threshold( scan.get_bw_threshold() );			pix_bw.convertFromImage( img.convert_bw() );		}		scaledPix = pix_bw.xForm( m );	}	else		scaledPix = pix.xForm( m );	int psize = max( 1, qRound( pen_size*scale ) );	QPen darkgreen( "darkgreen", psize, SolidLine, FlatCap, RoundJoin );	QPen red( "red", psize, SolidLine, FlatCap, RoundJoin );	QPen darkred( "darkred", psize, SolidLine, FlatCap, RoundJoin );	QPen darkmagenta( "darkmagenta", psize, SolidLine, FlatCap, RoundJoin );	QPen darkblue( "darkblue", psize, SolidLine, FlatCap, RoundJoin );	// 绘制图像	QPainter painter( &pixmap );	painter.drawPixmap( -pix_xpos, -pix_ypos, scaledPix );	// 绘制调试信息	for( list<char_line>::iterator line = lines.begin(); line != lines.end(); ++line )	{		for ( char_line::iterator mb = line->begin(); mb != line->end(); ++mb )		{			// 绘制包围盒			if( draw_flags & draw_boundingboxes )			{				for ( list< BoundingBox >::iterator bb = mb->parts.begin(); bb != mb->parts.end(); ++bb )				{						painter.setPen( darkblue );					drawRectangle( painter, scale, bb->min_x, bb->min_y, bb->max_x, bb->max_y );				}			}						// 绘制 metaboxes			if( draw_flags & draw_metaboxes )			{						int pos_shift = 0;				if ( draw_flags & draw_boundingboxes ) // 避免重绘包围盒					pos_shift = 2 * pen_size;								painter.setPen( darkgreen );				drawRectangle( painter, scale, mb->min_x - pos_shift, mb->min_y - pos_shift, 					       mb->max_x + pos_shift, mb->max_y + pos_shift );							}						// 绘制最高的字符			if( draw_flags & draw_maxpart )						{				painter.setPen( darkmagenta );				const BoundingBox *mp = &( *line->get_max_part() );				drawRectangle( painter, scale, mp->min_x, mp->min_y, mp->max_x, mp->max_y );			}		}				if ( !line->empty() )		{			base_line baseline( *line );			// 绘制基线			if ( draw_flags & draw_baseline )			{				painter.setPen( red );				painter.moveTo( 0 - pix_xpos, qRound( baseline.get_line()->function( 0 ) * scale - pix_ypos ) );				painter.lineTo( qRound( pix.width() * scale - pix_xpos ), 						qRound( baseline.get_line()->function( pix.width() ) * scale - pix_ypos ) );			}			if ( draw_flags & draw_basepoints )			{				for ( list< point<float> >::iterator bp = baseline.begin(); bp != baseline.end(); ++bp )				{						painter.save();										painter.setPen( darkred );					painter.setBrush( "darkred" );					painter.moveTo( qRound( bp->x * scale - pix_xpos ), qRound( bp->y * scale - pix_ypos ) );					int diameter = qRound( line->get_avg_height() / 10 * scale );					painter.drawEllipse( qRound( bp->x * scale - pix_xpos - diameter/2 ), 					                     qRound( bp->y * scale - pix_ypos - diameter/2 ), diameter, diameter );					painter.restore();				}			}		}	}}// 改变线条粗细void Page::change_line_thickness( bool bigger ){	// 改变输出pixmap的线条粗细	if( bigger )		pen_size++;	else	{		if( pen_size>1 )			pen_size--;		else			return;	}	repaint();}// 设置绘制标识void Page::set_draw_flag( drawing_flags flag, bool state ){	if( state )		draw_flags|=flag;	else		draw_flags&=~flag;	repaint();}// 清空void Page::clear(){	pix_xpos = pix_ypos = 0;	pix.resize( 0, 0 );	pix_bw.resize( 0, 0 );	lines.clear();}// 鼠标移动事件void Page::mouseMoveEvent( QMouseEvent *e ){	if( pix.width()!=0 )	{		float scale = getScale();		int x = qRound( e->x() / scale );		int y = qRound( e->y() / scale );		app->slotStatusMsg( QString( "Position ( x, y ): %1, %2" ).arg( x ).arg( y ) );	}}// 创建快照void Page::makeSnapshot(){	float scale = getScale();	QPixmap pixmap( qRound( pix.width()*scale ), qRound( pix.height()*scale ) );	drawRecognitionState( pixmap, scale, 0, 0 );		if ( pixmap.save( "snapshot_page.png", "PNG" ) )				app->slotStatusMsg( "Snapshot of page saved..." );	else	{		QApplication::beep();		app->slotStatusMsg( "Snapshot of page could not be saved..." );	}	}

⌨️ 快捷键说明

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