An example of detecting object motions using openCV

Motion detection example

Motion detection example

As asked many times about how to use openCV to detect body movements or other object movements, i borrow an example from openCV installation samples, which regards to motion detections particularly in motion directions. Some relevant posts have been posted before here, but to declare the use of openCV samples, this artical is posted. The picture demonstrating above has clearly showed the detection results which is, from left up to right down, just as the object moves, which is actually my head and part of shoulder.

Though this example is far too simple to put in practical use, this can be still useful for further applications as long as the codes are improved, at least the detection rules are remained. Here below is the list of source code which can be used directly as a .cpp file, check it out:

#ifdef _CH_
#pragma package
#endif

#ifndef _EiC
// motion templates sample code
#include “cv.h”
#include “highgui.h”
#include
#include #include
#include
#endif

// various tracking parameters (in seconds)
const double MHI_DURATION = 1;
const double MAX_TIME_DELTA = 0.5;
const double MIN_TIME_DELTA = 0.05;
// number of cyclic frame buffer used for motion detection
// (should, probably, depend on FPS)
const int N = 4;

// ring image buffer
IplImage **buf = 0;
int last = 0;

// temporary images
IplImage *mhi = 0; // MHI
IplImage *orient = 0; // orientation
IplImage *mask = 0; // valid orientation mask
IplImage *segmask = 0; // motion segmentation map
CvMemStorage* storage = 0; // temporary storage

// parameters:
// img – input video frame
// dst – resultant motion picture
// args – optional parameters
void update_mhi( IplImage* img, IplImage* dst, int diff_threshold )
{
double timestamp = (double)clock()/CLOCKS_PER_SEC; // get current time in seconds
CvSize size = cvSize(img->width,img->height); // get current frame size
int i, idx1 = last, idx2;
IplImage* silh;
CvSeq* seq;
CvRect comp_rect;
double count;
double angle;
CvPoint center;
double magnitude;
CvScalar color;

// allocate images at the beginning or
// reallocate them if the frame size is changed
if( !mhi || mhi->width != size.width || mhi->height != size.height ) {
if( buf == 0 ) {
buf = (IplImage**)malloc(N*sizeof(buf[0]));
memset( buf, 0, N*sizeof(buf[0]));
}

for( i = 0; i < N; i++ ) { cvReleaseImage( &buf[i] ); buf[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 ); cvZero( buf[i] ); } cvReleaseImage( &mhi ); cvReleaseImage( &orient ); cvReleaseImage( &segmask ); cvReleaseImage( &mask ); mhi = cvCreateImage( size, IPL_DEPTH_32F, 1 ); cvZero( mhi ); // clear MHI at the beginning orient = cvCreateImage( size, IPL_DEPTH_32F, 1 ); segmask = cvCreateImage( size, IPL_DEPTH_32F, 1 ); mask = cvCreateImage( size, IPL_DEPTH_8U, 1 ); } cvCvtColor( img, buf[last], CV_BGR2GRAY ); // convert frame to grayscale idx2 = (last + 1) % N; // index of (last - (N-1))th frame last = idx2; silh = buf[idx2]; cvAbsDiff( buf[idx1], buf[idx2], silh ); // get difference between frames cvThreshold( silh, silh, diff_threshold, 1, CV_THRESH_BINARY ); // and threshold it cvUpdateMotionHistory( silh, mhi, timestamp, MHI_DURATION ); // update MHI // convert MHI to blue 8u image cvCvtScale( mhi, mask, 255./MHI_DURATION, (MHI_DURATION - timestamp)*255./MHI_DURATION ); cvZero( dst ); cvCvtPlaneToPix( mask, 0, 0, 0, dst ); // calculate motion gradient orientation and valid orientation mask cvCalcMotionGradient( mhi, mask, orient, MAX_TIME_DELTA, MIN_TIME_DELTA, 3 ); if( !storage ) storage = cvCreateMemStorage(0); else cvClearMemStorage(storage); // segment motion: get sequence of motion components // segmask is marked motion components map. It is not used further seq = cvSegmentMotion( mhi, segmask, storage, timestamp, MAX_TIME_DELTA ); // iterate through the motion components, // One more iteration (i == -1) corresponds to the whole image (global motion) for( i = -1; i < seq->total; i++ ) {

if( i < 0 ) { // case of the whole image comp_rect = cvRect( 0, 0, size.width, size.height ); color = CV_RGB(255,255,255); magnitude = 100; } else { // i-th motion component comp_rect = ((CvConnectedComp*)cvGetSeqElem( seq, i ))->rect;
if( comp_rect.width + comp_rect.height < 100 ) // reject very small components continue; color = CV_RGB(255,0,0); magnitude = 30; } // select component ROI cvSetImageROI( silh, comp_rect ); cvSetImageROI( mhi, comp_rect ); cvSetImageROI( orient, comp_rect ); cvSetImageROI( mask, comp_rect ); // calculate orientation angle = cvCalcGlobalOrientation( orient, mask, mhi, timestamp, MHI_DURATION); angle = 360.0 - angle; // adjust for images with top-left origin count = cvNorm( silh, 0, CV_L1, 0 ); // calculate number of points within silhouette ROI cvResetImageROI( mhi ); cvResetImageROI( orient ); cvResetImageROI( mask ); cvResetImageROI( silh ); // check for the case of little motion if( count < comp_rect.width*comp_rect.height * 0.05 ) continue; // draw a clock with arrow indicating the direction center = cvPoint( (comp_rect.x + comp_rect.width/2), (comp_rect.y + comp_rect.height/2) ); cvCircle( dst, center, cvRound(magnitude*1.2), color, 3, CV_AA, 0 ); cvLine( dst, center, cvPoint( cvRound( center.x + magnitude*cos(angle*CV_PI/180)), cvRound( center.y - magnitude*sin(angle*CV_PI/180))), color, 3, CV_AA, 0 ); } } int main(int argc, char** argv) { IplImage* motion = 0; CvCapture* capture = 0; if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0]))) capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 ); else if( argc == 2 ) capture = cvCaptureFromFile( argv[1] ); if( capture ) { cvNamedWindow( "Motion", 1 ); for(;;) { IplImage* image; if( !cvGrabFrame( capture )) break; image = cvRetrieveFrame( capture ); if( image ) { if( !motion ) { motion = cvCreateImage( cvSize(image->width,image->height), 8, 3 );
cvZero( motion );
motion->origin = image->origin;
}
}

update_mhi( image, motion, 30 );
cvShowImage( “Motion”, motion );

if( cvWaitKey(10) >= 0 )
break;
}
cvReleaseCapture( &capture );
cvDestroyWindow( “Motion” );
}

return 0;
}

#ifdef _EiC
main(1,”motempl.c”);
#endif

To download the source code, please refer to directory “OpenCV\samples\c\motempl.c“.

Author: Andol Li

A HCI researcher, a digital media lecturer, an information product designer, and a python/php/java coder.

9 Comments On “ An example of detecting object motions using openCV”

  1. Hello there, I face some problems using OpenCV for quite some time. I am using wireless camera model STK1160 which is WDM type. In my knowledge, only VFW and MIL are compatible camera for OpenCV. I had tried using video input but it is unstable. The output may or may not come out. I also had tried using DirectX, it shows the image but I don’t know how to link the buffer with OpenCV for image processing. Could you please give me some advice on how to solve this problem? Thank you!

  2. hi andol ….I’m trying to detect a circle and hand, and draw a circle around the circle and a rectangle around the hand, and display both in the same image. When I run the program I get some memory error, can anyone please help?

    Below is my code:
    #include “opencv/cv.h”
    #include “opencv2\highgui\highgui.hpp”
    #include
    #include
    #include
    #include
    #include

    using namespace std;

    //declarations
    IplImage* img = 0;

    CvHaarClassifierCascade *cascade;
    CvMemStorage *cstorage;
    CvMemStorage *hstorage;

    void detectObjects( IplImage *img );
    int key;

    int main( int argc, char** argv )
    {
    CvCapture *capture;
    IplImage *frame;

    // loads classifier for hand haar cascade
    char *filename = “haarcascade_hand.xml”;
    cascade = ( CvHaarClassifierCascade* )cvLoad( “haarcascade_hand.xml”, 0, 0, 0 );

    // setup memory buffer
    hstorage = cvCreateMemStorage( 0 );
    cstorage = cvCreateMemStorage( 0 );

    // initialize camera
    capture = cvCaptureFromCAM( 0 );

    // always check
    //assert( cascade && storage && capture );

    // create a window
    cvNamedWindow( “Camera”, 1 );

    while(key!=’q’) {
    // captures frame and check every frame
    frame = cvQueryFrame( capture );
    if( !frame ) break;

    // detect objects and display video
    detectObjects (frame );

    // quit if user press ‘q’
    key = cvWaitKey( 10 );
    }

    // free memory
    cvReleaseCapture( &capture );
    cvDestroyAllWindows();
    cvReleaseHaarClassifierCascade( &cascade );
    cvReleaseMemStorage( &cstorage );
    cvReleaseMemStorage( &hstorage );

    return 0;
    }

    void detectObjects( IplImage *img )
    {
    int px;
    int py;
    int edge_thresh = 1;
    IplImage *gray = cvCreateImage( cvSize(640,480), 8, 1 );
    IplImage *edge = cvCreateImage( cvSize(640,480), 8, 1 );

    // convert video image color
    cvCvtColor(img,gray,CV_BGR2GRAY);

    // set the converted image’s origin
    gray->origin=1;

    // color threshold
    cvThreshold(gray,gray,100,255,CV_THRESH_BINARY);

    // smooths out image
    cvSmooth(gray, gray, CV_GAUSSIAN, 11, 11);

    // get edges
    cvCanny(gray, edge, (float)edge_thresh, (float)edge_thresh*3, 5);

    // detects circle
    CvSeq* circle = cvHoughCircles(gray, cstorage, CV_HOUGH_GRADIENT, 1, gray->height/50, 5, 35);

    // draws circle and its centerpoint
    float* p = (float*)cvGetSeqElem( circle, 0 );
    cvCircle( img, cvPoint(cvRound(p[0]),cvRound(p[1])), 3, CV_RGB(255,0,0), -1, 8, 0 );
    cvCircle( img, cvPoint(cvRound(p[0]),cvRound(p[1])), cvRound(p[2]), CV_RGB(200,0,0), 1, 8, 0 );
    px=cvRound(p[0]);
    py=cvRound(p[1]);

    // displays coordinates of circle’s center
    cout < (“<<px<<","<<py<<")"<x, r->y ),
    cvPoint( r->x + r->width, r->y + r->height ),
    CV_RGB( 255, 0, 0 ), 1, 8, 0 );

    cvShowImage(“Camera”,img);
    }

  3. Hi Martin..I can see that there is some bug in your code.Please verify each codes you wrong as python is very case sensitive.According to me this is the case.
    If you still having some problems to contact me,I will correct all the errors.
    ok.

  4. hiii,,
    actually i want to make a face login system ,,
    having some problem like how to compare previous saved images with the new images from camera,,
    i just have to compare same persons images as i will take his user name also as input ,,
    so pls. if u can help me ,,
    i m kind of new in this,,

  5. I do consider all the ideas you’ve introduced on your post.
    They’re very convincing and will certainly work. Still,
    the posts are very short for newbies. May just you please lengthen
    them a bitt from next time? Thanks for the post.

  6. Baltimore homes for rent are spacious, well equipped, built with all the fine finishes, just painted and all necessary facilities.

    Based on the book by Harper Lee, To Kill a Mockingbird is about a lawyer caught in the middle of what seems to be a hopeless racially biased case in which an innocent man’s life is on the
    chopping block. There is no magic strategy that guarantees your house will sell.

    Feel free to visit my homepage; บ้านเช่าสี่มุมเมือง

  7. Hello there I am so glad I found your webpage,
    I really found you by error, while I was browsing on Yahoo for something
    else, Regardless I am here now and would just like to
    say thank you for a remarkable post and a all
    round exciting blog (I also love the theme/design),
    I don’t have time to browse it all at the minute but I have bookmarked it and
    also added your RSS feeds, so when I have time I will be back to read more, Please do keep up the excellent jo.

Leave a comment
Due to technical adjustments, the comment function is shortly closed and will be re-openning soon. Thanks.


Copyrights 2006-2018 © All rights reserved
Theme Tree2, re-designed by Andol Li, powered by WordPress and Bootsrap
WWW.ANDOL.ME | 浙ICP备15040508号-1
公安备案图标 浙公网安备33010602004018号
Back to top