Help loading and testing a trained svm [closed]
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:
is it a row/col problem ? would
fix it ?
no, it still gives me the same error
Would it be easier to use hog.setSvmDetector() to detect digits?
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
detection != classification
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.
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
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?
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)
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