利用SVM支持向量机对彩色图像进行分割并使用OpenCV进行实现

 机器学习中的一个比较常用的算法SVM,Support vector machine,支持向量机,具体说明可以看维基百科http://zh.wikipedia.org/wiki/SVM

本文主要对SVM在OpenCV中的应用进行一些说明。

1、首先是SVM的构造

原文这样说http://docs.opencv.org/modules/ml/doc/support_vector_machines.html#cvsvmparams

 CvSVM::CvSVM

Default and training constructors.

C++:   CvSVM:: CvSVM ( )
C++: CvSVM::CvSVM(const Mat& trainData, const Mat& responses, const Mat& varIdx=Mat(), const Mat&sampleIdx=Mat(), CvSVMParams params=CvSVMParams() )
C++:   CvSVM:: CvSVM (const CvMat*  trainData, const CvMat*  responses, const CvMat*  varIdx=0, const CvMat* sampleIdx=0, CvSVMParams  params=CvSVMParams()  )
Python:   cv2. SVM ( [trainData, responses [, varIdx [, sampleIdx [, params ] ] ] ] ) → <SVM object>

The constructors follow conventions of CvStatModel::CvStatModel(). See CvStatModel::train() for parameters descriptions.

加红的C++是常用到的一种构造。

使用一般是

// 对SVM进行训练
    CvSVM SVM;
    SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);

  CvSVM::train

Trains an SVM.

C++: bool CvSVM::train(const Mat& trainData, const Mat& responses, const Mat& varIdx=Mat(), const Mat&sampleIdx=Mat(), CvSVMParams params=CvSVMParams() )
C++:  bool  CvSVM:: train (const CvMat*  trainData, const CvMat*  responses, const CvMat*  varIdx=0, const CvMat* sampleIdx=0, CvSVMParams  params=CvSVMParams()  )
Python:   cv2.SVM. train (trainData, responses [, varIdx [, sampleIdx [, params ] ] ] ) → retval

The method trains the SVM model. It follows the conventions of the generic CvStatModel::train() approach with the following limitations:

  • Only the CV_ROW_SAMPLE data layout is supported.//一般是按照一行为一个样本,例如彩色图像,一般是一行表示(B G R )的一个像素点,对于M*N的图像,可以reshape成MN*3的长条形Mat,这样一行就是一个像素点了
  • Input variables are all ordered.
  • Output variables can be either categorical (params.svm_type=CvSVM::C_SVC or params.svm_type=CvSVM::NU_SVC), or ordered (params.svm_type=CvSVM::EPS_SVR or params.svm_type=CvSVM::NU_SVR), or not required at all (params.svm_type=CvSVM::ONE_CLASS).//几个参数,还未细究
  • Missing measurements are not supported.

All the other parameters are gathered in the CvSVMParams structure.

2、其次是设置SVM的参数

这里在网上看到有不同的设置形式,具体可以看参数的说明吧http://www.cnblogs.com/justany/archive/2012/11/23/2784125.html

// 设置SVM参数
    CvSVMParams params;
    params.svm_type    = CvSVM::C_SVC;
    params.kernel_type = CvSVM::LINEAR;
    params.term_crit   = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);

3、再然后就是对测试的样本进行predict了

   CvSVM::predict

Predicts the response for input sample(s).

C++: float CvSVM::predict(const Mat& sample, bool returnDFVal=false ) const
C++:  float  CvSVM:: predict (const CvMat*  sample, bool  returnDFVal=false  )  const
C++:  float  CvSVM:: predict (const CvMat*  samples, CvMat*  results )  const
Python:   cv2.SVM. predict (sample [, returnDFVal ] ) → retval
Python:   cv2.SVM. predict_all (samples [, results ] ) → results
Parameters:
  • sample – Input sample for prediction.
  • samples – Input samples for prediction.
  • returnDFVal – Specifies a type of the return value. If true and the problem is 2-class classification then the method returns the decision function value that is signed distance to the margin, else the function returns a class label (classification) or estimated function value (regression).
  • results – Output prediction responses for corresponding samples.

   float response = SVM.predict(sampleMat);

这里需要注意, sampleMat 是与上面 CV_ROW_SAMPLE 相对应的,是一行sample,例如是(B G R),response 是lables标记的两类的标记 1 或者-1 (或其他中表示都可以)

以上的部分在大部分帖子或是博客里都能看到,接下来讲一下本文的重点,就是利用SVM进行彩色图像的分割,当然,本文所用方法略显笨拙,由于不是计算机及相关专业出身,所用许多C/c++的潜在功能使用不畅,还需努力啊。言归正传

 首先是对

SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);

中的trainingDataMat 和labelsMat 进行人为的获取和训练,并且对我们得到的目标点和背景点(姑且这么说)进行人为标记,可以将目标点标记为1,将背景点标记为-1。


例如以上这个图像,当然比较简单一些,只有蓝色图像和背景灰色图像。

目标颜色图像ForeImage, 大小为M*N, 背景图像BackImage,大小为m*n

那么trainingDataMat可以这样获取

trainingDataMat=ForeImage.reshape(1, ForeImage.rows*ForeImage.cols);//转换成1维,行数为M*N的长条矩阵,,每一行为一                                                                     //   个像素点
trainingDataMat.convertTo(trainingDataMat,CV_32FC1);//这里转换成浮点数,试过uchar的话在接下来的train时会报错

这样就将目标点转换成了向量了(可以这么理解),然后还有就是背景点,这里是将BackImage中的像素点push_back到trainingDataMat的后面了,只是需要记住,0~(M*N-1)是目标蓝色像素点,而M*N~(M*N+m*n-1)是背景像素点就好,因为我们要在之后的labelsMat中对trainingDataMat的每一个行向量进行标记,将 0~(M*N-1)标记为1,将M*N~(M*N+m*n-1)标记为-1。

	labelsMat=Mat(ForeImage.cols*ForeImage.rows + BackImage.cols*BackImage.rows,1, CV_32FC1, Scalar::all(1));
	for (int h=0;h<BackImage.rows;h++)
	{
		uchar* p_BackImage = BackImage.ptr<uchar>(h);
		for (int w=0;w<BackImage.cols;w++)
		{
			Mat m_pTemp(1,3,CV_32FC1);
			m_pTemp.at<float>(0,0) = p_BackImage[3*w+0];
			m_pTemp.at<float>(0,1) = p_BackImage[3*w+1];
			m_pTemp.at<float>(0,2) = p_BackImage[3*w+2];

			trainingDataMat.push_back(m_pTemp);
			labelsMat.at<float>(ForeImage.cols*ForeImage.rows + h*BackImage.cols + w, 0) = -1;
		}	
	}

实际上跟其他博客中讲的差不多,把 http://www.cnblogs.com/justany/archive/2012/11/23/2784125.html中的小例子贴过来了 吐舌头

对本文中的完整工程项目VS2010+opencv2.4.2中实现,点击这儿可以下载。

最终实现的效果图还凑合。


对于简单的两类图像的场景,该文中的方法还是比较容易实现的,对于复杂的可以尝试高斯混合模型(GMM),还在学习中。。。

  • 1
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值