opencv学习笔记(七)SVM+HOG

一、简介

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

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

二、SVM+HOG进行车标识别

  批处理:

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

  1. dir /b > trainsamsFilenameDecribeTxt.txt
  2.  
  3. dir /b > testsamsFilenameDecribeTxt.txt

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

  

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

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

  首先是训练样本:

  1. bool ClogoRecognition::createTrainSamDescribeTxt()
  2. {
  3. string s;
  4. ifstream in(DEFAULT_TRAINSAMPLES_FILESNAME_TXT_DECRIBE_PATH);
  5. if (!in)
  6. return FALSE;
  7. ofstream out;
  8. out.open(DEFAULT_TRAINSAMPLES_TXT_DECRIBE_PATH, ios::trunc); //ios::trunc表示在打开文件前将文件清空,由于是写入,文件不存在则创建
  9. while (getline(in, s))//逐行读取数据并存于s中,直至数据全部读取
  10. {
  11. out <<DEFAULT_TRAINSAMPLES_PATH<< s.c_str() << '\n';//路径后面加上训练样本的filename
  12. int n = s.c_str()[] - '';//每个训练样本文件都以数字开头命令,数字即代表该文件的类别
  13. out << n << '\n';//每个样本的后面写入其类别,用于SVM训练时指定type
  14. }
  15. in.close();
  16. out.close();
  17. return TRUE;
  18. }

  

  运行结果:

  

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

  其次是测试样本:

  1. /*创建测试样本描述文件*/
  2. bool ClogoRecognition::createTestSamDescribeTxt()
  3. {
  4. string s;
  5. ifstream in(DEFAULT_TESTSAMPLES_FILESNAME_TXT_DESCRIBE_PATH);
  6. if (!in)
  7. return FALSE;
  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. return TRUE;
  17. }

  运行结果:

  

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

  SVM训练:

  1. bool ClogoRecognition::svmTrain()
  2. {
  3. vector<string> img_path;//图像路径容器
  4. vector<int> img_catg;//图像类别容器
  5. int nLine = ;
  6. string buf;
  7. ifstream svm_data(DEFAULT_TRAINSAMPLES_TXT_DECRIBE_PATH);//训练样本图片的路径都写在这个txt文件中,使用bat批处理文件可以得到这个txt文件
  8. if (!svm_data)
  9. return FALSE;
  10. unsigned long n;
  11. while (svm_data)//将训练样本文件依次读取进来
  12. {
  13. if (getline(svm_data, buf))
  14. {
  15. nLine++;
  16. if (nLine % == )//注:奇数行是图片全路径,偶数行是标签
  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 / ; //nImgNum是样本数量,只有文本行数的一半,另一半是标签
  29. data_mat = cvCreateMat(nImgNum, , CV_32FC1); //第二个参数,即矩阵的列是由下面的descriptors的大小决定的,可以由descriptors.size()得到,且对于不同大小的输入训练图片,这个值是不同的
  30. cvSetZero(data_mat);
  31. //类型矩阵,存储每个样本的类型标志
  32. res_mat = cvCreateMat(nImgNum, , CV_32FC1);
  33. cvSetZero(res_mat);
  34. IplImage* src;
  35. IplImage* trainImg = cvCreateImage(cvSize(, ), , );//需要分析的图片,这里车标的尺寸归一化至40*32,所以上面定义了432,如果要更改图片大小,可以先用debug查看一下descriptors是多少,然后设定好再运行
  36.  
  37. //处理HOG特征
  38. for (string::size_type i = ; i != img_path.size(); i++)
  39. {
  40. src = cvLoadImage(img_path[i].c_str(), );
  41. if (src == NULL)
  42. {
  43. cout << " can not load the image: " << img_path[i].c_str() << endl;
  44. continue;
  45. }
  46.  
  47. cout << " 处理: " << img_path[i].c_str() << endl;
  48.  
  49. cvResize(src, trainImg);
  50. HOGDescriptor *hog = new HOGDescriptor(cvSize(, ), cvSize(, ), cvSize(, ), cvSize(, ), );//图片尺寸:40*32;block尺寸:16*16;cell尺寸:8*8;检测窗口的滑动步长:8*8;一个单元格内统计9个方向的梯度直方图
  51. vector<float>descriptors;//存放结果
  52. hog->compute(trainImg, descriptors, Size(, ), Size(, )); //Hog特征计算
  53. cout << "HOG dims: " << descriptors.size() << endl;
  54. n = ;
  55. for (vector<float>::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, , img_catg[i]);
  61. cout << " 处理完毕: " << img_path[i].c_str() << " " << img_catg[i] << endl;
  62. }
  63.  
  64. // CvSVM svm = CvSVM();//新建一个SVM
  65. CvSVM svm;
  66. CvSVMParams param;//这里是SVM训练相关参数
  67. CvTermCriteria criteria;
  68. criteria = cvTermCriteria(CV_TERMCRIT_EPS, , FLT_EPSILON);
  69. param = CvSVMParams(CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.09, 1.0, 10.0, 0.5, 1.0, NULL, criteria);
  70. // param = CvSVMParams(CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.3, 1.0, 5, 0.5, 1.0, NULL, criteria);
  71. svm.train(data_mat, res_mat, NULL, NULL, param);//训练数据
  72. //保存训练好的分类器
  73. svm.save(DEFAULT_SVMMODEL_PATH);
  74. cvReleaseMat(&data_mat);
  75. cvReleaseMat(&res_mat);
  76. cvReleaseImage(&trainImg);
  77. return TRUE;
  78. }

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

  SVM测试:

  1. bool ClogoRecognition::svmTest()
  2. {
  3. string buf;
  4. CvSVM svm;
  5. svm.load(DEFAULT_SVMMODEL_PATH);//加载训练好的xml文件
  6. //检测样本
  7. IplImage *test;
  8. char result[];
  9. vector<string> img_tst_path;
  10. ifstream img_tst(DEFAULT_TESTSAMPLES_TXT_DECRIBE_PATH); //加载需要预测的图片集合,这个文本里存放的是图片全路径,不要标签
  11. if (!img_tst)
  12. return FALSE;
  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 = ; j != img_tst_path.size(); j++)//依次遍历所有的待检测图片
  24. {
  25. test = cvLoadImage(img_tst_path[j].c_str(), );
  26. if (test == NULL)
  27. {
  28. cout << " can not load the image: " << img_tst_path[j].c_str() << endl;
  29. continue;//结束本次循环
  30. }
  31. IplImage* trainTempImg = cvCreateImage(cvSize(, ), , );
  32. cvZero(trainTempImg);
  33. cvResize(test, trainTempImg);
  34. HOGDescriptor *hog = new HOGDescriptor(cvSize(, ), cvSize(, ), cvSize(, ), cvSize(, ), );
  35. vector<float>descriptors;//结果数组
  36. hog->compute(trainTempImg, descriptors, Size(, ), Size(, ));
  37. cout << "HOG dims: " << descriptors.size() << endl;
  38. CvMat* SVMtrainMat = cvCreateMat(, descriptors.size(), CV_32FC1);
  39. int n = ;
  40. for (vector<float>::iterator iter = descriptors.begin(); iter != descriptors.end(); iter++)
  41. {
  42. cvmSet(SVMtrainMat, , 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. return TRUE;
  53. }

  

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

  

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

  

  

  

  

opencv学习笔记(七)SVM+HOG的更多相关文章

  1. 【opencv学习笔记七】访问图像中的像素与图像亮度对比度调整

    今天我们来看一下如何访问图像的像素,以及如何改变图像的亮度与对比度. 在之前我们先来看一下图像矩阵数据的排列方式.我们以一个简单的矩阵来说明: 对单通道图像排列如下: 对于双通道图像排列如下: 那么对 ...

  2. opencv学习笔记(七)---图像金字塔

    图像金字塔指的是同一图像不同分辨率的子图的集合,有向下取样金字塔,向上取样金字塔,拉普拉斯金字塔....它是图像多尺度表达的一种,最主要的是用于图像的分割 向下取样金字塔指高分辨率图像向低分辨率图像的 ...

  3. OpenCV学习笔记七:opencv_nonfree模块

    一,简介: 顾名思义,这个模块不是free的.主要包含: 1,SIFT implementation. The class implements SIFT algorithm by D. Lowe. ...

  4. OpenCV 学习笔记 07 目标检测与识别

    目标检测与识别是计算机视觉中最常见的挑战之一.属于高级主题. 本章节将扩展目标检测的概念,首先探讨人脸识别技术,然后将该技术应用到显示生活中的各种目标检测. 1 目标检测与识别技术 为了与OpenCV ...

  5. opencv学习笔记(六)直方图比较图片相似度

    opencv学习笔记(六)直方图比较图片相似度 opencv提供了API来比较图片的相似程度,使我们很简单的就能对2个图片进行比较,这就是直方图的比较,直方图英文是histogram, 原理就是就是将 ...

  6. opencv学习笔记(五)镜像对称

    opencv学习笔记(五)镜像对称 设图像的宽度为width,长度为height.(x,y)为变换后的坐标,(x0,y0)为原图像的坐标. 水平镜像变换: 代码实现: #include <ios ...

  7. opencv学习笔记(四)投影

    opencv学习笔记(四)投影 任选了一张图片用于测试,图片如下所示: #include <cv.h> #include <highgui.h> using namespace ...

  8. opencv学习笔记(三)基本数据类型

    opencv学习笔记(三)基本数据类型 类:DataType 将C++数据类型转换为对应的opencv数据类型 OpenCV原始数据类型的特征模版.OpenCV的原始数据类型包括unsigned ch ...

  9. opencv学习笔记(二)寻找轮廓

    opencv学习笔记(二)寻找轮廓 opencv中使用findContours函数来查找轮廓,这个函数的原型为: void findContours(InputOutputArray image, O ...

随机推荐

  1. DHCP协议格式、DHCP服务搭建、DHCP协商交互过程入门学习

    相关学习资料 http://www.rfc-editor.org/rfc/rfc2131.txt http://baike.baidu.com/view/7992.htm?fromtitle=DHCP ...

  2. rockmongo用法

    .简单查询 //xid=560870 and type=video { , "type": "video" } //查询数组中的数据 array( " ...

  3. Fast-cgi cgi nginx php-fpm 的关系 (转

    Fast-cgi  cgi  nginx  PHP-fpm 的关系 Fast-cgi是由cgi发展而来,是http服务器(http,nginx等)和动态脚本语言(php,perl等)之间的的通信接口, ...

  4. 使用log4net连接Mysql数据库配置

    log4net配置: //Author:GaoBingBing [assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net ...

  5. web.config 加密/解密

    (Aspnet_regiis.exe) 这样的一个工具,可以对站点的.config文件的节进行加密 方法: #> 加密:aspnet_regiis -pef "加密的web.confi ...

  6. ngrok反向代理

    关于ngrok ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道.ngrok 可捕获和分析所有通道上的流量,便于后期分析和重放. 为什么使用ngrok? ...

  7. javascript常量

    javascript中没有常量的概念,虽然许多现代的变成环境可能为您提供了用以创建常量的const语句.对于的自己的变量,可以采用相同的命名约定,并且将他们以静态属性的方式添加到构造函数中. //构造 ...

  8. iOS上传应用过程中出现的错误"images contain alpha channels or transparencies"以及解决方案

    如何取消图片透明度  本文永久地址为 http://www.cnblogs.com/ChenYilong/p/3989954.html,转载请注明出处. 当你试图通过<预览>进行" ...

  9. 调用{dede:likewords}为dedecms添加相关搜索词

    经常看到一些大型的网站会设置相关搜索,即使访客搜索的内容在本站暂时没有,它们也会展示一些其他搜索关键词,引导用户去点击查看,增加pv,提高用户体验:如果没有这些相关搜索,游客没有找到自己想要的内容就直 ...

  10. Asteroids(匈牙利算法入门)

    Asteroids Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16211   Accepted: 8819 Descri ...