OpenCV开发SVM算法是基于LibSVM软件包开发的,LibSVM是台湾大学林智仁(Lin Chih-Jen)等开发设计的一个简单、易于使用和快速有效的SVM模式识别与回归的软件包。用OpenCV使用SVM算法的大概流程是

1)设置训练样本集

需要两组数据,一组是数据的类别,一组是数据的向量信息。

2)设置SVM参数

利用CvSVMParams类实现类内的成员变量svm_type表示SVM类型:

CvSVM::C_SVC  C-SVC

CvSVM::NU_SVC v-SVC

CvSVM::ONE_CLASS 一类SVM

CvSVM::EPS_SVR e-SVR

CvSVM::NU_SVR v-SVR

成员变量kernel_type表示核函数的类型:

CvSVM::LINEAR 线性:u‘v

CvSVM::POLY 多项式:(r*u'v + coef0)^degree

CvSVM::RBF RBF函数:exp(-r|u-v|^2)

CvSVM::SIGMOID sigmoid函数:tanh(r*u'v + coef0)

成员变量degree针对多项式核函数degree的设置,gamma针对多项式/rbf/sigmoid核函数的设置,coef0针对多项式/sigmoid核函数的设置,Cvalue为损失函数,在C-SVC、e-SVR、v-SVR中有效,nu设置v-SVC、一类SVM和v-SVR参数,p为设置e-SVR中损失函数的值,class_weightsC_SVC的权重,term_crit为SVM训练过程的终止条件。其中默认值degree = 0,gamma = 1,coef0 = 0,Cvalue = 1,nu = 0,p = 0,class_weights = 0

3)训练SVM

调用CvSVM::train函数建立SVM模型,第一个参数为训练数据,第二个参数为分类结果,最后一个参数即CvSVMParams

4)用这个SVM进行分类

调用函数CvSVM::predict实现分类

5)获得支持向量

除了分类,也可以得到SVM的支持向量,调用函数CvSVM::get_support_vector_count获得支持向量的个数,CvSVM::get_support_vector获得对应的索引编号的支持向量。

实现代码如下:运行步骤

[cpp] view plaincopyprint?
  1. // step 1:
  2. float labels[4] = {1.0, -1.0, -1.0, -1.0};
  3. Mat labelsMat(3, 1, CV_32FC1, labels);
  4. float trainingData[4][2] = { {501, 10}, {255, 10}, {501, 255}, {10, 501} };
  5. Mat trainingDataMat(3, 2, CV_32FC1, trainingData);
  6. // step 2:
  7. CvSVMParams params;
  8. params.svm_type = CvSVM::C_SVC;
  9. params.kernel_type = CvSVM::LINEAR;
  10. params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
  11. // step 3:
  12. CvSVM SVM;
  13. SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);
  14. // step 4:
  15. Vec3b green(0, 255, 0), blue(255, 0, 0);
  16. for (int i=0; i<image.rows; i++)
  17. {
  18. for (int j=0; j<image.cols; j++)
  19. {
  20. Mat sampleMat = (Mat_<float>(1,2) << i,j);
  21. float response = SVM.predict(sampleMat);
  22. if (fabs(response-1.0) < 0.0001)
  23. {
  24. image.at<Vec3b>(j, i) = green;
  25. }
  26. else if (fabs(response+1.0) < 0.001)
  27. {
  28. image.at<Vec3b>(j, i) = blue;
  29. }
  30. }
  31. }
  32. // step 5:
  33. int c = SVM.get_support_vector_count();
  34. for (int i=0; i<c; i++)
  35. {
  36. const float* v = SVM.get_support_vector(i);
  37. }

实验代码1:颜色分类

[cpp] view plaincopyprint?
  1. //利用SVM解决2维空间向量的3级分类问题
  2. #include "stdafx.h"
  3. #include "cv.h"
  4. #include "highgui.h"
  5. #include <ML.H>
  6. #include <TIME.H>
  7. #include <CTYPE.H>
  8. #include <IOSTREAM>
  9. using namespace std;
  10. int main(int argc, char **argv)
  11. {
  12. int size = 400;         //图像的长度和宽度
  13. const int s = 1000;          //试验点个数(可更改!!)
  14. int i, j, sv_num;
  15. IplImage *img;
  16. CvSVM svm = CvSVM();    //★★★
  17. CvSVMParams param;
  18. CvTermCriteria criteria;//停止迭代的标准
  19. CvRNG rng = cvRNG(time(NULL));
  20. CvPoint pts[s];         //定义1000个点
  21. float data[s*2];        //点的坐标
  22. int res[s];             //点的所属类
  23. CvMat data_mat, res_mat;
  24. CvScalar rcolor;
  25. const float *support;
  26. // (1)图像区域的确保和初始化
  27. img= cvCreateImage(cvSize(size, size), IPL_DEPTH_8U, 3);
  28. cvZero(img);
  29. //确保画像区域,并清0(用黑色作初始化处理)。
  30. // (2)学习数据的生成
  31. for (i= 0; i< s; i++) {
  32. pts[i].x= cvRandInt(&rng) % size;   //用随机整数赋值
  33. pts[i].y= cvRandInt(&rng) % size;
  34. if (pts[i].y> 50 * cos(pts[i].x* CV_PI/ 100) + 200) {
  35. cvLine(img, cvPoint(pts[i].x- 2, pts[i].y- 2), cvPoint(pts[i].x+ 2, pts[i].y+ 2), CV_RGB(255, 0, 0));
  36. cvLine(img, cvPoint(pts[i].x+ 2, pts[i].y- 2), cvPoint(pts[i].x- 2, pts[i].y+ 2), CV_RGB(255, 0, 0));
  37. res[i] = 1;
  38. }
  39. else {
  40. if (pts[i].x> 200) {
  41. cvLine(img, cvPoint(pts[i].x- 2, pts[i].y- 2), cvPoint(pts[i].x+ 2, pts[i].y+ 2), CV_RGB(0, 255, 0));
  42. cvLine(img, cvPoint(pts[i].x+ 2, pts[i].y- 2), cvPoint(pts[i].x- 2, pts[i].y+ 2), CV_RGB(0, 255, 0));
  43. res[i] = 2;
  44. }
  45. else {
  46. cvLine(img, cvPoint(pts[i].x- 2, pts[i].y- 2), cvPoint(pts[i].x+ 2, pts[i].y+ 2), CV_RGB(0, 0, 255));
  47. cvLine(img, cvPoint(pts[i].x+ 2, pts[i].y- 2), cvPoint(pts[i].x- 2, pts[i].y+ 2), CV_RGB(0, 0, 255));
  48. res[i] = 3;
  49. }
  50. }
  51. }
  52. //生成2维随机训练数据,并将其值放在CvPoint数据类型的数组pts[ ]中。
  53. // (3)学习数据的显示
  54. cvNamedWindow("SVM", CV_WINDOW_AUTOSIZE);
  55. cvShowImage("SVM", img);
  56. cvWaitKey(0);
  57. // (4)学习参数的生成
  58. for (i= 0; i< s; i++) {
  59. data[i* 2] = float (pts[i].x) / size;
  60. data[i* 2 + 1] = float (pts[i].y) / size;
  61. }
  62. cvInitMatHeader(&data_mat, s, 2, CV_32FC1, data);
  63. cvInitMatHeader(&res_mat, s, 1, CV_32SC1, res);
  64. criteria= cvTermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON);
  65. param= CvSVMParams (CvSVM::C_SVC, CvSVM::RBF, 10.0, 8.0, 1.0, 10.0, 0.5, 0.1, NULL, criteria);
  66. /*
  67. SVM种类:CvSVM::C_SVC
  68. Kernel的种类:CvSVM::RBF
  69. degree:10.0(此次不使用)
  70. gamma:8.0
  71. coef0:1.0(此次不使用)
  72. C:10.0
  73. nu:0.5(此次不使用)
  74. p:0.1(此次不使用)
  75. 然后对训练数据正规化处理,并放在CvMat型的数组里。
  76. */
  77. //☆☆☆☆☆☆☆☆☆(5)SVM学习☆☆☆☆☆☆☆☆☆☆☆☆
  78. svm.train(&data_mat, &res_mat, NULL, NULL, param);//☆
  79. //☆☆利用训练数据和确定的学习参数,进行SVM学习☆☆☆☆
  80. // (6)学习结果的绘图
  81. for (i= 0; i< size; i++) {
  82. for (j= 0; j< size; j++) {
  83. CvMat m;
  84. float ret = 0.0;
  85. float a[] = { float (j) / size, float (i) / size };
  86. cvInitMatHeader(&m, 1, 2, CV_32FC1, a);
  87. ret= svm.predict(&m);
  88. switch ((int) ret) {
  89. case 1:
  90. rcolor= CV_RGB(100, 0, 0);
  91. break;
  92. case 2:
  93. rcolor= CV_RGB(0, 100, 0);
  94. break;
  95. case 3:
  96. rcolor= CV_RGB(0, 0, 100);
  97. break;
  98. }
  99. cvSet2D(img, i, j, rcolor);
  100. }
  101. }
  102. //为了显示学习结果,通过输入图像区域的所有像素(特征向量)并进行分类。然后对输入像素用所属等级的颜色绘图。
  103. // (7)训练数据的再绘制
  104. for (i= 0; i< s; i++) {
  105. CvScalar rcolor;
  106. switch (res[i]) {
  107. case 1:
  108. rcolor= CV_RGB(255, 0, 0);
  109. break;
  110. case 2:
  111. rcolor= CV_RGB(0, 255, 0);
  112. break;
  113. case 3:
  114. rcolor= CV_RGB(0, 0, 255);
  115. break;
  116. }
  117. cvLine(img, cvPoint(pts[i].x- 2, pts[i].y- 2), cvPoint(pts[i].x+ 2, pts[i].y+ 2), rcolor);
  118. cvLine(img, cvPoint(pts[i].x+ 2, pts[i].y- 2), cvPoint(pts[i].x- 2, pts[i].y+ 2), rcolor);
  119. }
  120. //将训练数据在结果图像上重复的绘制出来。
  121. // (8)支持向量的绘制
  122. sv_num= svm.get_support_vector_count();
  123. for (i= 0; i< sv_num; i++) {
  124. support = svm.get_support_vector(i);
  125. cvCircle(img, cvPoint((int) (support[0] * size), (int) (support[1] * size)), 5, CV_RGB(200, 200, 200));
  126. }
  127. //用白色的圆圈对支持向量作标记。
  128. // (9)图像的显示
  129. cvNamedWindow("SVM", CV_WINDOW_AUTOSIZE);
  130. cvShowImage("SVM", img);
  131. cvWaitKey(0);
  132. cvDestroyWindow("SVM");
  133. cvReleaseImage(&img);
  134. return 0;
  135. //显示实际处理结果的图像,直到某个键被按下为止。
  136. }

实验代码2:用MIT人脸库检测,效果实在不好,检测结果全是人脸或者全都不是人脸。原因应该是图像检测没有做好应该用HoG等特征首先检测,在进行分类训练,不特征不明显,肯定分类效果并不好。

[cpp] view plaincopyprint?
  1. //
  2. // File Name: pjSVM.cpp
  3. // Author:   easyfov(easyfov@gmail.com)
  4. // Company: Lida Optical and Electronic Co.,Ltd.
  5. //http://apps.hi.baidu.com/share/detail/32719017
  6. //
  7. #include <cv.h>
  8. #include <highgui.h>
  9. #include <ml.h>
  10. #include <iostream>
  11. #include <fstream>
  12. #include <string>
  13. #include <vector>
  14. using namespace std;
  15. #define WIDTH 20
  16. #define HEIGHT 20
  17. int main( /*int argc, char** argv*/ )
  18. {
  19. vector<string> img_path;
  20. vector<int> img_catg;
  21. int nLine = 0;
  22. string buf;
  23. ifstream svm_data( "E:/SVM_DATA.txt" );
  24. while( svm_data )
  25. {
  26. if( getline( svm_data, buf ) )
  27. {
  28. nLine ++;
  29. if( nLine % 2 == 0 )
  30. {
  31. img_catg.push_back( atoi( buf.c_str() ) );//atoi将字符串转换成整型,标志(0,1)
  32. }
  33. else
  34. {
  35. img_path.push_back( buf );//图像路径
  36. }
  37. }
  38. }
  39. svm_data.close();//关闭文件
  40. CvMat *data_mat, *res_mat;
  41. int nImgNum = nLine / 2;            //读入样本数量
  42. 样本矩阵,nImgNum:横坐标是样本数量, WIDTH * HEIGHT:样本特征向量,即图像大小
  43. data_mat = cvCreateMat( nImgNum, WIDTH * HEIGHT, CV_32FC1 );
  44. cvSetZero( data_mat );
  45. //类型矩阵,存储每个样本的类型标志
  46. res_mat = cvCreateMat( nImgNum, 1, CV_32FC1 );
  47. cvSetZero( res_mat );
  48. IplImage *srcImg, *sampleImg;
  49. float b;
  50. DWORD n;
  51. for( string::size_type i = 0; i != img_path.size(); i++ )
  52. {
  53. srcImg = cvLoadImage( img_path[i].c_str(), CV_LOAD_IMAGE_GRAYSCALE );
  54. if( srcImg == NULL )
  55. {
  56. cout<<" can not load the image: "<<img_path[i].c_str()<<endl;
  57. continue;
  58. }
  59. cout<<" processing "<<img_path[i].c_str()<<endl;
  60. sampleImg = cvCreateImage( cvSize( WIDTH, HEIGHT ), IPL_DEPTH_8U, 1 );//样本大小(WIDTH, HEIGHT)
  61. cvResize( srcImg, sampleImg );//改变图像大小
  62. cvSmooth( sampleImg, sampleImg );    //降噪
  63. //生成训练数据
  64. n = 0;
  65. for( int ii = 0; ii < sampleImg->height; ii++ )
  66. {
  67. for( int jj = 0; jj < sampleImg->width; jj++, n++ )
  68. {
  69. b = (float)((int)((uchar)( sampleImg->imageData + sampleImg->widthStep * ii + jj )) / 255.0 );
  70. cvmSet( data_mat, (int)i, n, b );
  71. }
  72. }
  73. cvmSet( res_mat, i, 0, img_catg[i] );
  74. cout<<" end processing "<<img_path[i].c_str()<<" "<<img_catg[i]<<endl;
  75. }
  76. CvSVM svm = CvSVM();
  77. CvSVMParams param;
  78. CvTermCriteria criteria;
  79. criteria = cvTermCriteria( CV_TERMCRIT_EPS, 1000, FLT_EPSILON );
  80. param = CvSVMParams( CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.09, 1.0, 10.0, 0.5, 1.0, NULL, criteria );
  81. /*
  82. SVM种类:CvSVM::C_SVC
  83. Kernel的种类:CvSVM::RBF
  84. degree:10.0(此次不使用)
  85. gamma:8.0
  86. coef0:1.0(此次不使用)
  87. C:10.0
  88. nu:0.5(此次不使用)
  89. p:0.1(此次不使用)
  90. 然后对训练数据正规化处理,并放在CvMat型的数组里。
  91. */
  92. //☆☆☆☆☆☆☆☆☆(5)SVM学习☆☆☆☆☆☆☆☆☆☆☆☆
  93. svm.train( data_mat, res_mat, NULL, NULL, param );
  94. //☆☆利用训练数据和确定的学习参数,进行SVM学习☆☆☆☆
  95. svm.save( "SVM_DATA.xml" );
  96. //检测样本
  97. IplImage *tst, *tst_tmp;
  98. vector<string> img_tst_path;
  99. ifstream img_tst( "E:/SVM_TEST.txt" );
  100. while( img_tst )
  101. {
  102. if( getline( img_tst, buf ) )
  103. {
  104. img_tst_path.push_back( buf );
  105. }
  106. }
  107. img_tst.close();
  108. CvMat *tst_mat = cvCreateMat( 1, WIDTH*HEIGHT, CV_32FC1 );
  109. char line[512];
  110. ofstream predict_txt( "SVM_PREDICT.txt" );
  111. for( string::size_type j = 0; j != img_tst_path.size(); j++ )
  112. {
  113. tst = cvLoadImage( img_tst_path[j].c_str(), CV_LOAD_IMAGE_GRAYSCALE );
  114. if( tst == NULL )
  115. {
  116. cout<<" can not load the image: "<<img_tst_path[j].c_str()<<endl;
  117. continue;
  118. }
  119. tst_tmp = cvCreateImage( cvSize( WIDTH, HEIGHT ), IPL_DEPTH_8U, 1 );
  120. cvResize( tst, tst_tmp );
  121. cvSmooth( tst_tmp, tst_tmp );
  122. n = 0;
  123. for(int ii = 0; ii < tst_tmp->height; ii++ )
  124. {
  125. for(int jj = 0; jj < tst_tmp->width; jj++, n++ )
  126. {
  127. b = (float)(((int)((uchar)tst_tmp->imageData+tst_tmp->widthStep*ii+jj))/255.0);
  128. cvmSet( tst_mat, 0, n, (double)b );
  129. }
  130. }
  131. int ret = svm.predict( tst_mat );
  132. sprintf( line, "%s %d\r\n", img_tst_path[j].c_str(), ret );
  133. predict_txt<<line;
  134. }
  135. predict_txt.close();
  136. cvReleaseImage( &srcImg );
  137. cvReleaseImage( &sampleImg );
  138. cvReleaseImage( &tst );
  139. cvReleaseImage( &tst_tmp );
  140. cvReleaseMat( &data_mat );
  141. cvReleaseMat( &res_mat );
  142. return 0;
  143. }

其中

G:/program/pjSVM/face/1.png
0
G:/program/pjSVM/face/2.png
0
G:/program/pjSVM/face/3.png
0
G:/program/pjSVM/face/4.png
0
G:/program/pjSVM/face/5.png
0
G:/program/pjSVM/face/6.png
0
G:/program/pjSVM/face/7.png
0
G:/program/pjSVM/face/8.png
0
G:/program/pjSVM/face/9.png
0
G:/program/pjSVM/face/10.png
0
G:/program/pjSVM/face/11.png
0
G:/program/pjSVM/face/12.png
0
G:/program/pjSVM/face/13.png
0
G:/program/pjSVM/face/14.png
0
G:/program/pjSVM/face/15.png
1
G:/program/pjSVM/face/16.png
1
G:/program/pjSVM/face/17.png
1
G:/program/pjSVM/face/18.png
1
G:/program/pjSVM/face/19.png
1
G:/program/pjSVM/face/20.png
1
G:/program/pjSVM/face/21.png
1
G:/program/pjSVM/face/22.png
1
G:/program/pjSVM/face/23.png
1
G:/program/pjSVM/face/24.png
1
G:/program/pjSVM/face/25.png
1
G:/program/pjSVM/face/26.png
1
G:/program/pjSVM/face/27.png
1
G:/program/pjSVM/face/28.png
1
G:/program/pjSVM/face/29.png
1
G:/program/pjSVM/face/30.png

1

SVM_TEST.txt中内容如下:

G:/program/pjSVM/try_face/5.png
G:/program/pjSVM/try_face/9.png
G:/program/pjSVM/try_face/11.png
G:/program/pjSVM/try_face/15.png
G:/program/pjSVM/try_face/2.png
G:/program/pjSVM/try_face/30.png
G:/program/pjSVM/try_face/17.png
G:/program/pjSVM/try_face/21.png
G:/program/pjSVM/try_face/24.png
G:/program/pjSVM/try_face/27.png

PS:txt操作简单方式:http://blog.csdn.net/lytwell/article/details/6029503

学习OpenCV——SVM相关推荐

  1. 学习|OpenCV图片修复函数inpaint

    学更好的别人, 做更好的自己. --<微卡智享> 本文长度为2020字,预计阅读6分钟 OpenCV图片修复 最近重新学习OpenCV的基础,偶然间发现了npaint的函数,于是就自己做了 ...

  2. 跟着小琼琼学习opencv~

    楼楼最近整理笔记,发现了自己学习Opencv时候的码的代码和简单介绍,现贴上来~主调用方法在最下方.转载请注明出处~ #include <opencv2\xfeatures2d\nonfree. ...

  3. 快速系统从零学习OpenCV 4路线图

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 转眼间,小白学视觉就要成立三周年了,小白一直是很感谢小伙伴们的支持 ...

  4. 【从零学习OpenCV 4】4种读取Mat类元素的的方法

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门 ...

  5. 【从零学习OpenCV 4】Mat类构造与赋值

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门 ...

  6. 【从零学习OpenCV 4】Mat类介绍

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门 ...

  7. 【从零学习OpenCV 4】安装过程中问题解决方案

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门 ...

  8. 【从零学习OpenCV 4】了解OpenCV的模块架构

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门 ...

  9. 【从零学习OpenCV 4】Image Watch插件的使用

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门 ...

最新文章

  1. POJ 3617 Best Cow Line 贪心
  2. JavaScript最全的10种跨域共享的方法
  3. java重写的特性解释
  4. 实践 | 不同行业WMS选型策略及需要注意的一些问题
  5. 一分钟了解Android横竖屏 mdpi hdpi xhdpi xxhdpi xxxhdpi
  6. 彩虹浏览器使用技巧:页签自动切换
  7. linux 环境变量导出,关于Linux:如何删除导出的环境变量?
  8. 002 Servlet 第一个程序
  9. 关于qt中的tr( )函数
  10. Doris之Schema Change
  11. MyEclipse 保护色设置
  12. 代码 生成迅雷链接启动迅雷下载
  13. ftp服务器修改默认端口,FTP原理和修改FTP默认端口
  14. Spring Boot 面试的十个问题
  15. Python:实现scoring functions评分函数算法(附完整源码)
  16. R实现一次性合并多个数据框
  17. java 经纬度 电子围栏_电子围栏判断 java 版本
  18. 易读代码的艺术之Code Should Be Easy to Understand
  19. 如何将抓取下来的unicode字符串转换为中文
  20. 基于jsp+Java+mysql的酒店预订系统

热门文章

  1. android应用可以访问/dev下设备节点
  2. MTK 快速开机 技术详解
  3. auto drop ssh failed ip address
  4. AWS CSAA -- 04 AWS Object Storage and CDN - S3 Glacier and CloudFront(三)
  5. 赛门铁克公布Q3财报 亏损68亿美元
  6. Python按行输出文件内容具体解释及延伸
  7. 雷观(十六):帮人写项目,不如教会别人写项目的方法
  8. SQLServer导入Excel截断数据的解决办法
  9. linux 命令详解 十一
  10. PHP: to use scptask, you need to install the SSH extension.