OpenCV SVM培训数据 [英] OpenCV SVM Training Data

查看:357
本文介绍了OpenCV SVM培训数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过在C ++和Visual Studio 2013中使用opencv 3.00库来学习svm实现。
我的代码:

 #include< stdio.h> 
#include< math.h>
#include< opencv\cv.h>
#include< opencv\highgui.h>
#include< opencv2\objdetect\objdetect.hpp>
#include< opencv2\highgui\highgui.hpp>
#include< opencv2\imgproc\imgproc.hpp>
#include< vector>
#include< windows.h>
#include< atlstr.h>
#include< iostream>
#include< sstream>
#include< iomanip>
#include< opencv2\imgproc\imgproc.hpp>
#include< opencv2\core\core.hpp>
#include< opencv2\highgui\highgui.hpp>
#include< opencv\cvaux.hpp>

using namespace cv;
using namespace std;

#include< opencv2\ml.hpp>

using namespace cv;

int main()
{
//视觉表示数据
int width = 512,height = 512;
Mat image = Mat :: zeros(height,width,CV_8UC3);

//设置训练数据
float labels [4] = {1.0,-1.0,-1.0,-1.0};
Mat labelsMat(4,1,CV_32FC1,labels);

float trainingData [4] [2] = {{501,10},{255,10},{501,255},{10,501}};
Mat trainingDataMat(4,2,CV_32FC1,trainingData);

//设置SVM的参数

Ptr< ml :: SVM> svm = ml :: SVM :: create();
// edit:params struct被删除,
//我们使用setter / getter now:
svm-> setType(ml :: SVM :: C_SVC);
svm-> setKernel(ml :: SVM :: LINEAR);
svm-> setGamma(3);

svm-> train(trainingDataMat,ml :: ROW_SAMPLE,labelsMat);

Mat res; // output


Vec3b green(0,255,0),blue(255,0,0);
//显示由SVM给出的决定区域
for(int i = 0; i for(int j = 0; j < image.cols; ++ j)
{
Mat sampleMat =(Mat_< float>(1,2)<< j,i);
float response = svm-> predict(sampleMat,res);

if(response == 1)
image.at< Vec3b>(i,j)= green;
else if(response == -1)
image.at< Vec3b>(i,j)= blue;
}

//显示训练数据
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);

//显示支持向量
thickness = 2;
lineType = 8;
Mat sv = svm-> getSupportVectors();

for(int i = 0; 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); //显示给用户
waitKey(0);

}

运行此代码后, p>

  OpenCV错误:错误参数<在分类问题的情况下,答复必须是分类的; 
在创建TrainData时指定varType,或者传递整数响应>在cv :: ml :: SVMImpl :: train,
文件C:\builds\master_PackSlave-win64-vc12-shared\opencv\modules\ml\src\svm.cpp,行1610

我调试了该代码。调试器停在此行: svm-> train(trainingDataMat,ml :: ROW_SAMPLE,labelsMat);



它说:

  train.exe中0x000007FEFDA5AAAD的第一次例外:Microsoft C ++异常:cv ::内存位置异常0x00000000001CEE50。 
未处理的异常在0x000007FEFDA5AAAD在train.exe:Microsoft C ++异常:cv ::在内存位置0x00000000001CEE50的异常。

此外,它说:

 (Win32):加载'C:\OpenCV3.0.0\opencv\build\x64\vc12\bin \opencv_world300d.dll'。找不到或打开PDB文件。 

其实,我的理解是问题与内存有关。

解决方案

响应的类型不能为 float double



更改

  float labels [4] = {1.0,-1.0,-1.0,-1.0}; 
Mat labelsMat(4,1,CV_32FC1,labels);

  int labels [4] = {1,-1,-1,-1}; 
Mat labelsMat(4,1,CV_32S,labels);

BTW,如果你使用Linear kernel,唯一的参数是 C ,因此您不需要 setGamma





$ b另一个问题是获得预测响应的方式。因为每次只有一个样本来预测,如果你想使用返回值作为响应,你不应该传递 res predict



您可以更改

  float response = svm-> predict(sampleMat,res); 

  float response = svm-> predict(sampleMat); 

否则,如果您要使用 res ,那么返回值不再是响应值。但您可以从 res 得到回应。



您可以更改

  if(response == 1)
image.at< Vec3b>(i,j)= green;
else if(response == -1)
image.at< Vec3b>(i,j)= blue;
}

  if(res.at< float>(0)== 1)
image.at< Vec3b>(i,j)= green;
else if(res.at< float>(0)== -1)
image.at< Vec3b>(i,j)= blue;
}


I would like to learn svm implementation by using opencv 3.00 library in C++ and Visual Studio 2013. My code:

#include<stdio.h>
#include<math.h>
#include<opencv\cv.h>
#include<opencv\highgui.h>
#include<opencv2\objdetect\objdetect.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include<vector>
#include <windows.h>
#include <atlstr.h>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv\cvaux.hpp>

using namespace cv;
using namespace std;

#include <opencv2\ml.hpp>

using namespace cv;

int main()
{
    // Data for visual representation
    int width = 512, height = 512;
    Mat image = Mat::zeros(height, width, CV_8UC3);

    // Set up training data
    float labels[4] = { 1.0, -1.0, -1.0, -1.0 };
    Mat labelsMat(4, 1, CV_32FC1, 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<ml::SVM> svm = ml::SVM::create();
    // edit: the params struct got removed,
    // we use setter/getter now:
    svm->setType(ml::SVM::C_SVC);
    svm->setKernel(ml::SVM::LINEAR);
    svm->setGamma(3);

    svm->train(trainingDataMat, ml::ROW_SAMPLE, labelsMat);

    Mat res;   // output


    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, res);

        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);

} 

After running this code, I got that error:

OpenCV Error: Bad argument < in the case of classification problem the responses must be categorical; 
either specify varType when creating TrainData, or pass integer responses > in cv::ml::SVMImpl::train, 
file C:\builds\master_PackSlave-win64-vc12-shared\opencv\modules\ml\src\svm.cpp, line 1610

I debugged that code. The debugger stops at this line: svm->train(trainingDataMat, ml::ROW_SAMPLE, labelsMat);

It says:

 First-chance exception at 0x000007FEFDA5AAAD in train.exe: Microsoft C++ exception: cv::Exception at memory location 0x00000000001CEE50.
    Unhandled exception at 0x000007FEFDA5AAAD in train.exe: Microsoft C++ exception: cv::Exception at memory location 0x00000000001CEE50.

Besides, it says that:

(Win32): Loaded 'C:\OpenCV3.0.0\opencv\build\x64\vc12\bin\opencv_world300d.dll'. Cannot find or open the PDB file.

Actually, what I understand is that the problem is related to the memory.

解决方案

The type of responses cannot be float or double.

Change

float labels[4] = { 1.0, -1.0, -1.0, -1.0 };
Mat labelsMat(4, 1, CV_32FC1, labels);

to

int labels[4] = { 1, -1, -1, -1 };
Mat labelsMat(4, 1, CV_32S, labels);

BTW, if you are using Linear kernel, the only parameter is C, so you do not need to setGamma.


Another problem is the way to get the predicted response. Since each time there is only one sample to predict, if you want to use the return value as the response, you should not pass res to predict.

You can change

float response = svm->predict(sampleMat, res);

to

float response = svm->predict(sampleMat);

Otherwise, if you want to use res, then the return value is no longer the response value. But you can get the response from res instead.

You can change

if (response == 1)
    image.at<Vec3b>(i, j) = green;
else if (response == -1)
    image.at<Vec3b>(i, j) = blue;
}

to

if (res.at<float>(0) == 1)
    image.at<Vec3b>(i, j) = green;
else if (res.at<float>(0) == -1)
    image.at<Vec3b>(i, j) = blue;
}

这篇关于OpenCV SVM培训数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆