Tracking Colored Objects in Video using OpenCV and cvBlobsLib

As a newcomer to image processing, I have attempted to achieve the tracking of coloured objects in some sample video footage. In my case, my little one’s blue gloves moving in a snow-covered landscape (a bitterly cold Musselburgh allotments, December 2010).



Pre-requisites

To get this to build and work properly, please ensure the following pre-requisites have been installed to your satisfaction:

Set up OpenCV and cvBlobsLib in Visual Studio.

Install and set up ffmpeg.

In the example given here we essentially do the following four things:

1. Obtain footage from the camera or video file.

CvCapture* capture = cvCaptureFromFile( "MOV.MPG" );

2. Convert video formats

Convert frame from its default BGR (blue, green, red) format into HSV (Hue, Saturation, Value) format and extract the binary (black and white) image from it:

cvCvtColor( img, imgHSV, CV_BGR2HSV );

It is much easier to detect coloured areas using the HSV (hue, saturation, value) format rather than the RGB (red, green, blue) format. HSV has the advantage of only having to use a single number to detect the colour (“hue”), in spite of there being several shades of that colour, ranging from relatively from light shades to darker shades. The amount of colour and the brightness of the colour are handled by the “saturation” and “value” parameters respectively.

3. Do the thresholding

The original image is kept intact for later use, and we then threshold the HSV reference image (imgHSV) to obtain our black and white image (imgThresh):

cvInRangeS( imgHSV,
            cvScalar( 104, 178, 70  ),
            cvScalar( 130, 240, 124 ),
            imgThresh );

The two cvScalar parameters represent the lower and upper bound of HSV (in that order) values that are blueish in colour. I got some suitable max/min values by grabbing some screenshots of the coloured objects I was interested in tracking and observing the kinds of hue/saturation/lum values that occur.

By selecting the region of interest (eg the blue gloves), and copying and pasting into another MS Paint document and expanding the area of interest, you can get a reasonable overview of the pixel colours that you are interested in tracking:

Dab on selected pixels and use the colour picker tool to display the hue/saturation/luminosity values mentioned earlier:

After writing down a few of these results I was able to get estimates of where these upper and lower values occur in the coloured regions of interest. This is far quicker than using trial and error.

It should be noted in MS Paint, the hue values range from 0-239, while OpenCV’s hue values range from 0-179. So any hue value you take from MS Paint for use in your code will need to be scaled using the factor 180 / 240. A MS Paint Hue value of 147 for example becomes 147 * (180/240) = 110 in OpenCV.

In MS Paint the Saturation and Luminosity are also in the range 0-239 while the OpenCV equivalents are in the range 0..255 (8 bit encoding). A MS Paint saturation of 210, for example, becomes (210/240) * 255 = 223 in OpenCV.

4. Do the blob detection

Use the cvBlobsLib APIs to detect the white blobs from the black background, excluding those of an inappropriate size.

blobs = CBlobResult( imgThresh, NULL, 0 );  

blobs.Filter( blobs, 
              B_EXCLUDE, 
              CBlobGetArea(),
              B_LESS,
              10 );

5. Insert bounding rectangles

Attach bounding rectangles to the detected coloured areas in the input video:

cvRectangle( frame,
             pt1,
             pt2,
             cvScalar(0, 0, 0, 0),
             1,
             8,
             0 );

So that the bounding rectangles covering the regions of interest are visible in the orginal input video:

Full Code Listing

// ObjectTracking.cpp : Define the entry point for console app.
#include "cv.h"
#include "highgui.h"
#include "BlobResult.h"
// Get thresholded image in HSV format
IplImage* GetThresholdedImageHSV( IplImage* img )
{
    // Create an HSV format image from image passed
    IplImage* imgHSV = cvCreateImage( cvGetSize( img ), 
                                      8, 
                                      3 );   

    cvCvtColor( img, imgHSV, CV_BGR2HSV );

    // Create binary thresholded image acc. to max/min HSV ranges
    // For detecting blue gloves in "MOV.MPG - HSV mode
    IplImage* imgThresh = cvCreateImage( cvGetSize( img ), 
                                         8, 
                                         1 );			

    cvInRangeS( imgHSV,
                cvScalar( 104, 178, 70  ),
                cvScalar( 130, 240, 124 ),
                imgThresh );

    // Tidy up and return thresholded image
    cvReleaseImage( &imgHSV );
    return imgThresh;
}
int main()
{
    CBlobResult blobs;  
    CBlob *currentBlob; 
    CvPoint pt1, pt2;
    CvRect cvRect;
    int key = 0;
    IplImage* frame = 0;

    // Initialize capturing live feed from video file or camera
    CvCapture* capture = cvCaptureFromFile( "MOV.MPG" );

    // Get the frames per second
    int fps = ( int )cvGetCaptureProperty( capture,
                                           CV_CAP_PROP_FPS );  

    // Can't get device? Complain and quit
    if( !capture )
    {
        printf( "Could not initialize capturing...\n" );
        return -1;
    }

    // Windows used to display input video with bounding rectangles
    // and the thresholded video
    cvNamedWindow( "video" );
    cvNamedWindow( "thresh" );		

    // An infinite loop
    while( key != 'x' )
    {
        // If we couldn't grab a frame... quit
        if( !( frame = cvQueryFrame( capture ) ) )
            break;		

        // Get object's thresholded image (blue = white, rest = black)
        IplImage* imgThresh = GetThresholdedImageHSV( frame );		

        // Detect the white blobs from the black background
        blobs = CBlobResult( imgThresh, NULL, 0 );  

        // Exclude white blobs smaller than the given value (10)  
        // The bigger the last parameter, the bigger the blobs need  
        // to be for inclusion  
        blobs.Filter( blobs,
                      B_EXCLUDE,
                      CBlobGetArea(),
                      B_LESS,
                      10 );  		

        // Attach a bounding rectangle for each blob discovered
        int num_blobs = blobs.GetNumBlobs();

        for ( int i = 0; i < num_blobs; i++ )  
        {               
            currentBlob = blobs.GetBlob( i );             
            cvRect = currentBlob->GetBoundingBox();

            pt1.x = cvRect.x;
            pt1.y = cvRect.y;
            pt2.x = cvRect.x + cvRect.width;
            pt2.y = cvRect.y + cvRect.height;

            // Attach bounding rect to blob in orginal video input
            cvRectangle( frame,
                         pt1, 
                         pt2,
                         cvScalar(0, 0, 0, 0),
                         1,
                         8,
                         0 );
        }

        // Add the black and white and original images
        cvShowImage( "thresh", imgThresh );
        cvShowImage( "video", frame );

        // Optional - used to slow up the display of frames
        key = cvWaitKey( 2000 / fps );

        // Prevent memory leaks by releasing thresholded image
        cvReleaseImage( &imgThresh );      
    }

    // We're through with using camera. 
    cvReleaseCapture( &capture );

    return 0;
}

Sample (compressed) MPG file “MOV.MPG” downloadable from here.

See this similar post for tracking colored objects using OpenCV calls only, no cvBlobsLib:

https://www.technical-recipes.com/2015/using-opencv-to-find-and-draw-contours-in-video/


Other posts related to image detection

Displaying AVI Video using OpenCV
Analyzing FlyCapture2 Images obtained from Flea2 Cameras
Integrating the FlyCapture SDK for use with OpenCV
OpenCV Detection of Dark Objects Against Light Backgrounds
Getting Started with OpenCV in Visual Studio
Object Detection Using the OpenCV / cvBlobsLib Libraries

Comments

19 responses to “Tracking Colored Objects in Video using OpenCV and cvBlobsLib”

  1. Andre Avatar

    You pretty much said what i could not effectively communicate. +1

    My blog:
    DSL Anbieter klick hier

  2. ebit Avatar

    thanks a lot .
    now i know how to determine lower and upper scale the specific color in HSV color space with openCV

    1. admin Avatar
      admin

      You’re welcome. I have found it much easier to achieve using HSV formats over RGB formats.
      Andy

  3. Arubab Avatar
    Arubab

    Hello sir, I really liked this article of yours. If possible could you write a tutorial on how to install cvblobs with microsoft visual studio 2010. Its really hard to install.

    1. Andy Avatar
      Andy

      Hi I have a previous post that has some guidelines on incorporating cvBlobsLib into Visual Studio. From what I remember it seemed to work in both the 2003 and 2010 versions:

      https://www.technical-recipes.com/2011/object-detection-using-the-opencv-cvblobslib-libraries/

      Specifically I think you will find the sections “Install the cvBlobsLib library” and onwards to be useful in installing the thing. It’s as good as a tutorial. I agree these things can be a pig to set up and get working. Let me know if you have problems.

      Kind regards, Andy.

  4. TJ Avatar
    TJ

    Thanks very much for this, I been working on the usual ‘air mouse’ that everyone does, this helped me learn the blob skin detection, I also made your example track a blue led light for a mouse, problem with the light is I had no clicking function.
    Anyways if anyone uses this for linux don’t forget to add the -lblob to the g++ compiling line.. that one got me for about 30 min…

    1. Andy Avatar
      Andy

      Thanks TJ. Good to see this post has been of use, and thanks for the additional info.

  5. Gürcan Kavakçı Avatar

    Thanks a lot again. I have learned how to tracking coloured objects.

    1. Andy Avatar
      Andy

      Lovely stuff. Good that these posts seem to be comprehensible.

  6. Pratyush Nalam Avatar

    How do you detect the direction of movement? Left, right or whatever?

    1. Andy Avatar
      Andy

      Hi Pratyus I would suggest Googling ‘motion detection’ or something similar. Not something I have had much experience in doing as yet.

  7. medo Avatar
    medo

    Thanks very much for this,how many frame per second fps process .
    when i read video and show it with out any process the speed 30fps ,but when convert from rgb model to hsv model and use cvInRangeS to threshold the color to convert to binary the number of frame process is less than 10 fps ???
    the cpu core i7 and os win7 64 bit

    1. Andy Avatar
      Andy

      I do not know the answer to this, but when I re-visit this I may have some more insights. Andy

  8. mahdi Avatar
    mahdi

    hi
    I want to use this lib(cvblob) for os win7 64 bit,
    you think that work?
    thanks

    1. Andy Avatar
      Andy

      Yes, I think it probably should.
      Mine is also running in Win 7 64-bit.
      Andy

  9. Tariq Avatar
    Tariq

    How do I run this tutorial in codeblocks.
    I don’t have cvBlobLibs for codeblocks. Compiled the ones for Visual studio but could not use that lib with codeblocks project.

    1. Andy Avatar
      Andy

      Hi Tariq. May get around this aspect one day. Thanks for bringing it to my attention. So much to do so little time! Please supply me with any progress in this you may have. Andy

  10. Aruna Avatar
    Aruna

    hi sir great tutorial it worked fine. how do i modify this code to detect object in an image (ex: detect a face in an image) can you help me
    thanks

  11. Ayush Joshi Avatar
    Ayush Joshi

    i am trying to implement your idea but its giving me include “BlobResult.h” no such file or directory fatal error . i am using Linux ubuntu 12.04 i am also get tried to include like this # btu giving same error…………….