opencv——基于SVM的数字识别(3)

时间:2024-04-14 08:26:30

前两篇文章写了基于两种特征提取的SVM数字识别

https://blog.****.net/weixin_41721222/article/details/84953788

https://blog.****.net/weixin_41721222/article/details/84978343

这篇文章主要是关于模型评估,即识别数字的正确率

 

下面代码是opencv3  c++

加载的XML文件是之前代码训练好的。

测试集是我的“”数字检测样本“”文件夹下的0-9个文件夹所包含的检测样本

opencv——基于SVM的数字识别(3)

opencv——基于SVM的数字识别(3)

 

 


#include <stdio.h>  
#include <time.h>  
#include <opencv2/opencv.hpp>  
#include <opencv/cv.h>  
#include <iostream> 
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/ml/ml.hpp>  
#include <io.h> //查找文件相关函数


using namespace std;
using namespace cv;
using namespace ml;
ostringstream oss;
Mat dealimage;
int num = -1;
Mat yangben_gray;
Mat yangben_thresh;
void shibie(Mat dealimage);
int yangben_data_position = 0;//代表为第几幅图像
int right_lei = -1;//让后面评估模型判断是否分类正确
int rigth_number = 0;//分类正确的个数
int test_num = 0;//累计总共的测试图像个数
Ptr<SVM>SVM_params;
int main()
{
	//加载XML文件
	SVM_params = SVM::load("C:/Users/zhang/Desktop/opencv——实例/小案例/车牌检测/基于机器学习/字符识别svm.xml");
	const int classsum = 10;//图片共有10类
	//////////////////////从指定文件夹下提取图片//////////////////
	for (int p = 0; p < classsum; p++)
	{
		right_lei += 1;//让后面评估模型判断是否分类正确
		oss << "C:/Users/zhang/Desktop/opencv——实例/机器学习/数字检测样本/";
		num += 1;//num从0到9
		int label = num;
		oss << num << "/*.jpg";//图片名字后缀,oss可以结合数字与字符串
		string pattern = oss.str();//oss.str()输出oss字符串,并且赋给pattern
		oss.str("");//每次循环后把oss字符串清空
		vector<Mat> input_images;
		vector<String> input_images_name;
		glob(pattern, input_images_name, false);
		//为false时,仅仅遍历指定文件夹内符合模式的文件,当为true时,会同时遍历指定文件夹的子文件夹
		//此时input_images_name存放符合条件的图片地址
		int all_num = input_images_name.size();//文件下总共有几个图片
		//cout << num << ":总共有" << all_num << "个图片待测试" << endl;

		for (int i = 0; i < all_num; i++)
		{
			cvtColor(imread(input_images_name[i]), yangben_gray, COLOR_BGR2GRAY);
			threshold(yangben_gray, yangben_thresh, 0, 255, THRESH_OTSU);
			input_images.push_back(yangben_thresh);
			//循环读取每张图片并且依次放在vector<Mat> input_images内
			dealimage = input_images[i];
			yangben_data_position += 1;//代表为第几幅图像
			test_num += 1;//累计总共的测试图像
			cout << "正在识别第" << yangben_data_position << "张图片" << endl;
			shibie(dealimage);
	
		}
	}

	//模型评估//
	cout << "正确个数"<<rigth_number << endl <<"总检测个数"<< test_num << endl;
	double right_rate = double(rigth_number) / double(test_num);
	cout << "正确率为:" << right_rate << endl;


	waitKey(0);
	return 0;
}
void shibie(Mat dealimage)
{
	//imshow("原图像", gray);
	//输入图像取特征点
	Mat trainTempImg = Mat::zeros(Size(128, 128), CV_8UC1);
	resize(dealimage, trainTempImg, trainTempImg.size());

	HOGDescriptor *hog = new HOGDescriptor(Size(128, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9);
	vector<float>descriptors;//结果数组         
	hog->compute(trainTempImg, descriptors, Size(1, 1), Size(0, 0));
	//cout << "HOG描述子向量维数    " << descriptors.size() << endl;
	Mat SVMtrainMat = Mat(1, descriptors.size(), CV_32FC1);

	int  number1 = descriptors.size();
	//将计算好的HOG描述子复制到样本特征矩阵SVMtrainMat  
	for (int i = 0; i < number1; i++)
	{
		//把一幅图像的HOG描述子向量依次存入data_mat矩阵的同一列
		//因为输入图像只有一个,即SVMtrainMat只有一列,则为0
		SVMtrainMat.at<float>(0, i) = descriptors[i];  									  //  n++;
	}

	SVMtrainMat.convertTo(SVMtrainMat, CV_32FC1);//更改图片数据的类型,必要,不然会出错
	int ret = (int)SVM_params->predict(SVMtrainMat);//检测结果  
	cout << "识别的数字为:" << ret << "\t";

	if (right_lei == ret)
	{
		cout << "识别正确" << endl;
		rigth_number+=1;
	}
	if (right_lei != ret)
		cout << "识别错误" << "\t" << "正确值为:" << right_lei << endl;
}

 

 

结果:

opencv——基于SVM的数字识别(3)

opencv——基于SVM的数字识别(3)

 

正确率为百分之67,不高主要是因为训练集用的是手写数字。而测试集用的是车牌数字。