学习OpenCV——SVM

学习SVM,首先通过http://zh.wikipedia.org/wiki/SVM

再通过博客http://blog.csdn.net/yang_xian521/article/details/6969904

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获得对应的索引编号的支持向量。

实现代码如下:运行步骤

  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:颜色分类

  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等特征首先检测,在进行分类训练,不特征不明显,肯定分类效果并不好。

  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——SVM 手写数字检测

    转自http://blog.csdn.net/firefight/article/details/6452188 是MNIST手写数字图片库:http://code.google.com/p/supp ...

  2. 学习opencv之路(一)

    先看一下<学习opencv> 找几个demo 学会相机标定 我做的是单目相机的标定.

  3. [纯小白学习OpenCV系列]官方例程00:世界观与方法论

    2015-11-11 ----------------------------------------------------------------------------------- 其实,写博 ...

  4. 《学习OpenCV》中求给定点位置公式

    假设有10个三维的点,使用数组存放它们有四种常见的形式: ①一个二维数组,数组的类型是CV32FC1,有n行,3列(n×3) ②类似①,也可以用一个3行n列(3×n)的二维数组 ③④用一个n行1列(n ...

  5. 对人脑处理视觉的描述(摘《学习OpenCV(中文版)》)

    人脑将视觉信号划分入很多个通道,将各种不同的信息输入你的大脑.你的大脑有一个关注系统,会根据任务识别出图像的重要部分,并做重点分析,而其他部分则分析得较少 .在人类视觉流中存在大量的反馈,但是目前我们 ...

  6. 《学习OpenCV》练习题第五章第二题abc

    代码: #include <stdio.h> #include <opencv/highgui.h> #include <opencv/cv.h> #include ...

  7. 《学习OpenCV》练习题第五章第一题ab

    这道题是载入一幅带有有趣纹理的图像并用不同的模板(窗口,核)大小做高斯模糊(高斯平滑),然后比较用5*5大小的窗口平滑图像两次和用11*11大小的窗口平滑图像一次是否接近相同. 先说下我的做法,a部分 ...

  8. 《学习OpenCV》练习题第四章第八题ab

    这道题是利用OpenCV例子程序里自带的人脸检测程序,做点图像的复制操作以及alpha融合. 说明:人脸检测的程序我参照了网上现有的例子程序,没有用我用的OpenCV版本(2.4.5)的facedet ...

  9. 《学习OpenCV》练习题第四章第三题b

    #include <highgui.h> #include <cv.h> #include "opencv_libs.h" /* *<学习OpenCV ...

随机推荐

  1. 使用 PowerShell 创建 Linux 虚拟机

    Azure PowerShell 模块用于从 PowerShell 命令行或脚本创建和管理 Azure 资源. 本指南详细介绍了如何使用 Azure PowerShell 模块部署运行 Ubuntu ...

  2. [EXCEL] 不能清除剪贴板: We couldn't free up space on the clipboard. Another program might be using it right now

    Excel复制粘贴时出现以下错误,原因是有程序占用了剪切板. We couldn't free up space on the clipboard. Another program might be ...

  3. RTCM32编解码中的一些概念及相关文献阅读

    1. IODC和 IODE ——  导航电文相关.iode/iodc是在GPS系统的ICD2中定义的参数,iode指星历数据事件,iodc指星钟数据事件. IOD 是 issue of data ,数 ...

  4. 【Alpha】事后诸葛亮

    一. 项目的预期计划 / 项目的现实进展 详见Alpha冲刺博客第一篇 二. 完成项目过程中的体会 详见Alpha冲刺博客第十二篇 三. 团队成员的分工及在Alpha阶段的工作量比例 成员 职务 博客 ...

  5. 手写阻塞队列(Condition实现)

    自己实现阻塞队列的话可以采用Object下的wait和notify方法,也可以使用Lock锁提供的Condition来实现,本文就是自己手撸的一个简单的阻塞队列,部分借鉴了JDK的源码.Ps:最近看面 ...

  6. 基于easyui开发Web版Activiti流程定制器详解(六)——Draw2d详解(二)

    回顾: 上一篇我们介绍了Draw2d整体结构,展示了组件类关系图,其中比较重要的类有Node.Canvas.Command.Port.Connection等,这篇将进一步介绍Draw2d如何使用以及如 ...

  7. BZOJ4241:历史研究(回滚莫队)

    Description IOI国历史研究的第一人——JOI教授,最近获得了一份被认为是古代IOI国的住民写下的日记.JOI教授为了通过这份日记来研究古代IOI国的生活,开始着手调查日记中记载的事件. ...

  8. 【[NOI2015]品酒大会】

    可能是最傻的做法了 暴力单调栈+\(st\)表 首先看到这道题就基本知道这是个\(SA\)了,先无脑敲上\(SA\)和求\(height\)的板子 之后尝试搞一下第一问 发现第一问就是求出满足\(lc ...

  9. 使用jenkins管理uirecorder录制的任务

    在uirecorder官网(http://uirecorder.com/)上,对jenkins的配置只有简单的几句话: How to dock Jenkins? Add commands source ...

  10. ganache-cli

    安装: npm install -g ganache-cli@6.1.8 使用: userdeMacBook-Pro:~ user$ ganache-cli -m "success rifl ...