How to prepare SVM with opencv based on a set of images?

I have a folder with positives and another image of negatives in JPG format, and I want to train SVM based on these images, I did the following, but I get an error message:

Mat classes = new Mat(); Mat trainingData = new Mat(); Mat trainingImages = new Mat(); Mat trainingLabels = new Mat(); CvSVM clasificador; for (File file : new File(path + "positives/").listFiles()) { Mat img = Highgui.imread(file.getAbsolutePath()); img.reshape(1, 1); trainingImages.push_back(img); trainingLabels.push_back(Mat.ones(new Size(1, 1), CvType.CV_32FC1)); } for (File file : new File(path + "negatives/").listFiles()) { Mat img = Highgui.imread(file.getAbsolutePath()); img.reshape(1, 1); trainingImages.push_back(img); trainingLabels.push_back(Mat.zeros(new Size(1, 1), CvType.CV_32FC1)); } trainingImages.copyTo(trainingData); trainingData.convertTo(trainingData, CvType.CV_32FC1); trainingLabels.copyTo(classes); CvSVMParams params = new CvSVMParams(); params.set_kernel_type(CvSVM.LINEAR); clasificador = new CvSVM(trainingData, classes, new Mat(), new Mat(), params); 

When I try to run, I get:

 OpenCV Error: Bad argument (train data must be floating-point matrix) in cvCheckTrainData, file ..\..\..\src\opencv\modules\ml\src\inner_functions.cpp, line 857 Exception in thread "main" CvException [org.opencv.core.CvException: ..\..\..\src\opencv\modules\ml\src\inner_functions.cpp:857: error: (-5) train data must be floating-point matrix in function cvCheckTrainData ] at org.opencv.ml.CvSVM.CvSVM_1(Native Method) at org.opencv.ml.CvSVM.<init>(CvSVM.java:80) 

I can’t train SVM, any idea? Thanks

+6
source share
2 answers

Assuming that you know what you are doing by modifying the image and using it to train your SVM, the most likely reason for this is that your

 Mat img = Highgui.imread(file.getAbsolutePath()); 

failed to read the image, creating an img matrix with the null data property, which ultimately will cause the following in OpenCV code:

 // check parameter types and sizes if( !CV_IS_MAT(train_data) || CV_MAT_TYPE(train_data->type) != CV_32FC1 ) CV_ERROR( CV_StsBadArg, "train data must be floating-point matrix" ); 

Basically, train_data does not satisfy the first condition (which is a valid matrix), and not the rejection of the second condition (of type CV_32FC1).

In addition, although a change to the *this object is performed, it acts like a filter and its effect is not permanent. If it is used in one statement without immediate use or assignment of another variable, it will be useless. Change the following lines in your code:

 img.reshape(1, 1); trainingImages.push_back(img); 

in

 trainingImages.push_back(img.reshape(1, 1)); 
+11
source

Just as the error says, you need to change the type of your matrix, from an integer type, possibly CV_8U, to a floating point one, CV_32F or CV_64F. For this you can use cv::Mat::convertTo() . Here is a little about the depths and types of matrices.

0
source

Source: https://habr.com/ru/post/946327/


All Articles