Using OpenCV to find and draw contours in video

This is a very similar post to that posted previously, which used a OpenCV and cvBlobsLib to identify contours in video footage and display them on the screen. Please refer to this for detail on how to convert the Red, Green, Blue (RGB) format into Hue, Saturation, Value (HSV) format, and threshold the HSV into the black and white format needed for finding contours in OpenCV:

http://www.technical-recipes.com/2011/track-colored-objects-in-video-using-opencv-and-cvblobslib/

This example achieves the same but without using the cvBlobsLib to identify contours / strongly connected components, just 100% OpenCV calls.

Full code listing as follows:

#include "cv.h"  
#include "highgui.h"  
#include <iostream>
#include <vector>

// 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 );  

    cvReleaseImage( &imgHSV );  
    return imgThresh;  
}  

int main()  
{
    CvCapture* capture = cvCaptureFromFile( "MOV.MPG" );  
    IplImage* frame = cvQueryFrame( capture );
        
    // Can't get device? Complain and quit  
    if( !capture )  
    {  
        std::cout << "Could not initialize capturing...\n";  
        return -1;  
    }  
    
    while (true)
    {
        frame = cvQueryFrame(capture); 
        
        if( !frame ) break; 
        
        IplImage* imgThresh = GetThresholdedImageHSV( frame );  
        cv::Mat imageThreshMat = cv::Mat(imgThresh, false);
        cv::Mat frameMat = cv::Mat(frame, false);
               
        // Find the contours.
        std::vector<std::vector<cv::Point> > contours;
        cv::Mat contourOutput = imageThreshMat.clone();
        cv::findContours( contourOutput, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE );

        //Draw the contours       
        cv::Mat contourImage = frameMat.clone(); 
        for (size_t idx = 0; idx < contours.size(); idx++) 
        {
            cv::drawContours(contourImage, contours, idx, cv::Scalar(255, 0, 0));
        } 
            
        cv::imshow("video", contourImage);
        cvWaitKey(40);
    }

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

    return 0;  
}

The video footage used in this example can be obtained from the following download link:

http://technical-recipes.com/pics/MOV.7z

In this example I draw and display the contours on the same source image, ie not as two separate images side-by-side, though this could easily be done. The result of running this code is demonstrated by the following screenshots, which show the ‘contours’ (my little boy’s blue gloves) superimposed on top of the original video frames. Click on the images to get a better view of the contours:

findcontours2

findcontours1

Have fun!

Leave a Reply