使用图像训练 SVM 并进行预测

Training an SVM with images and making predictions

感谢您的帮助...

我刚才写了一些代码,成功地检测了移动的交通视频中的汽车。因此,让我们考虑该代码的输出和该代码的最终输入是 150x200 大小的车辆图像。

我正在尝试实现的是一个支持向量机,它采用这些车辆并将它们分类为轿车和 SUV。 (假设只有轿车和 SUV)。

以下代码是通过密切关注此 link 上的信息实现的:https://docs.opencv.org/3.0-beta/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html 这个link:using OpenCV and SVM with images

请注意,与这些 link 相关的语法对于我拥有的最新版本的 SVM 上的 SVM 实现来说略微过时了。

    //Used to read multiple files from folder
stringstream ss;
string name = "Vehicle_";
string type = ".jpg";

int num_train_images = 29;      //29 images will be used to train the SVM
int image_area = 150 * 200;
Mat training_mat(num_train_images, image_area, CV_32FC1);   // Creates a 29 rows by 30000 columns... 29 150x200 images will be put into 1 row per image

//Converts 29 2D images into a really long row per image
for (int file_count = 1; file_count < (num_train_images + 1); file_count++) 
{
    ss << name << file_count << type;       //'Vehicle_1.jpg' ... 'Vehicle_2.jpg' ... etc ...
    string filename = ss.str();
    ss.str("");

    Mat training_img = imread(filename, 1);     //Reads the training images from the folder
    int ii = 0;                                 //Scans each column
    for (int i = 0; i < training_img.rows; i++) 
    {
        for (int j = 0; j < training_img.cols; j++)
        {
            training_mat.at<float>(file_count - 1, ii) = training_img.at<uchar>(i, j);  //Fills the training_mat with the read image
            ii++; 
        }
    }
}

//Labels are used as the supervised learning portion of the SVM. If it is a 1, its an SUV test image. -1 means a sedan. 
float labels[29] = { 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1 };

//Place the labels into into a 29 row by 1 column matrix. 
Mat labels_mat(num_train_images, 1, CV_32FC1, labels);

cout << "Beginning Training..." << endl;

//Set SVM Parameters (not sure about these values)
Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::LINEAR);
svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));

svm->train(training_mat, ROW_SAMPLE, labels_mat);

cout << "End Training" << endl;

waitKey(0);

Mat test_image(1, image_area, CV_32FC1);        //Creates a 1 x 30000 matrix to house the test image. 

Mat SUV_image = imread("SUV_1.jpg", 0);         //Read the file folder
int jj = 0;
for (int i = 0; i < SUV_image.rows; i++)
{
    for (int j = 0; j < SUV_image.cols; j++)
    {
        test_image.at<float>(0, jj) = SUV_image.at<uchar>(i, j);    //Fills the training_mat
        jj++;
    }
}

//Should return a 1 if its an SUV, or a -1 if its a sedan
svm->predict(test_image);

waitKey(0);

所以我在这里做的是拍摄测试图像,然后将每个 150 x 200 图像转换为 training_mat 中 1 行 x 30,000 列的行。

labels_mat 是 SVM 的监督学习部分,它判断训练图像是 SUV 还是轿车。

代码构建良好,但不幸的是,当它到达 svm->train 时它失败了,我收到一个中止错误,上面写着:"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"

不太清楚这是什么意思,可能是我的参数有问题。一位朋友建议我可能需要先提取图像的特征,然后才能将其输入 SVM,我不确定是否有必要这样做。

谢谢

已通过将 labels_mat 更改为 CV_32S 为整数类型解决了此问题。不幸的是,一个新问题仍然存在,即 svm->predict(test_image) returns 一个不是 -1 或 1 的大值。