KNearest Java Assertion Error[SOLVED]
I'm still new to OpenCV, but already learned a lot. I am however stuck on the K-NN Algorithm. I'm writing some software to read energy meters and I already succesfully wrote the image processing part. When the processing is finished, I end up with digits like this:
For the K-NN part (training and etc), I used almost all code from this OpenCV question. However, when running the following code (and doing the nescessary training in advance):
Mat one_feature = Imgcodecs.imread("/Users/jeremyk/Desktop/output/digits/digit0.png", 0);
Imgproc.resize(one_feature, one_feature, new Size(20, 20));
Mat res = new Mat();
one_feature.convertTo(one_feature, CvType.CV_32F);
one_feature.reshape(1,1);
float p = knn.findNearest(one_feature, 1, res);
I'm getting this nasty error:
OpenCV Error: Assertion failed (test_samples.type() == 5 && test_samples.cols == samples.cols) in cv::ml::BruteForceImpl::findNearest, file C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\ml\src\knearest.cpp, line 325
Exception in thread "main" CvException [org.opencv.core.CvException: cv::Exception: C:\build\master_winpack-bindings-win64-vc14-static\opencv\modules\ml\src\knearest.cpp:325: error: (-215) test_samples.type() == 5 && test_samples.cols == samples.cols in function cv::ml::BruteForceImpl::findNearest]
I can't seem to find any solution to this.. Anyone got a clue?
Thanks in advance!
Edit: import as grayscale and resize image added to one_feature in an attempt to solve the error.
Edit 2: Here's the training/testing code that I'm using
Edit 3: Here's the updated training/test code that I'm using
for (int c = 0; c< numberOfTrainingDigits; c++) {
// crop out 1 digit:
digit = Imgcodecs.imread("/Users/jeremyk/Desktop/training/digit" + c + ".png");
Mat num = new Mat();
Imgproc.resize(digit, num, new Size(60, 110));
// we need float data for knn:
num.convertTo(num, CvType.CV_32F);
// for opencv ml, each feature has to be a single row:
trainData.push_back(num.reshape(1,1));
trainLabs.add(c);
}
// Add test image
Mat testDigit = Imgcodecs.imread("/Users/jeremyk/Desktop/testdigit.png", 0);
Mat num = new Mat();
Imgproc.resize(testDigit, num, new Size(60, 110));
// we need float data for knn:
num.convertTo(num, CvType.CV_32F);
testData.push_back(num.reshape(1,1));
testLabs.add(6);
// make a Mat of the train labels, and train knn:
KNearest knn = KNearest.create();
knn.train(trainData, Ml.ROW_SAMPLE, Converters.vector_int_to_Mat(trainLabs));
// now test predictions:
for (int j=0; j<testData.rows(); j++)
{
Mat one_feature = testData.row(j);
int testLabel = testLabs.get(j);
Mat res = new Mat();
float p = knn.findNearest(one_feature, 1, res);
System.out.println(testLabel + " " + p + " " + res.dump());
}
the size of your test image did not match the size of your training images.
also, you load a 3channel, color image. did you train with grayscale ?
Hi berak, thank you very much for your answer! The training images are indeed not the same size as the image I'm testing on. Sorry, I didn't know that this had to be this way. Thanks for this. I changed it, but I still receive the same error. I looked into the grayscale, I'm using this training image for the training, so not sure if this one is already in grayscale.
have a look, on how you loaded the train img. was it with IMREAD_GRAYSCALE ?
use same flags for train / test images !
the digits.png uses 20x20 images for training, so you have to resize your test img to the same
(not to the size of digits.png, but to the size of a single digit in there !)
Hi berak, thanks for your quick response. The training image gets loaded with
Mat digits = Imgcodecs.imread("/Users/jeremyk/Desktop/digits.png", 0);
. The single digit I want to try KNearest on is loaded withMat one_feature = Imgcodecs.imread("/Users/jeremyk/Desktop/output/digits/digit0.png", 0);
. After that this image is loaded, it's now resized withImgproc.resize(one_feature, one_feature, new Size(20, 20));
to match the size of the single digits of the training image. Still getting the error however :(0 == IMREAD_GRAYSCALE
so, apply same flag when reading your test img
Hi berak, I am already doing this! This is the
Mat one_feature = Imgcodecs.imread("/Users/jeremyk/Desktop/output/digits/digit0.png", 0)
."I used almost all code from this OpenCV question" -- well, somehow, you differ. if you can't find out, you have to add your training code, too ;(
I included the training/testing code that I'm using! :)
btw:
then handwritten numbers might be bad training data , just saying. also, you'll have to take care, that your numbers are white on black in this case, exactly as the traindata.
Hello Berak, thanks, I followed your advice and created nice training images with a fixed size. Now I'm trying to test with an image which I'm uploading in an exact same manner as the training images, but it still doesn't work..