Android svm implementation error

asked 2016-05-28 05:06:53 -0600

siline gravatar image

I tried to implement svm in my android application but when i run my application i get errors.

        // Creating Training Data
            Mat trainData = new Mat();
        Mat train_labels = new Mat();


            for (int i = 0; i <549; i++) {
            String path = Environment.getExternalStorageDirectory().toString()
                    + "/Pictures/train/" + i + ".png";

            Mat img = Imgcodecs.imread(path);

            Log.i(TAG,"error"+i+img.empty());

            img.convertTo(img, CvType.CV_32FC1); // Convert to float
            Size dsize = new Size(25, 25);
            Imgproc.resize(img, img, dsize);

            img.convertTo(img, CvType.CV_32FC1);
            Mat imgResized = img.reshape(1, 1); // make continuous

            trainData.push_back(imgResized);
            // add 1 item
            train_labels
                    .push_back(new Mat(1, 1, CvType.CV_32FC1, new Scalar(i)));

        }

        Mat response = new Mat();
        Mat tmp;
        tmp = train_labels.reshape(1, 1); // make continuous
        tmp.convertTo(response, CvType.CV_32FC1); // Convert to float
         SVM svm = SVM.create();
            TermCriteria criteria = new TermCriteria(TermCriteria.EPS + TermCriteria.MAX_ITER,100,0.1);
            svm.setKernel(SVM.LINEAR);
            svm.setType(SVM.C_SVC);
            svm.setGamma(0.5);
            svm.setNu(0.5);
            svm.setC(1);
            svm.setTermCriteria(criteria);
            svm.train(trainData, Ml.ROW_SAMPLE,train_labels);

        // For Storing training data


        File datasetFile = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_DOWNLOADS), "dataset.xml");
        svm.save(datasetFile.getAbsolutePath());

And this is the error:

05-28 11:05:01.921: E/cv::error()(2252): OpenCV Error: Bad argument (in the case of classification problem the responses must be categorical; either specify varType when creating TrainData, or pass integer responses) in virtual bool cv::ml::SVMImpl::train(const cv::Ptr<cv::ml::traindata>&, int), file /home/maksim/workspace/android-pack/opencv/modules/ml/src/svm.cpp, line 1610 05-28 11:05:01.931: E/org.opencv.ml(2252): ml::train_10() caught cv::Exception: /home/maksim/workspace/android-pack/opencv/modules/ml/src/svm.cpp:1610: error: (-5) in the case of classification problem the responses must be categorical; either specify varType when creating TrainData, or pass integer responses in function virtual bool cv::ml::SVMImpl::train(const cv::Ptr<cv::ml::traindata>&, int)

edit retag flag offensive close merge delete

Comments

1

Make labels of type CV_32SC1 instead of CV_32FC1

LorenaGdL gravatar imageLorenaGdL ( 2016-05-28 05:14:03 -0600 )edit

when i change type of label i got this error: 05-28 11:25:30.378: E/cv::error()(9388): OpenCV Error: Insufficient memory (Failed to allocate 1128195000 bytes) in void* cv::OutOfMemoryError(size_t), file /home/maksim/workspace/android-pack/opencv/modules/core/src/alloc.cpp, line 52 05-28 11:25:30.378: E/cv::error()(9388): OpenCV Error: Assertion failed (u != 0) in void cv::Mat::create(int, const int, int), file /home/maksim/workspace/android-pack/opencv/modules/core/src/matrix.cpp, line 411 05-28 11:25:30.388: E/org.opencv.ml(9388): ml::train_10() caught cv::Exception: /home/maksim/workspace/android-pack/opencv/modules/core/src/matrix.cpp:411: error: (-215) u != 0 in function void cv::Mat::create(int, const int, int)

siline gravatar imagesiline ( 2016-05-28 05:26:44 -0600 )edit

That's another problem. Basically, you have not enough memory for training the SVM

LorenaGdL gravatar imageLorenaGdL ( 2016-05-28 05:43:03 -0600 )edit

here:

train_labels.push_back(new Mat(1, 1, CvType.CV_32FC1, new Scalar(i)));

as said before , you need integer, not float labels (and don't convert them later) also you probably don't want i as the class label. this would mean, that you have 549 different classes with 1 train image each only, which is a terrible setup. (and very expensive memory-wise, since the SVM internally tries to split it into one SVM per class)

last, you might want to train your SVM with tons of data on a beefy pc, not your phone ..

berak gravatar imageberak ( 2016-05-28 05:47:14 -0600 )edit

what are you actually trying to classify ?

berak gravatar imageberak ( 2016-05-28 05:57:25 -0600 )edit

In my application i should get images from data base and try to train them using opencv svm .Really i don't understand how to change i and how put my training data in classes

siline gravatar imagesiline ( 2016-05-28 05:57:52 -0600 )edit
1

"Really i don't understand ..." - yes, that's obvious.

again, what is the classification problem ? apples vs pears ? person identification ? what is it ?

berak gravatar imageberak ( 2016-05-28 06:00:54 -0600 )edit

I have to recognize letters in an image .so i try to submat each letter from text extracted from image taken by phone camera and then i shoud recognize each letter (i can't use ocr because image is a latin manuscrit so letters aren't very clear) by refering to svm algorithm for opencv.So if i understand i should create for each letter a class ? but i don't know how

siline gravatar imagesiline ( 2016-05-28 06:07:32 -0600 )edit

yes, each letter is a class,so a==1, b==2, ..etc. and you have to give those class numbers as labels, not i. later, when you try a prediction, you will get exactly those numbers back.

berak gravatar imageberak ( 2016-05-29 02:20:04 -0600 )edit

when t tried to predict labels i got this error: OpenCV Error: Assertion failed (samples.cols == var_count && samples.type() == CV_32F) in virtual float cv::ml::SVMImpl::predict(cv::InputArray, cv::OutputArray, int) for (int i = 0; i < h; i++){

        for (int j=x+1; j < nb.get(i); j++)
        {
            Mat img3 = Imgcodecs.imread("/storage/emulated/0/DCIM/OurText/"+i + j+".png");
            Mat test = new Mat();
            Imgproc.resize(img3, test, new Size(25, 25));
            test.convertTo(test, CvType.CV_32SC1);
            float label = svm.predict(test);
             if (label==1)
            {
                text.setText("A");
            } else if (label==2)  {
                text.setText("C");
            } 
             else if (label==3)  {
                text.setText("D");
            }  


        }
jack1 gravatar imagejack1 ( 2016-05-29 04:13:53 -0600 )edit