基于Qt5.8+Opencv3.0的简单手写数字识别界面

配置:WIN7下Qt5.8+VS2013+Opencv3.0

基于Qt5.8的简单手写数字识别界面是在 Opencv3.0 手写数字识别(Hog特征+SVM分类器)的基础上利用Qt5.8编写的一个简单界面。

在该界面中可以通过鼠标手写输入数字进行识别,该界面直接使用 Opencv3.0 手写数字识别(Hog特征+SVM分类器)训练得到的Xml文件进行手写数字识别,由于训练样本的量较少,识别效果不是很理想,但可以作为编写手写数字识别界面的参考。具体过程如下:

1.UI界面的设计

直接新建一个Qt Application项目,并利用Qt Designer进行界面设计,最终效果如下:

基于Qt5.8+Opencv3.0的简单手写数字识别界面_第1张图片

各Label及按钮的名称如下:

    QPushButton *ClearButton;
    QPushButton *TestButton;
    QPushButton *SaveButton;
    QLabel *testResultlabel;
    QLabel *loadImagelabel;
    QLabel *loadXmllabel;

2.手写数字识别界面的头文件编写

头文件主要进行了相关数据成员、成员函数的声明,程序如下。

#ifndef DOODLE_WIDGET_H
#define DOODLE_WIDGET_H

#include 
#include "ui_doodle_widget.h"
#include   
#include   
#include   

class Doodle_widget : public QWidget
{
	Q_OBJECT

public:
	Doodle_widget(QWidget *parent = 0);


protected:
	void paintEvent(QPaintEvent *);//重绘事件(重点:由update()函数触发)
	void mousePressEvent(QMouseEvent *);//鼠标按下事件  
	void mouseMoveEvent(QMouseEvent *);//鼠标移动事件(重点理解)  
	void mouseReleaseEvent(QMouseEvent *);//鼠标释放事件  

	void paint(QImage &theImage);//画图工具

private slots:
	void savetheImage();
	void test();
	void clearPaint();


private:  
	Ui::Doodle_widgetClass ui;

	QImage image;//一块画布
	
	QRgb backColor;//画布背景色  
	QPoint lastPoint;//前一个点,因为线是由无数点组成的  
	QPoint endPoint;//后一个点(结束点)  
	bool isDrawing;//判断是否在绘图也就是判断鼠标是否操作
};

#endif // DOODLE_WIDGET_H


3.手写数字识别界面的CPP文件编写

头文件主要进行了相关相关函数的定义,程序如下。

#include "doodle_widget.h"
#include   
#include  
#include 

#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
using namespace cv;
using namespace cv::ml;

Doodle_widget::Doodle_widget(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);

	isDrawing = false;
	image = QImage(128, 128, QImage::Format_RGB32);
	backColor = qRgb(0, 0, 0);
	image.fill(backColor);

	ui.loadXmllabel->setText("Waitting...");
	ui.loadImagelabel->setText("Waitting...");
	ui.testResultlabel->setText("Waitting...");


	connect(ui.SaveButton, SIGNAL(clicked()), this, SLOT(savetheImage()));
	connect(ui.TestButton, SIGNAL(clicked()), this, SLOT(test()));
	connect(ui.ClearButton, SIGNAL(clicked()), this, SLOT(clearPaint()));

}

void Doodle_widget::paintEvent(QPaintEvent *)
{//可理解为是一个绘图终端函数,在本程序中只通过update()触发,调用结束后  
	//这也是一个状态函数,只要没关闭mainwindow,一直待机等待update()触发  

	QPainter painter(this);//QPainter是绘图操作,父亲是paintwidget类而paintwidget的父亲又是mainwindow  
	//既关闭mainwindow就关闭paintwidget就关闭了painter  

	painter.drawImage(0, 0, image);//把图画在image上  
}

void Doodle_widget::mousePressEvent(QMouseEvent *event){
	if (event->button() == Qt::LeftButton){//-------------------------鼠标按下且为左键  
		lastPoint = event->pos();//----------------------------------设置起点为鼠标按下的点  
		endPoint = event->pos();//-----------------------------------设置终点为鼠标按下的点  
		isDrawing = true;//------------------------------------------开始绘图了  
	}
}

void Doodle_widget::mouseMoveEvent(QMouseEvent *event){ //重点理解部分  

	if (event->buttons() & Qt::LeftButton){//-------------------------鼠标按下左键并移动  
		endPoint = event->pos();//-----------------------------------鼠标每移动一次都刷新终点  

		paint(image);        //--------------理解清楚这个函数--------仔细看看void paint (QImage &theImage)函数  
		//---------------------------------------最后会通过update()函数调用void paintEvent(QPaintEvent *)重绘函数  
		//---------------------------------------再仔细看看void paintEvent(QPaintEvent *)重绘函数会把图画在image画布上  
		//---------------------------------------我觉得理解了这个就理解得差不多了  
	}
}
void Doodle_widget::mouseReleaseEvent(QMouseEvent *event){
	isDrawing = false;//--------------------------------------------绘图完毕  
	paint(image);//--------------------------------------------------把最后一点画在image画布上,可参考上面注释  
}


void Doodle_widget::paint(QImage &theImage){//------------------(画图函数)调用这个函数就是调用重绘函数,把图画在image上  
	QPainter p(&theImage); //------------------------------------把图画在theImage(theImage是painterDevice类型参数,由于是引用,其实就是画在image上)  
	QPen apen;
	apen.setWidth(5);//------------------------------------------画笔线条宽度设置为5 
	apen.setColor(Qt::white);
	p.setPen(apen);//--------------------------------------------设置画笔线条宽度,也可以不设置,既把这两句注释掉,线条默认宽度为1  
	p.drawLine(lastPoint, endPoint);//----------------------------画线,由于鼠标移动事件会调用此函数,因此lastPoint和endPoint相距近似为0  
	//---------------------------因此可近似看成画点,点连起来就是画笔的痕迹了  

	lastPoint = endPoint;//--------------------------------------把终点复制给起点  
	update();//--------------------------------------------------刷新  
}

void Doodle_widget::savetheImage()
{
	QString path = QString("%1/demo.png").arg(QApplication::applicationDirPath());
	image.save(path);
	ui.loadXmllabel->setText("Save done...");
	//if (!(image.save(path)))
	//{
	//	QMessageBox::warning(this, tr("Warning"), tr("Save failed !"));
	//}
	//else 
	//{
	//	QMessageBox::warning(this, tr("Notice"), tr("Save OK !"));
	//}

	//ui.SaveButton->setText("success");
}

void Doodle_widget::test()
{
	//creat SVM classfier
	Ptr svm = SVM::create();
	//load train file
	svm = SVM::load("SVM_HOG.xml");

	if (!svm)
	{
		ui.loadXmllabel->setText("load file faile...");
	}

	Mat test;
	test = imread("Win32/Debug/demo.png");
	//imshow("image", test);
	ui.loadImagelabel->setText("succcess");

	//winsize(64,128),blocksize(16,16),blockstep(8,8),cellsize(8,8),bins9
	//检测窗口(64,128),块尺寸(16,16),块步长(8,8),cell尺寸(8,8),直方图bin个数9
	HOGDescriptor hog(Size(128, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9);

	vector descriptors;//HOG描述子向量
	hog.compute(test, descriptors, Size(8, 8));//计算HOG描述子,检测窗口移动步长(8,8)
	int r = svm->predict(descriptors);   //对所有行进行预测
	
	ui.testResultlabel->setText("The number is " + QString::number(r) + ".");
	//ui.TestButton->setText("success");
}

void Doodle_widget::clearPaint()
{
	image = QImage(128, 128, QImage::Format_RGB32);
	backColor = qRgb(0, 0, 0);
	image.fill(backColor);
	ui.loadXmllabel->setText("Waitting...");
	ui.loadImagelabel->setText("Waitting...");
	ui.testResultlabel->setText("Waitting...");
	update();
}
main.cpp文件默认就行,程序如下。

#include "doodle_widget.h"
#include 

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	Doodle_widget w;
	w.show();
	return a.exec();
}

源程序下载

程序运行效果如下(先Save,再Test,Clear后可再次手写测试):

基于Qt5.8+Opencv3.0的简单手写数字识别界面_第2张图片
源程序下载:

基于Qt5.8+Opencv3.0的简单手写数字识别界面:

http://download.csdn.net/download/almost_miao/10218495






你可能感兴趣的:(基于Qt5.8+Opencv3.0的简单手写数字识别界面)