简体   繁体   English

使用SVM和opencv 3的图像训练

[英]Image train using SVM and opencv 3

#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;
using namespace std;

int main()
{
Mat img_mat = imread("/home/buddhika/workspace/project/images/t.jpg");

// Load images in the C++ format
Size size(64,124);//the image size,e.g.64x124
resize(img_mat ,img_mat ,size);//resize image

int num_files = 1;//number of images
int img_area = 64*124;//imag size
//initialize the training matrix
//The number of rows in the matrix would be 5, and the number of   columns would be the area of the image, 64*124 = 12
Mat training_mat(num_files,img_area,CV_32FC1);
// "fill in" the rows of training_mat with the data from each image.
cvtColor(img_mat,img_mat, CV_RGB2GRAY);
 imshow("",img_mat);

int ii = 0; // Current column in training_mat
//Do this for every training image
int file_num=0;
for (int i = 0; i<img_mat.rows; i++) {
    for (int j = 0; j < img_mat.cols; j++) {
        training_mat.at<float>(file_num,ii++) = img_mat.at<uchar>(i,j);
    }
}

// training matrix set up properly to pass into the SVM functions
//set up labels for each training image
//1D matrix, where each element in the 1D matrix corresponds to each row in the 2D matrix.
//-1 for non-human and 1 for human
//labels matrix
 float label = 1.0;
 cout << training_mat.rows<< endl;
 cout << training_mat.cols<< endl;
 Mat labels(1,7936 , CV_32SC1, label);

// Set up SVM's parameters
    Ptr<SVM> svmOld = SVM::create();
    svmOld->setType(SVM::C_SVC);
    svmOld->setKernel(SVM::LINEAR);
  //  svmOld->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));

    //train it based on your data

   svmOld->train(training_mat, ROW_SAMPLE, labels);
    //same svm
  svmOld->save("positive.xml");


    //Initialize SVM object
    Ptr<SVM> svmNew = SVM::create();
    //Load Previously saved SVM from XML
    //can save the trained SVM so you don't have to retrain it every time
    svmNew = SVM::load<SVM>("positive.xml");

//To test your images using the trained SVM, simply read an image, convert it to a 1D matrix, and pass that in to svm
// td.predict( training_mat);//It will return a value based on what you set as your labels

waitKey(0);
return(0);
}

This is the code I used for positive data train using SVM. 这是我用于使用SVM进行积极数据训练的代码。 But

svmOld->train(training_mat, ROW_SAMPLE, labels);

code crashed and give following error. 代码崩溃并给出以下错误。 How I overcome from this? 我该如何克服?

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 train, file /home/buddhika/Documents/OpenCV/modules/ml/src/svm.cpp, line 1618 terminate called after throwing an instance of 'cv::Exception' OpenCV错误:错误的参数(在分类问题的情况下,响应必须是分类的;在创建TrainData时指定varType,或者传递整数响应)在火车,文件/ home / buddhika / Documents / OpenCV / modules / ml / src / svm中.cpp,第1618行在引发'cv :: Exception'实例后终止终止

This happens because you are specifying that your samples are on the rows of your training_mat while you are writing them on the columns. 发生这种情况的原因是,您在将样本写在列上时指定了样本在training_mat的行上。

The code where you create your training matrix should be as follows: 创建训练矩阵的代码应如下所示:

Mat training_mat(img_area,num_files,CV_32FC1);
// "fill in" the rows of training_mat with the data from each image.
cvtColor(img_mat,img_mat, CV_RGB2GRAY);
imshow("",img_mat);

int ii = 0; // Current column in training_mat
//Do this for every training image
int file_num=0;
for (int i = 0; i<img_mat.rows; i++) {
    for (int j = 0; j < img_mat.cols; j++) {
        training_mat.at<float>(ii++,file_num) = img_mat.at<uchar>(i,j);
    }
}

And your labels should be changed too: Mat labels(training_mat.rows,1 , CV_32SC1, label); 并且您的labels应该更改: Mat labels(training_mat.rows,1 , CV_32SC1, label);

I don't know that i am right or not, but i would like to try it. 我不知道我是否正确,但是我想尝试一下。

Now talking about your question.As the problem seems to be the implementation of SVM.I would first advise you to study the opencv implementation of SVM first. 现在讨论您的问题,因为问题似乎出在SVM的实现上,我首先建议您先研究SVM的opencv实现。 https://docs.opencv.org/2.4/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html https://docs.opencv.org/2.4/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html

What i understand from the SVM documentation is that you have to first provide the training DataSet to it with the class label. 我从SVM文档中了解到,您必须首先使用类标签为其提供训练数据集。 Based upon the provided training data it would train the SVM. 根据提供的训练数据,它将训练SVM。 Also you have to train it for the both positive labels as well as for the negative labels. 另外,您还必须针对正标签和负标签进行训练。

What you are doing is quiet wrong.I had run your code on my machine and done some debuggging on it. 您正在做的事情很安静,我已经在计算机上运行了您的代码并对其进行了调试。 Use this debugged code. 使用此调试代码。

Mat img_mat = imread("C:\\Users\\saurabh chandra\\Desktop\\52.png");
Mat img_mat1 = imread("C:\\Users\\saurabh chandra\\Desktop\\53.png");
Size size(64, 124);                
resize(img_mat, img_mat, size);   
resize(img_mat1, img_mat1, size);
int num_files = 2;             
int img_area = 64 * 124;      


cvtColor(img_mat, img_mat, CV_RGB2GRAY);  
cvtColor(img_mat1, img_mat1, COLOR_BGR2GRAY);

int ii = 0; 

int file_num = 0;
for (int i = 0; i<img_mat.rows; i++) 
{
for (int j = 0; j < img_mat.cols; j++) 
{
    training_mat.at<float>(file_num, ii++) = img_mat.at<uchar>(i, j);
}

 }

ii = 0;
 file_num =file_num+1;

 for (int i = 0; i<img_mat.rows; i++)
  {
     for (int j = 0; j < img_mat.cols; j++)
     {
      training_mat.at<float>(file_num, ii++) = img_mat.at<uchar>(i, j);
     }
  }


 float label[2] = { 1.0,1.0 };
 cout << training_mat.rows << endl;
 cout << training_mat.cols << endl;
 Mat labels(2, 1, CV_32SC1, label);

 Ptr<SVM> svmOld = SVM::create();
 svmOld->setType(SVM::C_SVC);
 svmOld->setKernel(SVM::LINEAR);
 svmOld->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));

 svmOld->train(training_mat, ROW_SAMPLE, labels);
 svmOld->save("positive.xml");

 waitKey(0);
 return 0;
}

This code is saving the SVM training result into Positive.xml file.I had implemented your code for two images. 该代码将SVM训练结果保存到Positive.xml文件中。我已经为两个图像实现了您的代码。 But i would advise you to use good and large training data for better results. 但我建议您使用良好的大型训练数据,以获得更好的结果。

For better understanding on SVM implementation you can check here. 为了更好地了解SVM的实现,您可以在此处进行检查。

using OpenCV and SVM with images 将OpenCV和SVM与图像一起使用

If this help let me know. 如果有帮助,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM