Segmentation & object detection by color.

In this tutorial i go to explain how to image segmentation or detect objects byred color, in this case by red color.

This task is simple, but there are some things we must known.

Now i go to explain and get a demo code for segmentation, how to determine if each image pixel is red or no, and then, i go to explain how we  can detect object, it’s similar but with diferent concept.

In first moment, we can decide get the red channel of image  and get the values, if it’s a higher value then we have a red pixel otherwise no.

This is incorrect. Why?, imagine we have a pixel and in his red channel have a 255 value, this is the higher value, then we decide this is a red pixel, but if in green and blue channel have 255 value too then we have a white pixel instead a red pixel. Then how we determine if a pixel is red or no?

Ok, we go to get some color values and determine how we decide if is red or no.

Then we can decide that higher red value, and  lower values of blue and green can be defined as red color. Moreover the green and blue values don’t have a higher difference between his values.

We go to construct simple graph with some values to see better.

We see in this graph that the red value is higher than a max value and there are a min value for green and blue.

The min and max we go to name as blue green threshold and red threshold (bg_threshold, r_threshold).

This code compute for each pixel if it’s red or no, and create a black/white image, this is our segmentation image, and with this image we can use to label each object, we use a cvFindContours to retreive the contours of each object detected on our image.

 for(y=0;yheight; y++)
 {
 red=((uchar*)(img->imageData + img->widthStep*y))[x*3+2];
 green=((uchar*)(img->imageData + img->widthStep*y))[x*3+1];
 blue=((uchar*)(img->imageData + img->widthStep*y))[x*3];
 uchar* temp_ptr=&((uchar*)(img_result_threshold->imageData + img_result_threshold->widthStep*y))[x];

 if((red>threshold)&&(green < BG_threshold) && (blue < BG_threshold) && (abs(green-blue)< BG_diff)){
 temp_ptr[0]=255;//White to greater of threshold
 }else{
 temp_ptr[0]=0;//Black other
 }
 }
 }

 cvMorphologyEx(img_result_threshold, img_morph, img_temp, NULL, CV_MOP_CLOSE, 6);

 cvNamedWindow( "Threshold", 1 );
 cvShowImage( "Threshold", img_morph );

 cvFindContours( img_morph, storage, &contour, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );

 for( ; contour != 0; contour = contour->h_next )
 {
 CvScalar color = CV_RGB( rand()&255, rand()&255, rand()&255 );
 cvDrawContours( img, contour, color, color, -1, 3, 8, cvPoint(0,0) );
 }

And this is the result, whe can see in the image a color border with detected red objects, the system detect two objects. The notebook and the notebook corner

Demo Source

This is perfect to image segmentation by color, but imagine we have objects ofone image, and we want get each object and know if this object have a predominant red color or no.

The theory is same but applied to the object histogram, and use the median to determine the thresholds

But with this we don’t have enough, because we can get a gray image as we can see in the second histogram, then we need use another parameter more, the dispersion of each channel.

We can see that in this first histogram we can ensure this object have a predominant red, and in the second histogram no.

18 Comments to “Segmentation & object detection by color.”

  1. aclis 17 January 2010 at 7:48 pm #

    I think that it’s better convert the image to Lab space color and calculate the color distance.

  2. damiles 17 January 2010 at 8:06 pm #

    Hi aclis, of course, there are better color segmentation. I want explain the more simply color segmentation in this tutorial. There are better color segmentation as this paper and another papers.

    The purpose of my blog is not explain the better solution, i want create basic approximations to introduce people to OpenCV and his functions, and basics of Computer vision.

    Regards David.

  3. Burak 20 January 2010 at 11:36 am #

    Thank you !

  4. Noctis 4 March 2010 at 10:33 am #

    Hi,
    Thanks for your documentation, but i can not use the given code , can you send me as full version of it ? or put it somewhere in your blog?

  5. damiles 4 March 2010 at 11:38 am #

    Noctis there are a demo source in the post with a full version, under the image capture.

  6. awinash 17 March 2010 at 2:56 pm #

    act,i need full version of the code. so pl. if possible, send me the code on my mail.i will be very thankful to u………

  7. damiles 17 March 2010 at 2:59 pm #

    awinash, there are a demo with full version under image capture.

  8. farhan 26 May 2010 at 2:50 pm #

    First of all this is one of a great tutorial for newbee on open cv, Thanks alot. I would like to know can we use the same segmentation on human skin? I have read on many places hsv is best to provide skin color.?

  9. damiles 26 May 2010 at 4:08 pm #

    Thanks, of course, HSV is better for color tasks.

  10. farhan 26 May 2010 at 5:16 pm #

    it means i just need to convert the rgb to hsv and also i need to have skin colors store in shape of threshold like you did for red color? OR do i need more steps for it? Once again thanks for your reply.

  11. damiles 26 May 2010 at 5:55 pm #

    You can start with basic threshold and basic task, but SURE you need more steps!

  12. farhan 30 May 2010 at 1:07 am #

    I tried something which is written in some online document that i have to do these following things.

    RGB to HSV color space
    Then HSV ’s H should be between 6 and 38 range.

    Then make all other things as black while pixels between that range should be 255 so that result would come black and white.

    Then use filtering like dilate ,erode and smooth gaussian. But it doesnt work… can you give me any tip what i am doing mistake in it?

    IplImage* img = cvLoadImage(“1.jpg”);
    cvNamedWindow(“Example1″, CV_WINDOW_AUTOSIZE );

    //cvErode( img, img, NULL, 1);
    //cvDilate( img, img, NULL, 1);

    IplImage* hsv = cvCreateImage( cvGetSize(img), IPL_DEPTH_8U, 3 );

    cvCvtColor( img, hsv, CV_BGR2HSV );

    for(int x=0; xheight; x++)
    {
    for(int y=0;ywidth; y++)
    {
    float H=(float)((uchar*)(hsv->imageData + hsv->widthStep*x))[y*3+2];
    float S=(float)((uchar*)(hsv->imageData + hsv->widthStep*x))[y*3+1];
    float V=(float)((uchar*)(hsv->imageData + hsv->widthStep*x))[y*3];

    if(( V>6 && V0.23 && HimageData + hsv->widthStep*x))[y*3+2] =255;
    ((uchar*)(hsv->imageData + hsv->widthStep*x))[y*3+1] =255;
    ((uchar*)(hsv->imageData + hsv->widthStep*x))[y*3] =255;
    }
    else
    {
    ((uchar*)(hsv->imageData + hsv->widthStep*x))[y*3+2] =0;
    ((uchar*)(hsv->imageData + hsv->widthStep*x))[y*3+1] =0;
    ((uchar*)(hsv->imageData + hsv->widthStep*x))[y*3] =0;
    }

    }
    }

    cvDilate( hsv, hsv, NULL, 1);
    cvErode( hsv, hsv, NULL, 1);
    cvSmooth( hsv, hsv, CV_MEDIAN, 3, 3 );

    cvShowImage(“Example1″, hsv );
    cvWaitKey(0);
    cvReleaseImage( &img );
    cvDestroyWindow(“Example1″);

  13. damiles 1 June 2010 at 9:23 am #

    I think you have the error in conditional statement. I don’t see correctly this statmente, i don’t understand it.

  14. faizun 7 July 2010 at 1:48 pm #

    Hi Damiles,

    I am very new using OpenCv. I’ve compiled the source code from demo source but it still doesn’t work. I am confused why the name of the picture is not written in the source code? I don’t know yet what argv [0], argv [1], etc means?

    Thanks in advanced!

  15. damiles 7 July 2010 at 1:52 pm #

    Hi, this is a basic concept in console applications, the argv[0] is the app name and argv[1] is the first parameter send to app argv[2] the second …

    Then when you execute the application, under console, you call ./my_app myimage.jpg and you are passing myimage.jpg as variable stored in argv[1].

    Regards. Damiles.

  16. faizun 7 July 2010 at 2:12 pm #

    wow, thanks for the fast response. Sorry for the late reply :) Actually I’ve compiled it and succesfully result an application file. Then I put the image in the same folder with app file. But, it still doesn’t work. I compiled it using Dev-C++.

    Actually, what I have to do to make the source code function well,

    thanks so much Damiles.

  17. Aly 9 July 2010 at 12:14 am #

    hy man..thx u for ur help us :) pls if u know any thing about facial motion capture (steps,links)pls hel me …send to my e-mail……Great thanks

  18. damiles 9 July 2010 at 8:14 am #

    You can use opencv lkdemo.c sample. This is good starting point.


Leave a Reply