Ask Your Question
0

KNearest Java Assertion Error

asked 2018-02-23 09:07:56 -0500

Jérémy K gravatar image

updated 2018-02-27 05:03:56 -0500

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:

image description

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());
    }
edit retag flag offensive close merge delete

Comments

1

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 ?

berak gravatar imageberak ( 2018-02-24 01:55:55 -0500 )edit

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.

Jérémy K gravatar imageJérémy K ( 2018-02-24 04:45:49 -0500 )edit

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 !)

berak gravatar imageberak ( 2018-02-24 04:49:23 -0500 )edit

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 with Mat one_feature = Imgcodecs.imread("/Users/jeremyk/Desktop/output/digits/digit0.png", 0);. After that this image is loaded, it's now resized with Imgproc.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 :(

Jérémy K gravatar imageJérémy K ( 2018-02-24 04:59:24 -0500 )edit

0 == IMREAD_GRAYSCALE

so, apply same flag when reading your test img

berak gravatar imageberak ( 2018-02-24 05:00:48 -0500 )edit

Hi berak, I am already doing this! This is the Mat one_feature = Imgcodecs.imread("/Users/jeremyk/Desktop/output/digits/digit0.png", 0).

Jérémy K gravatar imageJérémy K ( 2018-02-24 05:03:54 -0500 )edit

"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 ;(

berak gravatar imageberak ( 2018-02-24 05:52:53 -0500 )edit

I included the training/testing code that I'm using! :)

Jérémy K gravatar imageJérémy K ( 2018-02-24 06:08:20 -0500 )edit

btw:

I'm writing some software to read energy meters

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.

berak gravatar imageberak ( 2018-02-24 06:41:02 -0500 )edit

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..

Jérémy K gravatar imageJérémy K ( 2018-02-27 05:05:14 -0500 )edit

1 answer

Sort by » oldest newest most voted
1

answered 2018-02-27 06:19:18 -0500

Jérémy K gravatar image

updated 2018-02-27 07:02:59 -0500

The solution for this issue can be split in multiple attention points:

  1. Make sure that you have appropriate training images for the image(s) you're testing on.
  2. Make sure that the training images are the same size as the image(s) you're testing on.
  3. Make sure that your importing the images in the same format. Tip: to get more information on your image, use [Your mat object].toString() and see if the type and size of your training images equals the type and size of your testing image(s).

Special thanks to berak for helping me out and getting me in the right direction for solving this issue!

edit flag offensive delete link more

Comments

so happy you solved it ;)

berak gravatar imageberak ( 2018-02-27 06:24:06 -0500 )edit

Thanks! I love it now and I'm really impressed by the accuracy. Used only 1 training image per digit and it does already a perfect job! Many thanks to the OpenCV community for keeping up a project like this.

Jérémy K gravatar imageJérémy K ( 2018-02-27 06:32:40 -0500 )edit
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2018-02-23 09:07:56 -0500

Seen: 537 times

Last updated: Feb 27 '18