opencv hog svm java_opencv学习笔记(七)SVM+HOG

本文介绍了使用OpenCV的HOG特征和SVM分类器进行车标识别的过程,包括如何创建训练和测试样本的描述文件,以及SVM的训练和测试步骤。通过批处理命令获取样本文件名,利用C++代码处理样本路径和标签,最后训练SVM模型并进行预测。
摘要由CSDN通过智能技术生成

opencv学习笔记(七)SVM+HOG

一、简介

方向梯度直方图(Histogram of Oriented Gradient,HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子。它通过计算和统计图像局部区域的梯度直方图来构成特征。Hog特征结合SVM分类器已经被广泛用于图像识别中,尤其在行人检测中获得了极大的成功。需要提醒的是,HOG+SVM进行行人检测的方法是法国研究院Dalal在2005的CVPR上提出的。

最近在做车标识别相关的研究,用到了SVM+HOG的方法进行识别,下面的例子,使用的数据样本是6类车标:本田、大众、丰田、现代、马自达和雪铁龙。

二、SVM+HOG进行车标识别

批处理:

首先在训练样本和测试样本的文件夹下,使用dos批处理命令:

dir /b >trainsamsFilenameDecribeTxt.txt

dir/b > testsamsFilenameDecribeTxt.txt

得到训练样本和测试样本的文件名列表,如下所示:

7cf67713d7486a8b23afc82998114448.png

注意将最后一行的“trainsamsFilenameDecribeTxt.txt”删掉。

然后需要将训练样本和测试样本文件夹所在的路径加到上述文件名列表的前面,形成样本的完整路径。我使用如下代码帮助我完成,

首先是训练样本:

1 boolClogoRecognition::createTrainSamDescribeTxt()2 {3 strings;4 ifstream in(DEFAULT_TRAINSAMPLES_FILESNAME_TXT_DECRIBE_PATH);5 if (!in)6 returnFALSE;7 ofstream out;8 out.open(DEFAULT_TRAINSAMPLES_TXT_DECRIBE_PATH, ios::trunc); //ios::trunc表示在打开文件前将文件清空,由于是写入,文件不存在则创建

9 while (getline(in, s))//逐行读取数据并存于s中,直至数据全部读取

10 {11 out <

12 int n = s.c_str()[0] - '0';//每个训练样本文件都以数字开头命令,数字即代表该文件的类别

13 out << n << '\n';//每个样本的后面写入其类别,用于SVM训练时指定type

14 }15 in.close();16 out.close();17 returnTRUE;18 }

运行结果:

8bdea419706ba71f611906ed68ad25f8.png

对于训练样本,路径之后紧接着该文件对应的标签类别。便于之后的训练步骤。

其次是测试样本:

1 /*创建测试样本描述文件*/

2 boolClogoRecognition::createTestSamDescribeTxt()3 {4 strings;5 ifstream in(DEFAULT_TESTSAMPLES_FILESNAME_TXT_DESCRIBE_PATH);6 if (!in)7 returnFALSE;8 ofstream out;9 out.open(DEFAULT_TESTSAMPLES_TXT_DECRIBE_PATH, ios::trunc); //ios::trunc表示在打开文件前将文件清空,由于是写入,文件不存在则创建

10 while (getline(in, s))//逐行读取数据并存于s中,直至数据全部读取

11 {12 out << DEFAULT_TESTSAMPLES_PATH << s.c_str() << '\n';//路径后面加上测试样本的filename

13 }14 in.close();15 out.close();16 returnTRUE;17 }

运行结果:

12b21171d8e41baa758879083e6f1f73.png

样本图片和数量,第一行从左往右依次为:本田、大众、丰田;第二行从左往右一次为:现代、马自达、雪铁龙;

66621df3e65eb95de297405497d41d4c.png

SVM训练:

1 boolClogoRecognition::svmTrain()2 {3 vector img_path;//图像路径容器

4 vector img_catg;//图像类别容器

5 int nLine = 0;6 stringbuf;7 ifstream svm_data(DEFAULT_TRAINSAMPLES_TXT_DECRIBE_PATH);//训练样本图片的路径都写在这个txt文件中,使用bat批处理文件可以得到这个txt文件

8 if (!svm_data)9 returnFALSE;10 unsigned longn;11 while (svm_data)//将训练样本文件依次读取进来

12 {13 if(getline(svm_data, buf))14 {15 nLine++;16 if (nLine % 2 == 0)//注:奇数行是图片全路径,偶数行是标签

17 {18 img_catg.push_back(atoi(buf.c_str()));//atoi将字符串转换成整型,标志(0,1,2,...,9),注意这里至少要有两个类别,否则会出错

19 }20 else

21 {22 img_path.push_back(buf);//图像路径

23 }24 }25 }26 svm_data.close();//关闭文件

27 CvMat *data_mat, *res_mat;28 int nImgNum = nLine / 2; //nImgNum是样本数量,只有文本行数的一半,另一半是标签

29 data_mat = cvCreateMat(nImgNum, 432, CV_32FC1); //第二个参数,即矩阵的列是由下面的descriptors的大小决定的,可以由descriptors.size()得到,且对于不同大小的输入训练图片,这个值是不同的

30 cvSetZero(data_mat);31 //类型矩阵,存储每个样本的类型标志

32 res_mat = cvCreateMat(nImgNum, 1, CV_32FC1);33 cvSetZero(res_mat);34 IplImage*src;35 IplImage* trainImg = cvCreateImage(cvSize(40, 32), 8, 3);//需要分析的图片,这里车标的尺寸归一化至40*32,所以上面定义了432,如果要更改图片大小,可以先用debug查看一下descriptors是多少,然后设定好再运行36

37 //处理HOG特征

38 for (string::size_type i = 0; i != img_path.size(); i++)39 {40 src = cvLoadImage(img_path[i].c_str(), 1);41 if (src ==NULL)42 {43 cout << "can not load the image:" << img_path[i].c_str() <

47 cout << "处理:" << img_path[i].c_str() <

49 cvResize(src, trainImg);50 HOGDescriptor *hog = new HOGDescriptor(cvSize(40, 32), cvSize(16, 16), cvSize(8, 8), cvSize(8, 8), 9);//图片尺寸:40*32;block尺寸:16*16;cell尺寸:8*8;检测窗口的滑动步长:8*8;一个单元格内统计9个方向的梯度直方图

51 vectordescriptors;//存放结果

52 hog->compute(trainImg, descriptors, Size(1, 1), Size(0, 0)); //Hog特征计算

53 cout << "HOG dims:" << descriptors.size() <::iterator iter = descriptors.begin(); iter != descriptors.end(); iter++)56 {57 cvmSet(data_mat, i, n, *iter);//存储HOG特征

58 n++;59 }60 cvmSet(res_mat, i, 0, img_catg[i]);61 cout << "处理完毕:" << img_path[i].c_str() << " " << img_catg[i] <

64

65 //CvSVM svm = CvSVM();//新建一个SVM

66 CvSVM svm;67 CvSVMParams param;//这里是SVM训练相关参数

68 CvTermCriteria criteria;69 criteria = cvTermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON);70 param = CvSVMParams(CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.09, 1.0, 10.0, 0.5, 1.0, NULL, criteria);71 //param = CvSVMParams(CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.3, 1.0, 5, 0.5, 1.0, NULL, criteria);

72 svm.train(data_mat, res_mat, NULL, NULL, param);//训练数据73 //保存训练好的分类器

74 svm.save(DEFAULT_SVMMODEL_PATH);75 cvReleaseMat(&data_mat);76 cvReleaseMat(&res_mat);77 cvReleaseImage(&trainImg);78 returnTRUE;79 }

等待几分钟即可得到训练好的xml模型;

SVM测试:

1 boolClogoRecognition::svmTest()2 {3 stringbuf;4 CvSVM svm;5 svm.load(DEFAULT_SVMMODEL_PATH);//加载训练好的xml文件6 //检测样本

7 IplImage *test;8 char result[512];9 vectorimg_tst_path;10 ifstream img_tst(DEFAULT_TESTSAMPLES_TXT_DECRIBE_PATH); //加载需要预测的图片集合,这个文本里存放的是图片全路径,不要标签

11 if (!img_tst)12 returnFALSE;13 while(img_tst)14 {15 if(getline(img_tst, buf))16 {17 img_tst_path.push_back(buf);18 }19 }20 img_tst.close();21

22 ofstream predict_txt(DEFAULT_TESTSAMPLES_RECOGNITION_RESULT_TXT_DECRIBE_PATH);//把预测结果存储在这个文本中

23 for (string::size_type j = 0; j != img_tst_path.size(); j++)//依次遍历所有的待检测图片

24 {25 test = cvLoadImage(img_tst_path[j].c_str(), 1);26 if (test ==NULL)27 {28 cout << "can not load the image:" << img_tst_path[j].c_str() <

30 }31 IplImage* trainTempImg = cvCreateImage(cvSize(40, 32), 8, 3);32 cvZero(trainTempImg);33 cvResize(test, trainTempImg);34 HOGDescriptor *hog = new HOGDescriptor(cvSize(40, 32), cvSize(16, 16), cvSize(8, 8), cvSize(8, 8), 9);35 vectordescriptors;//结果数组

36 hog->compute(trainTempImg, descriptors, Size(1, 1), Size(0, 0));37 cout << "HOG dims:" << descriptors.size() <::iterator iter = descriptors.begin(); iter != descriptors.end(); iter++)41 {42 cvmSet(SVMtrainMat, 0, n, *iter);43 n++;44 }45

46 int ret = svm.predict(SVMtrainMat);//检测结果

47 sprintf(result, "%s %d\r\n", img_tst_path[j].c_str(), ret);48 predict_txt << result; //输出检测结果到文本

49 }50 predict_txt.close();51 cvReleaseImage(&test);52 returnTRUE;53 }

运行SVM测试代码后,运行结果写入指定的txt中,每一行的最后一个数字代表该行路径下的图片的识别结果。如下图所示:

51cf20feeab92deced68a2c5624d5e02.png

95e7a169ee2edcc7ed2aab5ea5871de4.png

10d071513c6f2690f9306d099da19263.png

1fc40a28a43f7d5bf465f5e3a737dad9.png

1fafef1adff43ad54f34b320cbd9c1b7.png

9bfabe82e3dc2ada17cada58893e45de.png

图片文件名中第一个数字代表其类别,当和该行中最后一个数字一致时,说明识别正确,否则识别错误。由图中可以看到,识别结果还是挺不错的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值