how to Use KNN for OCR [closed]

asked 2017-05-29 10:53:04 -0600

Tomna gravatar image

updated 2017-05-30 05:38:53 -0600

so iv had this question every where and no answers are provided i am trying to recognize a digit (image)

image description

and the training data set is

image description

the result is 35 from the KNN.findNearest so my question is what does this number mean or how could i use it to say that the input data is equal to ٢

here is my code

        void run() throws IOException {
            String PATH_numbers = "/home/tomna/NetBeansProjects/Parking-tracking-system/src/mainclass/chdataset/Numb";
            Mat img = Imgcodecs.imread("/home/tomna/NetBeansProjects/Parking-tracking-system/src/mainclass/characters/6.jpg");
            Mat trainingData = new Mat();
            Mat trainingLabels = new Mat();


             int i=1;
             int j=1;
            for (File file : new File(PATH_numbers).listFiles()) {
                Mat image = getMat(file.getAbsolutePath());

                image.convertTo(image, CvType.CV_32F); // Convert to float
                Imgproc.resize(image, image, new Size(74, 60));
                Mat imgresized = image.reshape(1, 1); // make continous
                trainingData.push_back(imgresized);
                trainingLabels.push_back(new Mat(1, 1, CvType.CV_32SC1, new Scalar(i)));
                 if(j%5==0){
                 i++;
                      }
                    j++;
            }

            Mat response = new Mat();
            Mat tmp;
            tmp = trainingLabels.reshape(1, 1); // make continuous
            tmp.convertTo(response, CvType.CV_32F); // Convert to float
            KNearest knn = KNearest.create();
            knn.train(trainingData, Ml.ROW_SAMPLE, tmp);
            System.out.println(tmp.dump());

            Mat test = new Mat();
            Imgproc.cvtColor(img, test, Imgproc.COLOR_RGB2GRAY);
            Imgproc.resize(test, test, new Size(74, 60));
            test.convertTo(test, CvType.CV_32F);
            Mat results = new Mat();

            int label = (int) knn.findNearest(test.reshape(1, 1), 1, results);
            System.out.println(label);

/// this part is an old part when i had only two images for each digit so i thought that the output correspond to number of images (trainingdata) ex if label if 1 means that the nearest neighbor is from image 1.. not sure  
    //        if(label==1||label==2){
    //            System.out.println("٠");
    //        }else if(label==3||label==4){
    //             System.out.println("١");
    //        }else if(label==4||label==5){
    //             System.out.println("٢");
    //        }else if(label==6||label==7){
    //             System.out.println("٣");
    //        }else if(label==8||label==9){
    //             System.out.println("٤");
    //        }else if(label==10||label==11){
    //             System.out.println("٥");
    //        }else if(label==12||label==13){
    //             System.out.println("٦");
    //        }else if(label==14||label==15){
    //             System.out.println("٧");
    //        }else if(label==16||label==17){
    //             System.out.println("٨");
    //        }else if(label==18||label==19){
    //             System.out.println("٩");
    //        }else{
    //            System.out.println("Sorry");
    //        }


        }

edit after using moment and hue moment with findcontours there will be sure some code wrong or logically wrong but i am new to this so bare with me and point it out. the output is always 1 no matter what the input user image is

here is the code

void run() throws IOException { String PATH_numbers = "/home/tomna/NetBeansProjects/Parking-tracking-system/src/mainclass/chdataset/Numb"; Mat img = Imgcodecs.imread("/home/tomna/NetBeansProjects/Parking-tracking-system/src/mainclass/characters/4.jpg"); Mat trainingData = new Mat(); Mat trainingLabels = new Mat();

for (File file : new File(PATH_numbers).listFiles()) {
    Mat image = getMat(file.getAbsolutePath());


    Imgproc.resize(image, image, new Size(74, 60));
    List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
    Imgproc.findContours(image, contours ...
(more)
edit retag flag offensive reopen merge delete

Closed for the following reason question is not relevant or outdated by sturkmen
close date 2020-10-14 13:15:51.470444

Comments

@berak is this question wrong or hard to answer ?

Tomna gravatar imageTomna ( 2017-05-29 11:05:20 -0600 )edit

@LBerger i am new to all of this so if i did {new Scalar(1)" this will output only one label for all images so i guess putting every image in a label would fix this issue not sure. and yes all pixels in all the trainingdata is resized to 74*60 and the input image is also resized but not sure what do u mean by giving all pixel values as data

Tomna gravatar imageTomna ( 2017-05-29 12:34:38 -0600 )edit

for the labels i think it should look like this but dont now how to implement 1,1,1,1,1,2,2,2,2,2,...9,9,9,9,9

Tomna gravatar imageTomna ( 2017-05-29 12:36:01 -0600 )edit

@LBerger i made an edit now the output of the labels are as follow [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9] which means first 5 images have the same feature which means they will be assigned the same label

Tomna gravatar imageTomna ( 2017-05-29 14:00:35 -0600 )edit

Hue moment is not good idea because letter 35 and 36 are equal. Try moment and hue moment. you must have contour letter

LBerger gravatar imageLBerger ( 2017-05-29 15:58:41 -0600 )edit

@LBerger i tried the hue moment and an error happened here is the code

    Mat image = getMat(file.getAbsolutePath());
    image.convertTo(image, CvType.CV_32F); // Convert to float
    Moments mom = new Moments();
    mom = Imgproc.moments(image, false);

    Mat hu = new Mat();
    Imgproc.HuMoments(mom, hu);
    hu = hu.reshape(1, 1);
    Imgproc.resize(hu, hu, new Size(74, 60));
    trainingData.push_back(hu);
    trainingLabels.push_back(new Mat(1, 1, CvType.CV_32SC1, new Scalar(1)));

 the error is

OpenCV Error: Assertion failed (samples.type() == CV_32F || samples.type() == CV_32S) in setData,
Tomna gravatar imageTomna ( 2017-05-29 16:10:55 -0600 )edit

@LBerger sorry man but the letter_recogn its hard to understand anything from it like 5 contributors its hard to trace anything soo i am gonna edit my question and hope you have an explanation to the error i am getting using moment and hue moment

Tomna gravatar imageTomna ( 2017-05-30 04:29:23 -0600 )edit

@berak anything ?

Tomna gravatar imageTomna ( 2017-05-30 04:36:30 -0600 )edit

i/5+1 would make nice labels (starting from 1)

also, hu-moments are just 7 numbers, and don't make nice features for classification, usually.

oh, your resize() is the wrong way (you want vertical Rects, not hoizontal)

and yea, read grayscale images, the color is irrelevant here, no ?

also, do some processing, normalization, maybe deskew

berak gravatar imageberak ( 2017-05-30 08:38:14 -0600 )edit

@berak do you mean i use the code before the edit but the i/5+1 where will this be exactly

Tomna gravatar imageTomna ( 2017-05-30 08:45:39 -0600 )edit

oh, sorry, :

 int nImagesPerClass = 5;
 int id = 1 + (i / nImagesPerClass);
 trainingLabels.push_back(new Mat(1, 1, CvType.CV_32SC1, new Scalar(id)));
berak gravatar imageberak ( 2017-05-30 08:53:00 -0600 )edit

@berak so the training label will be something like this [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9] and after changing this to this for both the training images and test image

 Imgproc.resize(image, image, new Size(74, 60));
Imgproc.resize(image, image, new Size(60, 74));

now what processing could be done ?

Tomna gravatar imageTomna ( 2017-05-30 09:13:43 -0600 )edit

Just in general, why would one still use KNN for OCR classification. Simple networks like LeNet are available in every deep learning package and perform WAY better. Take a look at those in my opinion.

StevenPuttemans gravatar imageStevenPuttemans ( 2017-05-31 04:24:35 -0600 )edit

A great example of the difference in performance: http://christopher5106.github.io/comp...

StevenPuttemans gravatar imageStevenPuttemans ( 2017-05-31 04:25:56 -0600 )edit

@StevenPuttemans do you have any links on how to implement it using java and opencv lib ?

Tomna gravatar imageTomna ( 2017-05-31 06:08:29 -0600 )edit

Euhm wait, not sure if LeNet is supported in OpenCV, let alone java. But as I said, any major deep learning framework like caffe, tensorflow, ... support this!

StevenPuttemans gravatar imageStevenPuttemans ( 2017-05-31 06:12:03 -0600 )edit

@StevenPuttemans ya i know but i need to implement this using opencv so ya this is why i am using neural network ANN_MLP now

Tomna gravatar imageTomna ( 2017-05-31 06:22:02 -0600 )edit