欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

学习OpenCV——SVM

发布时间:2025/4/16 编程问答 37 豆豆
生活随笔 收集整理的这篇文章主要介绍了 学习OpenCV——SVM 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

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?
  • // step 1:   
  • float labels[4] = {1.0, -1.0, -1.0, -1.0};  
  • Mat labelsMat(3, 1, CV_32FC1, labels);  
  •   
  • float trainingData[4][2] = { {501, 10}, {255, 10}, {501, 255}, {10, 501} };  
  • Mat trainingDataMat(3, 2, CV_32FC1, trainingData);  
  •   
  • // step 2:   
  • CvSVMParams params;  
  • params.svm_type = CvSVM::C_SVC;  
  • params.kernel_type = CvSVM::LINEAR;  
  • params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);  
  •   
  • // step 3:   
  • CvSVM SVM;  
  • SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);  
  •   
  • // step 4:   
  • Vec3b green(0, 255, 0), blue(255, 0, 0);  
  • for (int i=0; i<image.rows; i++)  
  • {  
  •     for (int j=0; j<image.cols; j++)  
  •     {  
  •         Mat sampleMat = (Mat_<float>(1,2) << i,j);  
  •         float response = SVM.predict(sampleMat);  
  •   
  •         if (fabs(response-1.0) < 0.0001)  
  •         {  
  •             image.at<Vec3b>(j, i) = green;  
  •         }  
  •         else if (fabs(response+1.0) < 0.001)  
  •         {  
  •             image.at<Vec3b>(j, i) = blue;  
  •         }  
  •     }  
  • }  
  •   
  • // step 5:   
  • int c = SVM.get_support_vector_count();  
  •   
  • for (int i=0; i<c; i++)  
  • {  
  •     const float* v = SVM.get_support_vector(i);  
  • }  
  •  

    实验代码1:颜色分类

    [cpp] view plaincopyprint?
  • //利用SVM解决2维空间向量的3级分类问题      
  • #include "stdafx.h"      
  • #include "cv.h"      
  • #include "highgui.h"             
  • #include <ML.H>      
  • #include <TIME.H>      
  •      
  • #include <CTYPE.H>      
  •     
  • #include <IOSTREAM>      
  • using namespace std;     
  • int main(int argc, char **argv)     
  • {     
  •         int size = 400;         //图像的长度和宽度      
  •         const int s = 1000;          //试验点个数(可更改!!)      
  •         int i, j, sv_num;     
  •         IplImage *img;     
  •         CvSVM svm = CvSVM();    //★★★      
  •         CvSVMParams param;     
  •         CvTermCriteria criteria;//停止迭代的标准      
  •         CvRNG rng = cvRNG(time(NULL));     
  •         CvPoint pts[s];         //定义1000个点      
  •         float data[s*2];        //点的坐标      
  •         int res[s];             //点的所属类      
  •         CvMat data_mat, res_mat;     
  •         CvScalar rcolor;     
  •         const float *support;     
  •         // (1)图像区域的确保和初始化      
  •         img= cvCreateImage(cvSize(size, size), IPL_DEPTH_8U, 3);     
  •         cvZero(img);     
  •         //确保画像区域,并清0(用黑色作初始化处理)。      
  •          
  •         // (2)学习数据的生成      
  •         for (i= 0; i< s; i++) {     
  •             pts[i].x= cvRandInt(&rng) % size;   //用随机整数赋值      
  •             pts[i].y= cvRandInt(&rng) % size;     
  •             if (pts[i].y> 50 * cos(pts[i].x* CV_PI/ 100) + 200) {     
  •                 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));     
  •                 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));     
  •                 res[i] = 1;     
  •             }     
  •             else {     
  •                 if (pts[i].x> 200) {     
  •                     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));     
  •                     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));     
  •                     res[i] = 2;     
  •                 }     
  •                 else {     
  •                     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));     
  •                     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));     
  •                     res[i] = 3;     
  •                 }     
  •             }     
  •         }     
  •         //生成2维随机训练数据,并将其值放在CvPoint数据类型的数组pts[ ]中。      
  •          
  •         // (3)学习数据的显示      
  •         cvNamedWindow("SVM", CV_WINDOW_AUTOSIZE);     
  •         cvShowImage("SVM", img);     
  •         cvWaitKey(0);     
  •          
  •         // (4)学习参数的生成      
  •         for (i= 0; i< s; i++) {     
  •             data[i* 2] = float (pts[i].x) / size;     
  •             data[i* 2 + 1] = float (pts[i].y) / size;     
  •         }     
  •         cvInitMatHeader(&data_mat, s, 2, CV_32FC1, data);     
  •         cvInitMatHeader(&res_mat, s, 1, CV_32SC1, res);     
  •         criteria= cvTermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON);     
  •         param= CvSVMParams (CvSVM::C_SVC, CvSVM::RBF, 10.0, 8.0, 1.0, 10.0, 0.5, 0.1, NULL, criteria);     
  •         /*   
  •             SVM种类:CvSVM::C_SVC   
  •             Kernel的种类:CvSVM::RBF   
  •             degree:10.0(此次不使用)   
  •             gamma:8.0   
  •             coef0:1.0(此次不使用)   
  •             C:10.0   
  •             nu:0.5(此次不使用)   
  •             p:0.1(此次不使用)   
  •             然后对训练数据正规化处理,并放在CvMat型的数组里。   
  •                                                                 */     
  •          
  •          
  •         //☆☆☆☆☆☆☆☆☆(5)SVM学习☆☆☆☆☆☆☆☆☆☆☆☆      
  •         svm.train(&data_mat, &res_mat, NULL, NULL, param);//☆      
  •         //☆☆利用训练数据和确定的学习参数,进行SVM学习☆☆☆☆          
  •          
  •         // (6)学习结果的绘图      
  •         for (i= 0; i< size; i++) {     
  •             for (j= 0; j< size; j++) {     
  •                 CvMat m;     
  •                 float ret = 0.0;     
  •                 float a[] = { float (j) / size, float (i) / size };     
  •                 cvInitMatHeader(&m, 1, 2, CV_32FC1, a);     
  •                 ret= svm.predict(&m);     
  •                 switch ((int) ret) {     
  •                     case 1:     
  •                         rcolor= CV_RGB(100, 0, 0);     
  •                         break;     
  •                     case 2:     
  •                         rcolor= CV_RGB(0, 100, 0);     
  •                         break;     
  •                     case 3:     
  •                         rcolor= CV_RGB(0, 0, 100);     
  •                         break;     
  •                 }     
  •                 cvSet2D(img, i, j, rcolor);     
  •             }     
  •         }     
  •         //为了显示学习结果,通过输入图像区域的所有像素(特征向量)并进行分类。然后对输入像素用所属等级的颜色绘图。      
  •          
  •         // (7)训练数据的再绘制      
  •         for (i= 0; i< s; i++) {     
  •             CvScalar rcolor;     
  •             switch (res[i]) {     
  •                 case 1:     
  •                     rcolor= CV_RGB(255, 0, 0);     
  •                     break;     
  •                 case 2:     
  •                     rcolor= CV_RGB(0, 255, 0);     
  •                     break;     
  •                 case 3:     
  •                     rcolor= CV_RGB(0, 0, 255);     
  •                     break;     
  •             }     
  •             cvLine(img, cvPoint(pts[i].x- 2, pts[i].y- 2), cvPoint(pts[i].x+ 2, pts[i].y+ 2), rcolor);     
  •             cvLine(img, cvPoint(pts[i].x+ 2, pts[i].y- 2), cvPoint(pts[i].x- 2, pts[i].y+ 2), rcolor);     
  •         }     
  •         //将训练数据在结果图像上重复的绘制出来。      
  •          
  •         // (8)支持向量的绘制      
  •         sv_num= svm.get_support_vector_count();     
  •         for (i= 0; i< sv_num; i++) {     
  •             support = svm.get_support_vector(i);     
  •             cvCircle(img, cvPoint((int) (support[0] * size), (int) (support[1] * size)), 5, CV_RGB(200, 200, 200));     
  •         }     
  •         //用白色的圆圈对支持向量作标记。      
  •          
  •         // (9)图像的显示       
  •         cvNamedWindow("SVM", CV_WINDOW_AUTOSIZE);     
  •         cvShowImage("SVM", img);     
  •         cvWaitKey(0);     
  •         cvDestroyWindow("SVM");     
  •         cvReleaseImage(&img);     
  •         return 0;     
  •         //显示实际处理结果的图像,直到某个键被按下为止。      
  •     }    

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

    [cpp] view plaincopyprint?
  • //  
  • // File Name: pjSVM.cpp  
  • // Author:   easyfov(easyfov@gmail.com)  
  • // Company: Lida Optical and Electronic Co.,Ltd.  
  • //http://apps.hi.baidu.com/share/detail/32719017  
  • //  
  •   
  • #include <cv.h>  
  • #include <highgui.h>  
  • #include <ml.h>  
  •   
  • #include <iostream>  
  • #include <fstream>  
  • #include <string>  
  • #include <vector>  
  • using namespace std;  
  •   
  • #define WIDTH 20  
  • #define HEIGHT 20  
  •   
  • int main( /*int argc, char** argv*/ )  
  • {  
  •     vector<string> img_path;  
  •     vector<int> img_catg;  
  •     int nLine = 0;  
  •     string buf;  
  •     ifstream svm_data( "E:/SVM_DATA.txt" );  
  •   
  •     while( svm_data )  
  •     {  
  •         if( getline( svm_data, buf ) )  
  •         {  
  •             nLine ++;  
  •             if( nLine % 2 == 0 )  
  •             {  
  •                  img_catg.push_back( atoi( buf.c_str() ) );//atoi将字符串转换成整型,标志(0,1)  
  •             }  
  •             else  
  •             {  
  •                 img_path.push_back( buf );//图像路径  
  •             }  
  •         }  
  •     }  
  •     svm_data.close();//关闭文件  
  •   
  •     CvMat *data_mat, *res_mat;  
  •     int nImgNum = nLine / 2;            //读入样本数量  
  •     样本矩阵,nImgNum:横坐标是样本数量, WIDTH * HEIGHT:样本特征向量,即图像大小  
  •     data_mat = cvCreateMat( nImgNum, WIDTH * HEIGHT, CV_32FC1 );  
  •     cvSetZero( data_mat );  
  •     //类型矩阵,存储每个样本的类型标志  
  •     res_mat = cvCreateMat( nImgNum, 1, CV_32FC1 );  
  •     cvSetZero( res_mat );  
  •   
  •     IplImage *srcImg, *sampleImg;  
  •     float b;  
  •     DWORD n;  
  •   
  •     for( string::size_type i = 0; i != img_path.size(); i++ )  
  •     {  
  •        srcImg = cvLoadImage( img_path[i].c_str(), CV_LOAD_IMAGE_GRAYSCALE );  
  •        if( srcImg == NULL )  
  •        {  
  •             cout<<" can not load the image: "<<img_path[i].c_str()<<endl;  
  •             continue;  
  •        }  
  •   
  •        cout<<" processing "<<img_path[i].c_str()<<endl;  
  •   
  •        sampleImg = cvCreateImage( cvSize( WIDTH, HEIGHT ), IPL_DEPTH_8U, 1 );//样本大小(WIDTH, HEIGHT)  
  •        cvResize( srcImg, sampleImg );//改变图像大小  
  •   
  •        cvSmooth( sampleImg, sampleImg );    //降噪  
  •        //生成训练数据  
  •        n = 0;  
  •         forint ii = 0; ii < sampleImg->height; ii++ )  
  •         {  
  •             forint jj = 0; jj < sampleImg->width; jj++, n++ )  
  •             {  
  •                  b = (float)((int)((uchar)( sampleImg->imageData + sampleImg->widthStep * ii + jj )) / 255.0 );  
  •                  cvmSet( data_mat, (int)i, n, b );  
  •             }  
  •         }  
  •         cvmSet( res_mat, i, 0, img_catg[i] );  
  •         cout<<" end processing "<<img_path[i].c_str()<<" "<<img_catg[i]<<endl;  
  •     }  
  •   
  •   
  •     CvSVM svm = CvSVM();  
  •     CvSVMParams param;  
  •     CvTermCriteria criteria;  
  •     criteria = cvTermCriteria( CV_TERMCRIT_EPS, 1000, FLT_EPSILON );  
  •     param = CvSVMParams( CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.09, 1.0, 10.0, 0.5, 1.0, NULL, criteria );  
  •      /*   
  •             SVM种类:CvSVM::C_SVC   
  •             Kernel的种类:CvSVM::RBF   
  •             degree:10.0(此次不使用)   
  •             gamma:8.0   
  •             coef0:1.0(此次不使用)   
  •             C:10.0   
  •             nu:0.5(此次不使用)   
  •             p:0.1(此次不使用)   
  •             然后对训练数据正规化处理,并放在CvMat型的数组里。   
  •                                                                 */     
  •     //☆☆☆☆☆☆☆☆☆(5)SVM学习☆☆☆☆☆☆☆☆☆☆☆☆      
  •     svm.train( data_mat, res_mat, NULL, NULL, param );  
  •     //☆☆利用训练数据和确定的学习参数,进行SVM学习☆☆☆☆  
  •     svm.save( "SVM_DATA.xml" );  
  •   
  •   
  •     //检测样本  
  •     IplImage *tst, *tst_tmp;  
  •     vector<string> img_tst_path;  
  •     ifstream img_tst( "E:/SVM_TEST.txt" );  
  •     while( img_tst )  
  •     {  
  •         if( getline( img_tst, buf ) )  
  •         {  
  •             img_tst_path.push_back( buf );  
  •         }  
  •     }  
  •     img_tst.close();  
  •   
  •     CvMat *tst_mat = cvCreateMat( 1, WIDTH*HEIGHT, CV_32FC1 );  
  •     char line[512];  
  •     ofstream predict_txt( "SVM_PREDICT.txt" );  
  •     for( string::size_type j = 0; j != img_tst_path.size(); j++ )  
  •     {  
  •         tst = cvLoadImage( img_tst_path[j].c_str(), CV_LOAD_IMAGE_GRAYSCALE );  
  •         if( tst == NULL )  
  •         {  
  •              cout<<" can not load the image: "<<img_tst_path[j].c_str()<<endl;  
  •                continue;  
  •    }  
  •    tst_tmp = cvCreateImage( cvSize( WIDTH, HEIGHT ), IPL_DEPTH_8U, 1 );  
  •    cvResize( tst, tst_tmp );  
  •    cvSmooth( tst_tmp, tst_tmp );  
  •    n = 0;  
  •    for(int ii = 0; ii < tst_tmp->height; ii++ )  
  •    {  
  •      for(int jj = 0; jj < tst_tmp->width; jj++, n++ )  
  •      {  
  •          b = (float)(((int)((uchar)tst_tmp->imageData+tst_tmp->widthStep*ii+jj))/255.0);  
  •          cvmSet( tst_mat, 0, n, (double)b );  
  •      }  
  •    }  
  •   
  •    int ret = svm.predict( tst_mat );  
  •    sprintf( line, "%s %d\r\n", img_tst_path[j].c_str(), ret );  
  •    predict_txt<<line;  
  • }  
  • predict_txt.close();  
  •   
  • cvReleaseImage( &srcImg );  
  • cvReleaseImage( &sampleImg );  
  • cvReleaseImage( &tst );  
  • cvReleaseImage( &tst_tmp );  
  • cvReleaseMat( &data_mat );  
  • cvReleaseMat( &res_mat );  
  •   
  • return 0;  
  • }  

  • 其中

    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的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。