上篇文章我们用的特征是训练样本的所有像素点值,虽然方便但不准确。

这篇文章主要介绍用SVM+HOG特征对数字进行识别。

详细请看上篇文章,它们主要区别在于训练样本HOG特征的提取,其他基本一样,所以我直接附上代码。

下面代码是opencv3和C++

可以根据自己需要修改训练样本类别,数目,尺寸。oss的训练样本路径,src的检测图片路径。
#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;//结合字符串和数字 int num = -1; Mat dealimage; Mat src; Mat
yangben_gray; Mat yangben_thresh; void feature(Mat dealimage);
////===============================读取训练数据===============================////
const int classsum = 10;//训练图片共有10类,可修改 const int imagesSum =
500;//每类有500张图片,可修改 int yangben_data_position = -1; Mat data_mat =
Mat(classsum*imagesSum, 8100, CV_32FC1);
//data_mat用来保存所有训练样本的HOG特征,每一列为一副图像的HOG特征 //每一行为每一幅训练图像 //必须为CV_32FC1的类型
//行、列、类型;第二个参数,即矩阵的列是由下面的descriptors的大小决定的,
//可以由descriptors.size()得到,且对于不同大小的输入训练图片,这个值是不同的 //descriptors为提取到的HOG特征 int
main() { //训练数据,每一行一个训练图片 Mat trainingData; //训练样本标签 Mat labels; //最终的训练样本标签
Mat clas; //最终的训练数据 Mat traindata;
//////////////////////从指定文件夹下提取图片////////////////// for (int p = 0; p <
classsum; p++)//依次提取0到9文件夹中的图片 { 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 < imagesSum; i++)//依次循环遍历每个文件夹中的图片 {
cvtColor(imread(input_images_name[i]), yangben_gray, COLOR_BGR2GRAY);//灰度变换
threshold(yangben_gray, yangben_thresh, 0, 255, THRESH_OTSU);//二值化
//循环读取每张图片并且依次放在vector<Mat> input_images内
input_images.push_back(yangben_thresh); dealimage = input_images[i];
//选择了HOG的方式完成特征提取工作 yangben_data_position += 1;//代表为第几幅图像
feature(dealimage);//图片特征提取 labels.push_back(label);//把每个图片对应的标签依次存入 cout <<
"第" << yangben_data_position << "样本正在提取HOG特征" << endl; } } cout <<
"样本特征提取完毕,等待创建SVM模型" << endl;
////===============================创建SVM模型===============================////
// 创建分类器并设置参数 Ptr<SVM> SVM_params = SVM::create();
SVM_params->setType(SVM::C_SVC);//C_SVC用于分类,C_SVR用于回归
SVM_params->setKernel(SVM::LINEAR); //LINEAR线性核函数。SIGMOID为高斯核函数
SVM_params->setDegree(0);//核函数中的参数degree,针对多项式核函数;
SVM_params->setGamma(1);//核函数中的参数gamma,针对多项式/RBF/SIGMOID核函数;
SVM_params->setCoef0(0);//核函数中的参数,针对多项式/SIGMOID核函数;
SVM_params->setC(1);//SVM最优问题参数,设置C-SVC,EPS_SVR和NU_SVR的参数;
SVM_params->setNu(0);//SVM最优问题参数,设置NU_SVC, ONE_CLASS 和NU_SVR的参数;
SVM_params->setP(0);//SVM最优问题参数,设置EPS_SVR 中损失函数p的值. //结束条件,即训练1000次或者误差小于0.01结束
SVM_params->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER +
TermCriteria::EPS, 1000, 0.01)); //训练数据和标签的结合 Ptr<TrainData> tData =
TrainData::create(data_mat, ROW_SAMPLE, labels); // 训练分类器
SVM_params->train(tData);//训练 //保存模型
SVM_params->save("C:/Users/zhang/Desktop/opencv——实例/小案例/车牌检测/基于机器学习/字符识别svm.xml");
cout << "训练好了!!!" << endl; cout << "等待识别" << endl;
////===============================预测部分===============================//// Mat
src =
imread("C:/Users/zhang/Desktop/opencv——实例/小案例/车牌检测/基于机器学习/检测到的车牌字符/字符7.jpg");
cvtColor(src, src, COLOR_BGR2GRAY); threshold(src, src, 0, 255,
CV_THRESH_OTSU); imshow("原图像", src); //输入图像取特征点 Mat trainTempImg =
Mat::zeros(Size(128, 128), CV_8UC1); resize(src, 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 << endl;
waitKey(0); return 0; } void feature(Mat dealimage) {
//把训练样本放大到128,128。便于HOG提取特征 Mat trainImg = Mat(Size(128, 128), CV_8UC1);
resize(dealimage, trainImg, trainImg.size()); //处理HOG特征
//检测窗口(64,128),块尺寸(16,16),块步长(8,8),cell尺寸(8,8),直方图bin个数9 ,需要修改 HOGDescriptor
*hog = new HOGDescriptor(Size(128, 128), Size(16, 16), Size(8, 8), Size(8, 8),
9); vector<float>descriptors;//存放结果 为HOG描述子向量 hog->compute(trainImg,
descriptors, Size(1, 1), Size(0, 0)); //Hog特征计算,检测窗口移动步长(1,1) //cout <<
"HOG描述子向量维数 : " << descriptors.size() << endl; for (vector<float>::size_type j
= 0; j < descriptors.size(); j++) { //把一幅图像的HOG描述子向量依次存入data_mat矩阵的同一列
data_mat.at<float>(yangben_data_position, j) = descriptors[j]; } }
 

识别结果:

技术
©2019-2020 Toolsou All rights reserved,
基于神经网络的车辆牌照字符识别技术Java基础(三) String深度解析 dedecms网站被黑 劫持到其他网站如何解决精准手机号抓取,运营商大数据利用梆梆加固逻辑漏洞取巧脱壳QT 删除目录及文件Java小明A+B苹果不送充填器耳机真为环保?可能还是为了赚钱吧在Pytorch上使用summaryC#中字典的排序方法