OpenCV 无法设置 SVM 参数
Posted
技术标签:
【中文标题】OpenCV 无法设置 SVM 参数【英文标题】:OpenCV unable to set up SVM Parameters 【发布时间】:2016-02-27 03:20:03 【问题描述】:我刚刚开始使用 C++ OpenCV 学习 SVM,并参考了 SVM 文档here。我想先试用链接中的示例源代码以熟悉它,但我无法运行示例源代码。它返回错误:
错误 1 错误 C2065: 'CvSVMParams' : 未声明的标识符
我正在使用带有 OpenCV 3.0.0 的 Visual Studio 2012。设置过程应该是正确的,因为除此之外所有其他代码都运行良好。
【问题讨论】:
谢谢。但我现在收到此错误:错误 C2039: 'Params' : is not a member of 'cv::ml::SVM' 你能显示一些代码吗? 对不起,我只是从here复制了完全相同的示例源代码 可能样本也过时了...像我在回答我链接的问题时所做的那样设置参数,即svm->setType(SVM::C_SVC);
等...
好吧,这可能不简单,我会添加一个答案
【参考方案1】:
很多事情都改变了from OpenCV 2.4 to OpenCV 3.0。其中包括不向后兼容的机器学习模块。
这是 OpenCV tutorial code for the SVM,OpenCV 3.0 更新:
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>
using namespace cv;
using namespace cv::ml;
int main(int, char**)
// Data for visual representation
int width = 512, height = 512;
Mat image = Mat::zeros(height, width, CV_8UC3);
// Set up training data
int labels[4] = 1, -1, -1, -1 ;
Mat labelsMat(4, 1, CV_32SC1, labels);
float trainingData[4][2] = 501, 10 , 255, 10 , 501, 255 , 10, 501 ;
Mat trainingDataMat(4, 2, CV_32FC1, trainingData);
// Set up SVM's parameters
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::LINEAR);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
// Train the SVM with given parameters
Ptr<TrainData> td = TrainData::create(trainingDataMat, ROW_SAMPLE, labelsMat);
svm->train(td);
// Or train the SVM with optimal parameters
//svm->trainAuto(td);
Vec3b green(0, 255, 0), blue(255, 0, 0);
// Show the decision regions given by the SVM
for (int i = 0; i < image.rows; ++i)
for (int j = 0; j < image.cols; ++j)
Mat sampleMat = (Mat_<float>(1, 2) << j, i);
float response = svm->predict(sampleMat);
if (response == 1)
image.at<Vec3b>(i, j) = green;
else if (response == -1)
image.at<Vec3b>(i, j) = blue;
// Show the training data
int thickness = -1;
int lineType = 8;
circle(image, Point(501, 10), 5, Scalar(0, 0, 0), thickness, lineType);
circle(image, Point(255, 10), 5, Scalar(255, 255, 255), thickness, lineType);
circle(image, Point(501, 255), 5, Scalar(255, 255, 255), thickness, lineType);
circle(image, Point(10, 501), 5, Scalar(255, 255, 255), thickness, lineType);
// Show support vectors
thickness = 2;
lineType = 8;
Mat sv = svm->getSupportVectors();
for (int i = 0; i < sv.rows; ++i)
const float* v = sv.ptr<float>(i);
circle(image, Point((int)v[0], (int)v[1]), 6, Scalar(128, 128, 128), thickness, lineType);
imwrite("result.png", image); // save the image
imshow("SVM Simple Example", image); // show it to the user
waitKey(0);
输出应如下所示:
【讨论】:
如果我有两个负数据集和正数据集,我该如何为 SVM 训练这些数据集 @Miki 谢谢——总是很难找到这些新东西,因为搜索引擎已经展示了很多旧方法!我对此进行了修改以显式显示哪些内容位于哪个命名空间中,并将绘图链接到实际数据而不是复制它:gist.github.com/daviddoria/943b82f1877f4ed3541544c48c22926d @Miki 我们不能在堆栈上创建 SVM 对象有什么原因吗?我查看了svm.cpp
和create()
只返回一个SVMImpl
,但这是故意隐藏的,我猜是因为这就是PIMPL 的意义所在?只是想确认我的理解:)
@Miki 我试过trainAuto
(与train
相比)发现response
在使用-1
时在任何地方都为零。输出图像看起来一样,除了大的蓝色区域变成黑色(因为图像被初始化为零)。这是预期的吗?
嗨@大卫!我明天会检查.. 或星期一;D 感谢您的编辑! (据我了解是适合“算法”界面。是的,pimpl .. 不打算在课堂外使用)【参考方案2】:
我发现上面的代码有效,但我需要进行一些小修改才能将标签转换为整数。修改为粗体:
// Set up training data **Original**:
int labels[4] = 1, -1, -1, -1 ;
Mat labelsMat(4, 1, **CV_32SC1**, labels);
// Set up training data **Modified**:
int labels[4] = 1, -1, -1, -1 ;
Mat labelsMat(4, 1, **CV_32S**, labels);
【讨论】:
为什么需要这样做? 根据我的成员,类标签是双精度或特征矩阵是整数。这是 6 多年前的事了,所以有点朦胧CV_32S
和 CV_32SC1
考虑到构造函数的调用方式没有区别。它们在这里的意思是一样的。以上是关于OpenCV 无法设置 SVM 参数的主要内容,如果未能解决你的问题,请参考以下文章