purudpd
purudpd

Reputation: 179

Training svm for images in opencv

I have already reffered to the following links: Link 1 and Link 2

From the above i have to managed to write the following :

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/ml/ml.hpp>

using namespace cv;
using namespace std;

int main(){
    int num_files = 2;
    int width = 128, height = 128;

    Mat image[2];
    image[0] = imread("Tomato.jpg");
    image[1] = imread("Melon.jpg");

    Mat new_image(2,height*width,CV_32FC1); //Training sample from input images

    int ii = 0;
    for (int i = 0; i < num_files; i++){
        Mat temp = image[i];
        ii = 0;
        for (int j = 0; j < temp.rows; j++){
            for (int k = 0; k < temp.cols; k++){
                new_image.at<float>(i, ii++) = temp.at<uchar>(j, k);
            }
        }
    }
    //new_image.push_back(image[0].reshape(0, 1));
    //new_image.push_back(image[1].reshape(0, 1));
    Mat labels(num_files, 1, CV_32FC1);
    labels.at<float>(0, 0) = 1.0;//tomato
    labels.at<float>(1, 0) = -1.0;//melon

    imshow("New image", new_image);
    printf("%f %f", labels.at<float>(0, 0), labels.at<float>(1, 0));

    CvSVMParams params;
    params.svm_type = CvSVM::C_SVC;
    params.kernel_type = CvSVM::LINEAR;
    params.gamma = 3;
    params.degree = 3;
    params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
    CvSVM svm;
    svm.train(new_image, labels, Mat(), Mat(), params);

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

    Mat test_img = imread("Tomato.jpg");
    test_img=test_img.reshape(0, 1);
    imshow("shit_image", test_img);
    test_img.convertTo(test_img, CV_32FC1);
    svm.predict(test_img);

    waitKey(0);
}

I get the following error:

unsupported format or combination of formats, input sample must have 32FC1 type in cvPreparePredictData ...

I followed all steps in the second link. All matrices are 32FC1 type. What am I missing? Is there something wrong with the svm parameters ? The error is caused when i try to predict a result.

Upvotes: 1

Views: 3428

Answers (1)

JeongHwan
JeongHwan

Reputation: 11

check

1) Tomato.jpg and Melon.jpg size is 128*128 ?
2) both images are grayscale?

if not. try this code:
I just add resize(), cvtColor() and print result

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/ml/ml.hpp>
#include <opencv2\imgproc\imgproc.hpp>

using namespace cv;
using namespace std;

int main(){
    int num_files = 2;
    int width = 128, height = 128;

    Mat image[2];
    image[0] = imread("Tomato.jpg", 0);
    image[1] = imread("Melon.jpg", 0);

    resize(image[0], image[0], Size(width, height));
    resize(image[1], image[1], Size(width, height));

    Mat new_image(2, height*width, CV_32FC1); //Training sample from input images

    int ii = 0;
    for (int i = 0; i < num_files; i++){
        Mat temp = image[i];
        ii = 0;
        for (int j = 0; j < temp.rows; j++){
            for (int k = 0; k < temp.cols; k++){
                new_image.at<float>(i, ii++) = temp.at<uchar>(j, k);
            }
        }
    }
    //new_image.push_back(image[0].reshape(0, 1));
    //new_image.push_back(image[1].reshape(0, 1));
    Mat labels(num_files, 1, CV_32FC1);
    labels.at<float>(0, 0) = 1.0;//tomato
    labels.at<float>(1, 0) = -1.0;//melon

    imshow("New image", new_image);
    printf("%f %f", labels.at<float>(0, 0), labels.at<float>(1, 0));

    CvSVMParams params;
    params.svm_type = CvSVM::C_SVC;
    params.kernel_type = CvSVM::LINEAR;
    params.gamma = 3;
    params.degree = 3;
    params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
    CvSVM svm;
    svm.train(new_image, labels, Mat(), Mat(), params);

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

    Mat test_img = imread("Tomato.jpg", 0);
    resize(test_img, test_img, Size(width, height));
    test_img = test_img.reshape(0, 1);
    imshow("shit_image", test_img);
    test_img.convertTo(test_img, CV_32FC1);
    float res = svm.predict(test_img);
    if (res > 0)
        cout << endl << "Tomato";
    else
        cout << endl << "Melon";
    waitKey(0);
}

Upvotes: 1

Related Questions