使用 SVM 支持向量机和 OpenCV 实现彩色图像分割 - CvSVM::predict
最编程
2024-03-31 14:37:45
...
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),还在学习中。。。
上一篇: 使用 CSS 打印背景颜色