生活随笔
收集整理的这篇文章主要介绍了
学习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?
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); CvSVMParams params; params.svm_type = CvSVM::C_SVC; params.kernel_type = CvSVM::LINEAR; params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6); CvSVM SVM; SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params); 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; } } } 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?
#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]; float data[s*2]; int res[s]; CvMat data_mat, res_mat; CvScalar rcolor; const float *support; img= cvCreateImage(cvSize(size, size), IPL_DEPTH_8U, 3); cvZero(img); 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; } } } cvNamedWindow("SVM", CV_WINDOW_AUTOSIZE); cvShowImage("SVM", img); cvWaitKey(0); 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.train(&data_mat, &res_mat, NULL, NULL, param); 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); } } 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); } 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)); } cvNamedWindow("SVM", CV_WINDOW_AUTOSIZE); cvShowImage("SVM", img); cvWaitKey(0); cvDestroyWindow("SVM"); cvReleaseImage(&img); return 0; }
实验代码2:用MIT人脸库检测,效果实在不好,检测结果全是人脸或者全都不是人脸。原因应该是图像检测没有做好应该用HoG等特征首先检测,在进行分类训练,不特征不明显,肯定分类效果并不好。
[cpp] view plaincopyprint?
#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( ) { 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() ) ); } else { img_path.push_back( buf ); } } } svm_data.close(); CvMat *data_mat, *res_mat; int nImgNum = nLine / 2; 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 ); cvResize( srcImg, sampleImg ); cvSmooth( sampleImg, sampleImg ); n = 0; for( int ii = 0; ii < sampleImg->height; ii++ ) { for( int 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.train( data_mat, res_mat, NULL, NULL, param ); 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的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。