Ask Your Question
0

Color based classification using SVM

asked 2017-06-22 07:07:15 -0600

Nani gravatar image

updated 2017-07-03 03:13:14 -0600

I would like to ask a question about how to use SVM to classify images based on colors:

I have a dataset which contains 15 features extracted using simple image histogram includes mean, stddev, mode, and other statistics accompanied with a label in the same dataset.

How I can proceed from this dataset and how to change it to xml file store and load it in my Android app. Do I need to separate the dataset into training and label data, etcl.

I know there is lots of material in the website but a kind help from you will save my time.

Here the code I developed and I have this error: E/cv::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) const, file /Volumes/Linux/builds/master_pack-android/opencv/modules/ml/src/svm.cpp, line 1930

    int trainingRow = 18;
    int trainingCol = 18;
    Mat trainingDataMat = new Mat(trainingRow, trainingCol, CvType.CV_32FC1);
    int testingRow = 1;
    int testingCol = 18;
    Mat testingDataMat = new Mat(testingRow, testingCol, CvType.CV_32FC1);


    featureVector = "featureVector";
    double[][] trainingList = new double[trainingRow][trainingCol];
    trainingList = readFromFile(featureVector, trainingRow, trainingCol);
    for(int i=0;i<trainingRow;i++){
        for(int j=0;j<trainingCol;j++) {
            Log.i(TAG, "Data of data" + "[" + i + "," + j + "]" + " " + trainingList[i][j]);
            trainingDataMat.put(i, j, trainingList[i][j]);
        }
        v_features.push_back(trainingDataMat.reshape(1,1));
    }

    featureVector = "label";
    int[] labelList = new int[trainingRow];
    labelList = readFromFile1(featureVector);
    for(int i=0;i<trainingRow;i++){
        Log.i(TAG, "Data of label " + "[" + i + "]" + " " + labelList[i]);
        Mat labelsMat = new Mat(1, 1, CvType.CV_32SC1, new Scalar(labelList[i]));
        trainingLabels.push_back(labelsMat);
    }
    Log.i(TAG,"Training...");
    v_features.copyTo(trainingData);
    trainingData.convertTo(trainingData, CvType.CV_32F);
    trainingLabels.copyTo(classes);
    classes.convertTo(classes, CvType.CV_32S);
    classifier.setType(SVM.C_SVC);
    classifier.setKernel(SVM.LINEAR);
    classifier.setGamma(0.5);
    classifier.setNu(0.5);
    classifier.setC(1);
    TermCriteria criteria = new TermCriteria(TermCriteria.EPS + TermCriteria.MAX_ITER,100,0.1);
    classifier.setTermCriteria(criteria);

    classifier.train(trainingData, Ml.ROW_SAMPLE, classes);

    Log.i(TAG,"Done Training");

    Log.i(TAG,"Testing...");

    featureVector = "testVector";
    double[][] testingList = new double[testingRow][testingCol];
    testingList = readFromFile(featureVector, testingRow, testingCol);
    for(int i=0;i<testingRow;i++) {
        for (int j = 0; j < testingCol; j++) {
            Log.i(TAG, "Data of test" + "[" + i + "," + j + "]" + " " + testingList[i][j]);
            testingDataMat.put(i, j, testingList[i][j]);
        }
        vt_features.push_back(testingDataMat.reshape(1, 1));
    }

    vt_features.copyTo(testingData);
    testingData.convertTo(testingData, CvType.CV_32F);

    Log.i(TAG, "classification result" + classifier.predict(testingData));
edit retag flag offensive close merge delete

Comments

save our time, too, please.

show us, what you tried, so far, so we don't have to start from 0

berak gravatar imageberak ( 2017-06-22 08:59:20 -0600 )edit

Thanks for your help. So far I segmented an image and i calculated mean, mode, stddev, energy, and entropy and create a dataset. Now i would like to use SVM to train the data and afterward predict the correct classification using my Android app

Nani gravatar imageNani ( 2017-06-22 09:31:34 -0600 )edit

here is a rough outline for hog features. try something, and come back, if you run into trouble.

berak gravatar imageberak ( 2017-06-22 09:57:39 -0600 )edit

@berak Thank for the link. I followed exctaly what in the link but I countered a problem in the line v_descriptors.push_back(descriptorsValues.reshape(1, 1)); I think the reshape function did not work for me and I delete it then I countered a problem with the line classifier.train(trainingData, Ml.ROW_SAMPLE, classes); I really need suggestion on that.

Nani gravatar imageNani ( 2017-06-29 04:07:07 -0600 )edit

you your features have to be a single row matrix, so if it's an image, or a column vector, you need to reshape(1,1) your images, for both training and testing. (each row in the trainData is supposed to be 1 sample)

what went wrong ? how do you put your features into a Mat ?

berak gravatar imageberak ( 2017-06-29 04:21:31 -0600 )edit

I put the segmented images in the path String PATH_POSITIVE = "/mnt/sdcard/Data_Set/Postive_Img"; and then use just HOGDescriptor to extract the features. Is that right or I need to add my features that I extracted (I extracted 18 features from the image which in double values). The app stop working at this point when reshaping the descriptor produced by the HOG.

Nani gravatar imageNani ( 2017-06-29 04:43:17 -0600 )edit

can we focus on the data, you get from your textfile, for now ? (see answer below)

if that works out, we can expand it to use HOG features instead, but possibly in a follow-up question.

berak gravatar imageberak ( 2017-06-30 06:35:13 -0600 )edit

@Nani, any updates / new problems there ? i cannot see anything.

berak gravatar imageberak ( 2017-07-03 03:31:07 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2017-06-30 06:33:53 -0600

berak gravatar image

updated 2017-06-30 06:45:53 -0600

the way you setup your train data looks broken.

look here:

trainingDataMat.put(i, j, trainingList[i][j]); // trainingDataMat is where ?

in the 1st run, you have 18 features, so you pushback a row of 18 here:

v_features.push_back(trainingDataMat.reshape(1,1));

but in the 2nd run, since you reuse trainingDataMat , you already got 36 cols, if you reshape it, and it gets longer and longer....

i think, you should do like this instead(same problem for your testing data!):

trainingList = readFromFile(featureVector, trainingRow, trainingCol);
for(int i=0; i<trainingRow; i++){
   Mat a_row = new Mat(1, trainingCol, CV_32F); // a **local** Mat w. correct size and type 
   for(int j=0; j<trainingCol; j++) {
        Log.i(TAG, "Data of data" + "[" + i + "," + j + "]" + " " + trainingList[i][j]);
        a_row.put(i, j, trainingList[i][j]);
    }
    v_features.push_back(a_row); // no need to reshape, it's already a row.
}

final checklist:

  • train labels need to be Mat(trainRows, 1, CV_32S);
  • train data needs to be Mat(trainRows, trainCols, CV_32F);
  • test data needs to be Mat(testRows, trainCols, CV_32F);

    ( yes, you can test several samples at the same time, but you need to use an (empty) result Mat in predict)


Mat result = new Mat(); //since we have more than 1 sample
classifier.predict(testingData, result);
edit flag offensive delete link more

Comments

Thank you very much, it worked fine but the classifier gave me two wrong answer out of 4. Do think the order of the labelsMat is correct or the features are not enough or are not good? I need to save and load the classifier but it gave me an error. I using Opencv 3.10.

Nani gravatar imageNani ( 2017-06-30 09:30:37 -0600 )edit
  • no good -- what do you expect from 18 samples ? (also your features are very short) 1000 samples per class !
  • load the classifier -- load() is a static method, that returns a new SVM. got that right ?l
berak gravatar imageberak ( 2017-06-30 09:34:49 -0600 )edit

Also for testing multiple sample classifier.predict(testingData, result); can not be resolved with two mat objects.

Nani gravatar imageNani ( 2017-06-30 09:37:40 -0600 )edit

@berak thank you for your reply, this is my first time i use machine learning, opencv, and image processing and I am in the learning process and thanks to this group which make the learning process faster, anyway I could not get what you mean. Can you please give me some hints about improving my classifier.

Nani gravatar imageNani ( 2017-06-30 09:44:38 -0600 )edit

predict(query,result, 0); please look at docs.

btw, i found weka quite helpful for tweaking SVM params & data.

berak gravatar imageberak ( 2017-06-30 09:45:18 -0600 )edit

Thanks @berak, testing multiple samples worked fine but know I am trying to save the classifier to the android device but it gives me this error: --------- beginning of crash 07-03 10:39:32.602 7629-7629/? A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 7629 (esar.opencvtest)

                                   [ 07-03 10:39:32.606  3096: 3096 W/         ]
                                   debuggerd: handling request: pid=7629 uid=10215 gid=10215 tid=7629
Nani gravatar imageNani ( 2017-07-03 04:46:21 -0600 )edit

I am using this code:
final File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Directory_Feature/" );

    if (!dir.exists())
    {
        if(!dir.mkdirs()){
            Log.e("ALERT","could not create the directories");
        }
    }

    final File myFile = new File(dir, "datafile.xml");

    if (!myFile.exists())
    {
        myFile.createNewFile();
    }

    classifier.save(myFile.getAbsolutePath());
Nani gravatar imageNani ( 2017-07-03 04:46:56 -0600 )edit

sorry, cannot help with android specific things (no such thing here)

berak gravatar imageberak ( 2017-07-03 04:49:21 -0600 )edit

Thanks, Just general question I read that opencv 3.10 which the version i use does not support save and load the classifier. Is this correct?

Nani gravatar imageNani ( 2017-07-03 05:33:44 -0600 )edit

it had a problem with loading it back (in python or java), but that should be solved now.

berak gravatar imageberak ( 2017-07-03 05:37:40 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2017-06-22 07:07:15 -0600

Seen: 748 times

Last updated: Jul 03 '17