Damiles - David Millán Escrivá

Blender, 3D, Development, OpenGL, Computer Vision, OpenCV, Flash and more…

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

  • 0 Comments
  • Filed under: OpenCV, Tutorials
  • Last day, i’m developing an application with hsqldb and java swing with jpa entites classes, and whe i set a primary key or class attribute as int, integer, long or similar number type, when it parsed to sql statment with toplink it’s created as Number instead as integer.

    Before i looking many hours in Google i find the solution thanks to this web

    The solution is include  in persistence.xml this line:

    <property name=“toplink.target-database” value=“HSQL”/>

    We need specify to Toplink JPA the target database to HSQL.

    But we can specify more types or database as Attunity, Cloudspace, Database, MySQL4, Oracle… You can find the documentation and databases suport in Toplink Essential JPA Extension Reference

    Basic Painter in OpenCV

    In this basic tutorial we go to learn some basic instructions to work in OpenCV, mouse event, trackbar controler, create image, save image and draw basic circle.

    First step is create two windows, one is our canvas image, and other to color selector as we see in last tutorials.

    //Create window
    cvNamedWindow( “Demo”, 0 );
    cvNamedWindow( “ColorSelector”,0);

    Second step is creat the trackbars to control the color, then we need 3 trackbars, one by color.

    //Create track Bar
    cvCreateTrackbar(”Red”,”ColorSelector”, &red,255,&changeColor);
    cvCreateTrackbar(”Green”,”ColorSelector”, &green,255,&changeColor);
    cvCreateTrackbar(”Blue”,”ColorSelector”, &blue,255,&changeColor);

    The trackbar function has these parameter and definition:

    int cvCreateTrackbar( const char* trackbar_name, const char* window_name,
    int* value, int count, CvTrackbarCallback on_change );

    trackbar_name Name of created trackbar.
    window_name Name of the window which will e used as a parent for created trackbar.
    value Pointer to the integer variable, which value will reflect the position of the slider. Upon the creation the slider position is defined by this variable.
    count Maximal position of the slider. Minimal position is always 0.
    on_change Pointer to the function to be called every time the slider changes the position. This function should be prototyped as void Foo(int);Can be NULL if callback is not required.

    In our tutorial we have a changeColor function asociated to set a color preview:

    void changeColor(int pos){
    cvSet(imgColor, CV_RGB(red,green,blue),NULL);
    }

    The cvSet function set all matrix values to a scalar value. The cvSet function and params are:

    void cvSet( CvArr* arr, CvScalar value, const CvArr* mask=NULL );

    arr The destination array.
    value Fill value.
    mask Operation mask, 8-bit single channel array; specifies elements of destination array to be changed.

    The function cvSet copies scalar value to every selected element of the destination array:

    arr(I)=value if mask(I)!=0

    If array arr is of IplImage type, then is ROI used, but COI must not be set.

    To get mouse events we use cvSetMouseCallback where first parameter is window name we want give events, and the second parameter the pointer to callback function, we can pass third parameter as callback optional parameters.

    cvSetMouseCallback(”Demo”,&on_mouse, 0 );

    The mouse event callback function must defined a:

    void on_mouse( int event, int x, int y, int flags, void* param )

    Where

    event is a constant that give this values and define the mouse event:
    #define CV_EVENT_MOUSEMOVE      0
    #define CV_EVENT_LBUTTONDOWN    1
    #define CV_EVENT_RBUTTONDOWN    2
    #define CV_EVENT_MBUTTONDOWN    3
    #define CV_EVENT_LBUTTONUP      4
    #define CV_EVENT_RBUTTONUP      5
    #define CV_EVENT_MBUTTONUP      6
    #define CV_EVENT_LBUTTONDBLCLK  7
    #define CV_EVENT_RBUTTONDBLCLK  8
    #define CV_EVENT_MBUTTONDBLCLK  9

    x, y: integer mouse position in our image

    flag is another constant value:
    #define CV_EVENT_FLAG_LBUTTON   1
    #define CV_EVENT_FLAG_RBUTTON   2
    #define CV_EVENT_FLAG_MBUTTON   4
    #define CV_EVENT_FLAG_CTRLKEY   8
    #define CV_EVENT_FLAG_SHIFTKEY  16
    #define CV_EVENT_FLAG_ALTKEY    32

    Demo Source

  • 3 Comments
  • Filed under: OpenCV, Tutorials
  • OpenCV More with cameras.

    In last tutorial we learn how to get frames of our camera, now we go to learn some basic OpenCV functions to work with our captured frames or video. There is nothing special, but it’s the first steps to introduce to work with OpenCV

    Imagine we want create a basic OpenCV program that get a video o camera capture and process the images to get a binary image difference between actual frame and last frame.

    Then we have a actual image, lastImage, diffImage where we store the difference images, and the bitImage result that are IplImage instance.

    IplImage* image;
    IplImage* lastImage;
    IplImage* diffImage;
    IplImage* bitImage;

    Whe need create these variables and initialize with cvCreateImage, this function create and allocate in memory the structure and headers of our image, this function need as attribute image size, depth and number of channels. We get frame as reference to initialize the variables.

    image=cvCreateImage(cvSize(frame->width,frame->height),frame->depth,1);

    The frame whe get sure is a RGB image, but we go to working with gray level images the we need conver captured frame to Gray Level. The cvCvtColor conver color spaces of image to another and is defined:

    void cvCvtColor( const CvArr* src, CvArr* dst, int code );

    src is the source 8-bit (8u), 16-bit (16u) or single-precision floating-point (32f) image. dst is the destination image of the same data type as the source one. The number of channels may be different. And code is color conversion operation that can be specified using CV_<src_color_space>2<dst_color_space> constants

    cvCvtColor(frame, image, CV_BGR2GRAY);

    We can get a new copy in memory of image withcvCloneImage

    lastImage=cvCloneImage(image);

    To get the image differences we use cvAbsDiff function, to get absolute diference between images:

    cvAbsDiff(image,lastImage,diffImage);

    The function definition

    void cvAbsDiff( const CvArr* src1, const CvArr* src2, CvArr* dst );

    Where src1 is the first source array. src2 is the second source array, and dst is the destination array.

    Then to finish we only need get a threshold of image, and we do it with cvThreshold function

    cvThreshold(diffImage,bitImage,tr,255,CV_THRESH_BINARY);

    And this function have this definition:

    double cvThreshold( const CvArr* src, CvArr* dst, double threshold,
    double max_value, int threshold_type );

    Where src is source array (single-channel, 8-bit of 32-bit floating point), dst is destination array; must be either the same type as src or 8-bit, threshold is the threshold value, max_value is the maximum value to use with CV_THRESH_BINARY and CV_THRESH_BINARY_INV thresholding types, and threshold_type is thresholding type

    This is the main loop program:

    for(;;){
    IplImage* frame = 0;
    int c;

    frame = cvQueryFrame( capture );
    if( !frame )
    break;
    //If is the first frame
    if(!image){
    //Create image header same as frame but with 1 channel to gray
    image=cvCreateImage(cvSize(frame->width,frame->height),frame->depth,1);
    bitImage=cvCreateImage(cvSize(frame->width,frame->height),frame->depth,1);
    }
    //Convert frame to gray and store in image
    cvCvtColor(frame, image,CV_BGR2GRAY);

    //If is the first frame
    if(!lastImage){

    //If no lastImage clone actual image;
    lastImage=cvCloneImage(image);
    }
    if(!diffImage){
    //Create image header same as frame but with 1 channel to gray
    diffImage=cvCreateImage(cvSize(frame->width,frame->height),frame->depth,1);
    }

    cvShowImage( “CamSub”, frame );
    //Differences with actual and last image
    cvAbsDiff(image,lastImage,diffImage);
    //threshold image
    cvThreshold(diffImage,bitImage,tr,255,CV_THRESH_BINARY);
    //Change datas;
    lastImage=cvCloneImage(image);

    cvShowImage(”CamSub 1″,bitImage);

    c = cvWaitKey(10);
    if( (char) c == 27 )
    break;
    }

    Demo Source

  • 0 Comments
  • Filed under: OpenCV, Tutorials
  • Working in opencv with cameras is very easy, we only need a camera and our opencv libraries.

    The structure that we store the camera link is CvCapture, here we store this link, then to get this link we need call to cvCaptureFromCAM function, this function need only one param, the index of the camera to be used. If there is only one camera or it does not matter what camera to use -1 may be passed.

    Then this is our basic line to retrive our camera link

    CvCapture* capture = cvCaptureFromCAM( 0 );

    Then we only need get each frame we can capture with cam, to do this we can use the cvQuetyFrame passing as param our camera link and it return a IplImage* struct that we can show.

    IplImage* frame = cvQueryFrame( capture );

    With this easy lines we can get all frames we need from our camera.

    Demo source

  • 0 Comments
  • Filed under: OpenCV, Tutorials
  • Create a percent bar with CSS

    To create a easy and valid percent bar or tipicall star bar we can use a schemma as you can see below.

    CSS-Percent schema

    With this html code:

    <span class="percent"><span style="width:25%">25%</span></span>

    And this stylesheet:

    .percent{
    display: block;
    float: left;
    background:url(images/percent.png) top left no-repeat;
    height: 17px;
    width:75px;
    }
    .percent span{
    background:url(images/percent.png) bottom right no-repeat;
    display:block;
    float:left;
    height:17px;
    }

    This is the result of our percent image:
    36%45%89%66%

  • 0 Comments
  • Filed under: CSS, Tutorials
  • GNUPLOT - 3d plot surface

    For 3d plot gnuplot use command splot.

    splot sin(sqrt((x*x+y*y)))/sqrt(x*x+y*y) t “weaves”

    Gnuplot surface wireframe

    Gnuplot surface wireframe

    We can add the style pm3d to add a gradient surface texture

    splot sin(sqrt((x*x+y*y)))/sqrt(x*x+y*y) with pm3d t “weaves”

    Gnuplot surface 3d pm3d

    Gnuplot surface 3d pm3d

    But you can see we need more resolution, then we must set more isosamples:

    set isosamples 75,75

    Gnuplot surface with pm3d and isosample 75,75

    Gnuplot surface with pm3d and isosample 75,75

    For more info go to gnuplot page

    AWK. Calculate mean, min and max

    AWK is a general purpose programing language that is designed for processing text-based data. This unix command is very powerful and with it we can calculate the mean, min and max of a data stored in file.

    data.txt:

    10
    20
    50
    100
    200
    500

    awk command:

    awk ‘{if(min==”"){min=max=$1}; if($1>max) {max=$1}; if($1< min) {min=$1}; total+=$1; count+=1} END {print total/count, min, max}’ data.txt

    Result:

    146.667 10 500

    New Blog

    Hi, this is my new Blog, in wordpress, why? Because to maintain my old site and do it atractive need a lot of time, and I don’t have time, then i installed a wordpress blog in my little server to do the task of maintain the site more easy.

    I want publish more post now…

  • 0 Comments
  • Filed under: Personal
  • OpenCV & OpenGL

    In this tutorial we see how we can acces to OpenCV functions and use the images we process with it to use in our OpenGL program.

    To use an OpenCV image (IplImage) and use it as an OpenGL textures we mus use this function.

    int loadTexture_Ipl(IplImage *image, Ttexture *dest) {
    unsigned char *pixels;

    if (dest==NULL) return -1;

    dest->width=image->width;
    dest->height=image->height;
    pixels=(unsigned char*)image->imageData;

    dest->tmode=GL_REPLACE;
    dest->minMode=GL_NEAREST;
    dest->maxMode=GL_NEAREST;
    dest->wrap_s=GL_REPEAT;
    dest->wrap_t=GL_REPEAT;

    glGenTextures(1, &dest->texid);
    setTexture(dest);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    glTexImage2D(GL_TEXTURE_2D, 0, 4, dest->width, dest->height,0, GL_BGR,
    GL_UNSIGNED_BYTE, pixels);
    return 0;
    }

    This function only get data image and store it as an image Texture.

    We can get a camera image and use it  to texture aplane, to do it we need a function to update the texture data, this we can do in OpenGL main loop or in glutiddleFunc as show

    //En la funcion donde se actualizen los datos
    frame = cvQueryFrame( capture );
    if( frame ){
    loadTexture_Ipl(frame, &texs[0]);
    }

    Download source