使用OpenCV和SVM与图像 [英] using OpenCV and SVM with images

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

问题描述

我无法读取图片,提取训练的功能,以及使用SVM在OpenCV中测试新图片。有人可以请我指出一个伟大的链接?我查看了,但我有问题,由于矩阵不连续。在我的经验,我做了这样的:

  Mat img_mat = imread(imgname,0); //我为灰度使用0 
int ii = 0; //当前列in training_mat
for(int i = 0; i for(int j = 0; j training_mat.at< float>(file_num,ii ++)= img_mat.at< uchar>(i,j)
}
}

对每个训练图像执行此操作(记住增加 file_num )。此后,您应该正确设置训练矩阵以传递到SVM函数。其余步骤应与在线示例非常相似。



请注意,在执行此操作时,还必须为每个训练图像设置标签。因此,例如,如果您基于图像对眼睛和非眼睛进行分类,则需要指定训练矩阵中对应于眼睛和非眼睛的哪一行。这被指定为1D矩阵,其中1D矩阵中的每个元素对应于2D矩阵中的每一行。选择每个类的值(例如,非眼睛为-1,眼睛为1),并将其设置在标签矩阵中。

  Mat标签(num_files,1,CV_32FC1);因此,如果这个标签中的第三个元素 
 

矩阵为-1,则意味着训练矩阵中的第三行在非眼类中。您可以在评估每个图像的循环中设置这些值。您可以做的一件事是将训练数据分类到每个类的单独目录,并循环通过每个目录中的图像,并根据目录设置标签。



接下来要做的是设置SVM参数。这些值将根据您的项目而变化,但基本上您将声明一个 CvSVMParams 对象并设置值:

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

有几个在线示例如何设置这些参数



接下来,您创建一个 CvSVM 对象,然后根据对您的数据!

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

根据您有多少数据,这可能需要很长时间。但是,在完成培训后,您可以保存经过训练的SVM,以便您不必每次都重新训练。

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

要使用训练的SVM测试图像,只需读取图像, 1D矩阵,并将其传递给 svm.predict()

  svm.predict(img_mat_1d); 

它将返回一个基于您设置为标签的值(例如,-1或1,基于我的眼睛/非眼睛例子上面)。或者,如果要一次测试多个图像,则可以创建一个与前面定义的训练矩阵格式相同的矩阵,并将其作为参数传递。



祝你好运!


I am having difficulty with reading an image, extracting features for training, and testing on new images in OpenCV using SVMs. can someone please point me to a great link? I have looked at the OpenCV Introduction to Support Vector Machines. But it doesn't help with reading in images, and I am not sure how to incorporate it.


Thanks so much for the explanation. My goals are to classify pixels in an image. These pixel would belong to a curves. I understand forming the training matrix (for instance, 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 a [3][2]={ {1,1} {1,2} {1,3} {1,4} {1,5} {2,1} ..{} }

However, I am a little confuse about the labels. From my understanding, I have to specify which row (image) in the training matrix corresponds, which corresponds to a curve or non-curve. But, how can I label a training matrix row (image) if there are some pixels belonging to the curve and some not belonging to a curve. For example, my training 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 but the rest does not.

Thanks a lot -

解决方案

I've had to deal with this recently, and here's what I ended up doing to get SVM to work for images.

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

Let's say you wanted to train the SVM on 5 different images, and each image was 4x3 pixels. First you would have to 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, 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 wouldn't be hardcoded, but obtained from looping through a directory and counting the number of images and taking the actual area of an image.

The next step is to "fill in" the rows of training_mat with the data from each image. Below is an example of how this mapping would work for one row.

I've numbered each element of the image matrix with where it should go in the corresponding row in the training matrix. For example, if that were the third image, this would be the third row in the training matrix.

You would have to loop through each image and set the value in the output matrix accordingly. Here's an example for multiple images:

As for how you would do this in code, you could use reshape(), but I've had issues with that due to matrices not being continuous. In my experience I've done 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 every training image (remembering to increment file_num). After this, you should have your training matrix set up properly to pass into the SVM functions. The rest of the steps should be very similar to examples online.

Note that while doing this, you also have to set up labels for each training image. So for example if you were classifying eyes and non-eyes based on images, you would need to specify which row in the training matrix corresponds to an eye and a non-eye. This is specified as a 1D matrix, where each element in the 1D matrix corresponds to each row in the 2D matrix. Pick values for each class (e.g., -1 for non-eye and 1 for eye) and set them in the labels matrix.

Mat labels(num_files,1,CV_32FC1);

So if the 3rd element in this labels matrix were -1, it means the 3rd row in the training matrix is in the "non-eye" class. You can set these values in the loop where you evaluate each image. One thing you could do is to sort the training data into separate directories for each class, and loop through the images in each directory, and set the labels based on the directory.

The next thing to do is set up your SVM parameters. These values will vary based on your project, but basically you would 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 examples online on how to set these parameters, like in the link you posted in the question.

Next, you create a CvSVM object and train it based on your data!

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

Depending on how much data you have, this could take a long time. After it's done training, however, you can save the trained 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 the trained SVM, simply read an image, convert it to a 1D matrix, and pass that in 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 more than one image at a time, you can create a matrix that has the same format as the training matrix defined earlier and pass that in as the argument. The return value will be different, though.

Good luck!

这篇关于使用OpenCV和SVM与图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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