Help loading and testing a trained svm

asked 2018-05-12 14:29:33 -0500

9261 gravatar image

updated 2018-05-12 15:42:28 -0500

I have been attempting to make an SVM for the dataset of handwritten digits that comes with openCV (samples/data/digits.png). I used the code from this source in order to train the svm, but I am having difficulty using the file it produces in java. When I try to use svm.predict(), it gives me this error:

"Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\ml\src\svm.cpp, line 2005"

I think this might have something to do with the format of my data, but I have no experience with this type of thing and could really use some help figuring it out. I am using Intelij 2017 community edition on windows 7 64 bit, with openCV 3.4.0. Here is my code:

private static double SZ = 20;
public static void main(String args[]) {
    SVM svm = SVM.load("C:\\Users\\User\\Desktop\\svm\\svm_data.dat");
    Mat image = Imgcodecs.imread("C:\\Users\\User\\Desktop\\svm\\1.jpg",Imgcodecs.IMREAD_GRAYSCALE);
    Core.bitwise_not(image,image); //makes the dark pencil lines white and the paper background black
    Imgproc.resize(image,image,new Size(20,20));
    Mat deskewed = deskew(image);

    HOGDescriptor hog = new HOGDescriptor(new Size(20,20),new Size(10,10), new Size(5,5), new Size(10,10),16,1,-1,0,0.2,true,64,true);

    MatOfFloat descriptors = new MatOfFloat();
    hog.compute(deskewed,descriptors);
    System.out.println(svm.predict(descriptors));
}

private static Mat deskew(Mat img) {
    Mat deskewed = new Mat();

    Moments m = Imgproc.moments(img);
    if(Math.abs(m.m02) < 1e-2) {
        return img.clone();
    }
    double skew = (float) m.mu11/m.mu02;
    Mat M = Mat.zeros(2,3, CvType.CV_32F);
    M.put(0,0, new float[] {1});
    M.put(0,1, new float[] {(float) skew});
    M.put(0,2, new float[] {(float) (-0.5*SZ*skew)});
    M.put(1,0, new float[] {0});
    M.put(1,1, new float[] {1});
    M.put(1,2, new float[] {0});
    System.out.println(M.dump());
    System.out.println(skew);
    Imgproc.warpAffine(img,deskewed,M,new Size(SZ,SZ),Imgproc.WARP_INVERSE_MAP | Imgproc.INTER_LINEAR);
    return deskewed;
}

and here is the image I am running the svm on:

image description

edit retag flag offensive close merge delete

Comments

is it a row/col problem ? would

svm.predict(descriptors.reshape(1,1))

fix it ?

berak gravatar imageberak ( 2018-05-12 17:52:24 -0500 )edit

no, it still gives me the same error

9261 gravatar image9261 ( 2018-05-12 18:22:07 -0500 )edit

Would it be easier to use hog.setSvmDetector() to detect digits?

9261 gravatar image9261 ( 2018-05-12 18:54:22 -0500 )edit

I found the problem but I don't really know how to fix it. When I trained it with the python code, it used a descriptor size of 1x64 for 16 bins, but the hogDescriptor class uses a descriptor of 1x144 for 16 bins, so var_count (64) != descriptor.cols

9261 gravatar image9261 ( 2018-05-12 20:52:08 -0500 )edit

detection != classification

berak gravatar imageberak ( 2018-05-12 20:54:35 -0500 )edit
1

I confirmed that it was the discrepancy in descriptor sizes that is causing the problem. I changed the winSize variable to 15x15 to make it have a descriptor size of 1x64, and it runs without errors now, but it is now returning 7 for every test image I give it. Also, I am trying to classify the digits, sorry if I made that unclear with my last comment.

9261 gravatar image9261 ( 2018-05-12 21:15:10 -0500 )edit

I tested the hog descriptor outputs from the python code and java code and they were different, which is probably why the svm keeps returning 7

9261 gravatar image9261 ( 2018-05-13 00:26:38 -0500 )edit

Also, while looking at the digits.py example, I noticed that the first number returned by svm.predict was always 0, but the second value, the numpy array, contained the correct prediction. Is this a bug and if not could this be relevant to the issue I've been having?

9261 gravatar image9261 ( 2018-05-13 04:21:01 -0500 )edit

that's easy to explain: if you predict with more than one sample, it obviously will return one result per sample in the results array. (you can't return a single number for many predictions)

berak gravatar imageberak ( 2018-05-13 05:01:34 -0500 )edit

Sorry I meant this is happening when I run predict on one sample. It always returns the same number no matter what sample I give it

9261 gravatar image9261 ( 2018-05-13 14:02:08 -0500 )edit