Using OpenCV and SVM with Images

I'm having difficulty reading an image, retrieving training functions, and testing new images in OpenCV using SVM. can someone please indicate me a great link? I reviewed OpenCV Introduction to Vector Machine Support . But this does not help when reading images, and I'm not sure how to turn it on.




Thanks so much for the explanation. My goals are to classify the pixels in the image. These pixels will belong to the curves. I understand the formation of the training matrix (for example, the image A 1.1 1.2 1.3 1.4 1.5 2.1 2.2 2.3 2.4 2.5 3.1 3.2 3.3 3 , 4 3.5

I would form my training matrix as [3] [2] = {{1,1} {1,2} {1,3} {1,4} {1,5} {2,1} .. {}}

However, I'm a little confused about the shortcuts. In my opinion, I should indicate which row (image) in the learning matrix matches, which corresponds to a curve or not a curve. But how can I outline a row (figure) of the training matrix if there are some pixels that belong to the curve, and some of them do not belong to the curve. For example, my learning matrix is ​​[3] [2] = {{1,1} {1,2} {1,3} {1,4} {1,5} {2,1} .. {}}, pixels {1,1} and {1,4} belong to the curve, and the rest do not.

Thank you very much -

+54
c ++ opencv svm
Feb 04 '13 at 8:15
source share
1 answer

I had to deal with this recently, and here is what I eventually did to get SVM to work with images.

To train your SVM in a set of images, you first need to build a training matrix for SVM. This matrix is ​​defined as follows: each row of the matrix corresponds to one image, and each element in this row corresponds to one class function - in this case, the pixel color at a certain point. Since your images are 2D, you need to convert them to a 1D matrix. The length of each line will be the image area (note that the images must be the same size).

Suppose you wanted to train SVM on 5 different images, and each image was 4x3 pixels. First you will need to initialize the learning matrix. The number of rows in the matrix is ​​5, and the number of columns will be the image area, 4 * 3 = 12.

int num_files = 5; int img_area = 4*3; Mat training_mat(num_files,img_area,CV_32FC1); 

Ideally, num_files and img_area will not be hardcoded, but obtained from a loop through a directory and counting the number of images and taking the actual image area.

The next step is to “populate” the training_mat lines with data from each image. The following is an example of how this mapping will work for a single line.

Convert 2D image matrix to 1D matrix

I numbered each element of the image matrix, where it should go on the corresponding line in the training matrix. For example, if it was the third image, it will be the third row in the training matrix.

You will need to scroll through each image and set the value in the output matrix accordingly. Here is an example for several images:

Training matrix with multiple images

As for how you do this in code, you can use reshape() , but I had problems with this due to the lack of matrix continuity. In my experience, I did something like this:

 Mat img_mat = imread(imgname,0); // I used 0 for greyscale int ii = 0; // Current column in training_mat 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); } } 

Do this for each training image (remember the file_num increment). After that, you must properly configure your training matrix in order to switch to SVM functions. The rest of the steps should be very similar to the online examples.

Please note that in doing so, you also need to set labels for each training image. For example, if you have classified the eyes and eyes from the image, you need to indicate which row in the training matrix corresponds to the eye and the eye. This is defined as a 1D matrix, where each element in the 1D matrix corresponds to each row in the 2D matrix. Select values ​​for each class (for example, -1 for the non-eye and 1 for the eyes) and set them in the label matrix.

 Mat labels(num_files,1,CV_32FC1); 

So, if the 3rd element in this matrix of labels is -1, this means that the 3rd row in the training matrix is ​​in the “non-eye” class. You can set these values ​​in a loop where you evaluate each image. One thing you can do is sort the training data into separate directories for each class and cycle through the images in each directory and set labels based on the directory.

The next thing to do is configure the SVM settings. These values ​​will depend on your project, but basically you will declare a CvSVMParams object and set the values:

 CvSVMParams params; params.svm_type = CvSVM::C_SVC; params.kernel_type = CvSVM::POLY; params.gamma = 3; // ...etc 

There are several online examples on how to set these parameters, for example, in the link published in the question.

Then you create a CvSVM object and CvSVM it based on your data!

 CvSVM svm; svm.train(training_mat, labels, Mat(), Mat(), params); 

Depending on how much data you have, this can take a long time. However, after training, you can save your prepared SVM so you don't have to retrain it every time.

 svm.save("svm_filename"); // saving svm.load("svm_filename"); // loading 

To test your images using trained SVM, just read the image, convert it to a 1D matrix and pass it to svm.predict() :

 svm.predict(img_mat_1d); 

It will return a value based on what you set as your labels (e.g. -1 or 1, based on my eye / non-eye example above). Alternatively, if you want to test several images at a time, you can create a matrix that has the same format as the previously developed training matrix and pass it as an argument. The return value will be different.

Good luck

+198
Feb 04
source share



All Articles