学习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. .Net Core+Vue.js+ElementUI 实现前后端分离

    .Net Core+Vue.js+ElementUI 实现前后端分离 Tags: Vue 架构 前端采用:Vue.js.Element-UI.axios 后端采用:.Net Core Mvc 本项目是 ...

  2. SQL Server 常用数据类型

    char:    固定长度,存储ANSI字符,不足的补英文半角空格. varchar:  可变长度,存储ANSI字符,根据数据长度自动变化. nchar:   固定长度存储Unicode字符,汉字英文 ...

  3. [翻译] CSStickyHeaderFlowLayout

    CSStickyHeaderFlowLayout https://github.com/jamztang/CSStickyHeaderFlowLayout Parallax, Sticky Heade ...

  4. 获取系统屏幕尺寸参数的类WxHxD

    获取系统屏幕尺寸参数的类WxHxD 源码: // // WxHxD.h // PM2.5 // // Created by YouXianMing on 14/10/29. // Copyright ...

  5. SQL语言DDL DML DCL TCL四种语言

    1.DDL(Data Definition Language)数据库定义语言:DDL使我们有能力创建或删 除表格.可以定义索引(键),规定表之间的链接,以及施加表间的 约束. • 常见DDL 语句: ...

  6. Python学习---xml文件的解析[beautifulsoup4模块学习]

    1.1. 安装beautifulsoup4 pip install beautifulsoup4 [更多参考]https://blog.csdn.net/sunhuaqiang1/article/de ...

  7. Linux chkconfig命令详解

    chkconfig命令检查.设置系统的各种服务.这是Red Hat公司遵循GPL规则所开发的程序,它可查询操作系统在每一个执行等级中会执行哪些系统服务,其中包括各类常驻服务.谨记chkconfig不是 ...

  8. php 开源项目汇总

    WordPress是最热门的开源个人信息发布系统(Blog)之一,基于PHP+MySQL构建.WordPress提供的功能包括:1.文章发布.分类.归档. 2.提供文章.评论.分类等多种形式的RSS聚 ...

  9. Spring Boot REST

    资源(Resources) 所谓资源,就是网络上一个实体,或者是网络上一个具体信息.他可以是一段文本,一张图片,一种服务,总之是一个具体的实体.可以用一个URI(统一资源定位符)指向它,每种资源对应一 ...

  10. Service Mesh服务网格之Linkerd架构

    今天详细介绍一下Linkerd的架构. 控制平面 Linkerd控制平面是一组在专用Kubernetes命名空间中运行的服务(在Linked默认情况下).这些服务完成各种事情——聚合遥测数据.提供面向 ...