The basic patter recognition and classification with openCV

Nov 14, 2008 by     73 Comments    Posted under: OpenCV, Tutorials

In this tutorial we go to introduce to the pattern recognitions basics in openCV.

In pattern recognitions before we can classificate an element we need train our system. We go to train with 3 class with 100 samples each one.

Then we create 2 matrix trainData and traninClasses with 300 samples:

int train_sample_count = 300;
CvRNG rng_state = cvRNG(-1);
CvMat* trainData = cvCreateMat( train_sample_count, 2, CV_32FC1 );
CvMat* trainClasses = cvCreateMat( train_sample_count, 1, CV_32FC1 );

Where our 100 first data are class 1, the range 100 to 200 are class 2 and last 100 data are class 3, then we set our trainClasses matrix data:

cvGetRows( trainClasses, &trainClasses1, 0, 100 );
cvSet( &trainClasses1, cvScalar(1) );

cvGetRows( trainClasses, &trainClasses2, 100, 200 );
cvSet( &trainClasses2, cvScalar(2) );

cvGetRows( trainClasses, &trainClasses3, 200, 300 );
cvSet( &trainClasses3, cvScalar(3) );

cvGetRows function set a CvMat structure (matrix structure) with selected rows of source matrix.

cvGetRows( srcMatrix, destMatrix, first_row, last_row );

And set all rows to dest class witn cvSet, this function set all values of matrix to a scalar

cvSet( matrix, cv_scalar_value );

We go to use in this tutorial a random normalized sample in 2D (2D gaussian mixture)  that we generate in openCV with cvRandArr function. For create data sample we need create to cvRandArr, one for x values and other for y values.

//Train sample class 1
cvGetRows( trainData, &trainData1, 0, 100 );
cvGetCol( &trainData1, &colData1x, 0);
cvGetCol( &trainData1, &colData1y, 1);
cvRandArr( &rng_state, &colData1x, CV_RAND_NORMAL, cvScalar(200), cvScalar(50) );
cvRandArr( &rng_state, &colData1y, CV_RAND_NORMAL, cvScalar(200), cvScalar(50) );
//Train sample class 2
cvGetRows( trainData, &trainData2, 100, 200 );
cvGetCol( &trainData2, &colData2x, 0);
cvGetCol( &trainData2, &colData2y, 1);
cvRandArr( &rng_state, &colData2x, CV_RAND_NORMAL, cvScalar(300), cvScalar(50) );
cvRandArr( &rng_state, &colData2y, CV_RAND_NORMAL, cvScalar(300), cvScalar(50) );
//Train sample class 3
cvGetRows( trainData, &trainData3, 200, 300 );
cvGetCol( &trainData3, &colData3x, 0);
cvGetCol( &trainData3, &colData3y, 1);
cvRandArr( &rng_state, &colData3x, CV_RAND_NORMAL, cvScalar(100), cvScalar(30) );
cvRandArr( &rng_state, &colData3y, CV_RAND_NORMAL, cvScalar(400), cvScalar(30) );

Now we can train our classifier. In this basic tutorial, we go to use the k nearest neighbour classifier.

This classifier is the most simplest but it’s used in more cases. This algorithm classify an object by a majority vote of its nearest neighbors.

Then we use CvKNearest openCV class

CvKNearest knn( trainData, trainClasses, 0, false, K );

Where first parameter is train data, second the classes, and last parameter is the nomber of k-neighbour value with maximum value is 32.

Now we have in knn instance a k-nn classifier. Now if we want know in wich class is classified point only need call knn.find_nearest and return the nearest class.

Then we go to classify a values for range [0,0] to [500,500] this our classifier, this is the result:

Red points: Train data of class 1.
Green points: Train data of class 2.
Blue points: Train data of class 3.

Red area: classify as class 1 with more than 5 neighbours in class 1
Light red area: classify as class 1 with less than 5 neighbours in class 1
Green area: classify as class 2 with more than 5 neighbours in class 2
Light green area: classify as class 2 with less than 5 neighbours in class 2
Blue area: classify as class 3 with more than 5 neighbours in class 3
Light blue area: classify as class 2 with less than 5 neighbours in class 2
Orange area: don’t classify

Demo source

73 Comments + Add Comment

  • Hi,I like your blog, I am interested in OpenCv for machine learning and I tried your example code. But I found linker problem with the ml function. I am using Borland Builder c++ and OpenCb version 1.1. Someone have some suggestion for that problem ?
    Thanks.

  • hi, if you have link problem, you must check you have the libraries set in your configuration project. Check how is set in VC++ (http://opencv.willowgarage.com/wiki/VisualC%2B%2B)

    Regards

  • Hello, I need used opencv with netbeans of java for industrial parts detection by color and form.
    Thanks for your help.
    Sorry, i’m not speak english well

  • Hi, you need port or wrapper for use opencv in java or only need compile your C/C++ projects with Netbeans.

    There are many opencv ports and wrappers you can use. Look for in google and sure you can find one to use.

  • Hey nice post, I am looking for stuff more that the 7-8 basic classifiers implemented in ml.h. Do you know a good machine learning library in C++ containing implementations of ideas like graphical models?

  • Hi if you look for Machine learning into google you can find MCL++ from sgi, it can be good, and there are weka too, weka is writted in java with graphical frontend. Weka can be a good for tests and more.

    Regards David.

  • Hello, I am new to opencv and have been trying to compile you code using Visual Basic 2010 on Windows7. I have downloaded opencv-2.1.0 and build it using CMake ver2.8. I included all the directories but i am clueless what to do next. Because when i try to Debug main it gives me some 40 errors.
    I am making a project on Handwriting and Shape recognition from graphic pen input to make UML diagrams. It would be great help if you guide me how to run these opencv projects.

    Regards
    Sank

  • Hello,

    I’ve been reading through your blog and source codes and I must say that I’m impressed. I’m currently working on a handwritting OCR and I was wondering if how you would approach that issue and extend your example to “letters of the alphabet”. I have an idea how to do it by using the k-nearest neighbour algorithm (i.e. change the ). It would just involves creating more training set and introducing more classes and the appropriate data mapping. But I would like your insight on how you would approach it.

    Btw, I was wondering if there’s any specific reason why you used PBM format for the training and not other format such as PNG, JPG? Does openCV not support those format? My apology for those silly questions but I’m new to openCV.

    Thanks,

    kayce

  • Hi, Can you please show us an example on how to link extracted features for training?

  • Hi Damiles,
    Thank you for your basicOCR code. I compiled it but always get run-time errors when loading the train data at cvLoadImage. It doesn’t recognize even the first file in “..\OCR00.pbm”.
    Do you have any clue what went wrong? Thank you in advance.

  • please ensure you have the images in the folder that app is looking for.

  • Hi damiles,

    Thank you! Yes, you are right. The executable VS creates is in a debug folder and of course could not find the train dats in “..\OCR”

    Brady

  • Hi, do you have any code for indoor/outdoor image recognition? Or it is possible to you this code for my problem? Than you very much!

  • Hey.

    Anyone had any luck with regression values from the machine learning library?

    Particularly the SVM, which does both classification and regression values.

    I have an example code snippet…..

    int main( int argc, char** argv )
    {
    bool train_update = false;
    int train_sample_count = 100, train_sample_size = 10;
    CvMat *data_mat, *class_mat;
    class_mat = cvCreateMat(train_sample_count, 1, CV_32FC1);
    data_mat= cvCreateMat(train_sample_count, train_sample_size, CV_32FC1);
    for(i = 0; i data.fl[ i] = value;//assign the class or regression value
    for(j = 0; j data.fl[i*train_sample_size+ j] = val;//assing data sample value
    }
    }
    CvSVMParams svm_param;
    svm_param.svm_type = CvSVM::NU_SVR;
    svm_param.kernel_type = CvSVM::RBF;
    svm_param.gamma = 1./train_sample_size;
    svm_param.nu = 0.5;
    svm_param.C = 8;
    svm_param.term_crit.epsilon = 0.001;
    svm_param.term_crit.max_iter = 50;
    svm_param.term_crit.type = CV_TERMCRIT_ITER|CV_TERMCRIT_EPS;
    CvSVM *tSvm = new CvSVM();
    tSvm->train(data_mat, class_mat, 0, 0, svm_param);
    tSvm->save(“filename.xml”, 0);

    //For prediction
    CvSVM *pSvm = new CvSVM();
    pSvm->load(“filename.xml”, 0);
    CvMat *sample = cvCreateMat(1, train_sample_size, CV_32FC1);
    for(i = 0; i data.fl[i] = val ;//assign value
    }
    float pred = pSvm->predict(sample);
    printf(“\n %.3f”, pred);
    }

    However variables val and value aren’t mentioned before useage. Any ideas? Regression classification is defined in many sources (O’Reilly etc.) but it isn’t clear how to go about applying it.

    Variable instances ORDERED or CATEGORICAL. Could we start a dialog on this?

    Dan

  • I don’t test svm, but i try to test your code and i respond you.

    Regards David.

  • No sorry, i never have a similar project. sorry.

  • hi
    thanks a lot for this perfect tutorial!
    i’m working in a project which consist of recognizing arabic text using opencv.
    Do you think that i can use the same method to recognize letter?and why you work wit PMB ?can I work with jpg o png?is ther anny difference??(i m new in opencv)
    thnks a lot :) )

  • hi Kayce please i’m working in the same project as you you said that you have an idea how to recognize character can you help me please??

  • Hi maryem, you can use the same tutorial and method, and you can use jpg or png instead pbm, there are no differences.

    Regards.

  • muchas gracias damiles :) ) you’re the best :) )

  • thanks for your blog ,i am just a beginner in opencv!

  • Cool dude!
    I’m curious about something more?
    How about letter detection, word detection, and phrase detection?

    If you have clue, please send a clue of code to
    my email: sky.henry [ at ] live.com

    I’m totally appreciate that Dude :)

  • This is no a esasy task, there are two techniques, top down and down top, this is, top down is first detect text blocks, and for each text block detect lines, words and letters, and down top is detect each letter and cluster each letter into words, lines and texts

    Look foor into http://scholar.google.es/ text block detection. there are a lot of info.

Got anything to say? Go ahead and leave a comment!

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">