OpenCV2.0 SVM代码及其分析
OpenCV 在很久以前就集成了SVM的功能,现在OpenCV升级到了3.0和3.1了,很多人都不习惯了怎么调用OpenCV中的SVM功能了。在之前OpenCV的SVM调用一直有个案例:首先,给定几组训练数据,并且给了label所对应的值。然后经过训练之后,对图像的各个位置进行预测是1还是-1。如果是1的话,用绿色来表示,如果是-1呢,用蓝色表示。并且还画出几个支持向量。
下面给了OpenCV2.0 的SVM代码(勿喷,直接从OpenCV官方网址复制下来的)
OpenCV 3.0、OpenCV3.1 的SVM训练代码
下面给出了正确的,记住是正确的代码:
例子1:
例子2:
运行的效果如下:
为了保证代码可读性,代码没有用using namespace cv
或using namespace cv::ml;
之类的代码,全部都写完整的名称,命名空间+类名。比如设置SVM的核类型为线性,写成svm->setKernel(cv::ml::SVM::KernelTypes::LINEAR);
。当然,这个只是一处地方,其他的请自己阅读。
代码的注意事项
虽然,大家的目标很明确:导入训练数据+label –> Mat, 训练,预测,显示这些目标。但是仍然避免不了代码错误。下面就是我遇到的代码的问题。
标签以及变成Mat的数据类型
其实,在本代码中出现了一种情况就是数据类型,下面均以标签为例:
这个是OpenCV3.0、OpenCV3.1正确的代码:
下面是OpenCV 2.X 正确代码
如果将OpenCV 2.X的代码换到OpenCV 3.1、OpenCV3.0代码会有什么样子的结果呢?
这个很熟悉吧所以,如果傻乎乎的换,这个是行不通的。
下面对于label
和labelMat
按照不同的情况进行分析。
首先,这个labelMat
和trainingMat
到底能取哪几种类型?
下面,请看OpenCV3.1 源码中的一个部分:
为了方便起见,将这个函数的代码的其他部分删除了。首先解释一下:samples
就是训练的数据。response
就是标签。通过上面,我们知道再来用Mat的时候,只能用CV_32F
和CV_32S
。所以说,如果这些矩阵不能写什么CV_8UC1
之类的了,这个是错误的。
假设我们写其他的情况,比如
label为int,labelsMat为CV_32SC1
这个是正确的。
label为float,labelsMat为CV_32FC1
这个会出现错误,这个我还没有分析出来是什么原因。错误的截图如下:
。
下面的错误均表示为截图所示的错误。
label为int,labelsMat为CV_32FC1
同样的,这个是错误。当我们用Imagewatch插件去观察labelsMat的值的时候发现这个labelsMat的值为
。好吧,这个很明显了。
label为float,labelsMat为CV_32SC1
这个是可以运行的,但是结果肯定是错误的。同样的,值不对。