前两篇文章写了基于两种特征提取的SVM数字识别
https://blog.****.net/weixin_41721222/article/details/84953788
https://blog.****.net/weixin_41721222/article/details/84978343
这篇文章主要是关于模型评估,即识别数字的正确率
下面代码是opencv3 c++
加载的XML文件是之前代码训练好的。
测试集是我的“”数字检测样本“”文件夹下的0-9个文件夹所包含的检测样本
#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;
}
结果:
正确率为百分之67,不高主要是因为训练集用的是手写数字。而测试集用的是车牌数字。