2 #pragma package <opencv>
6 // motion templates sample code
15 // various tracking parameters (in seconds)
16 const double MHI_DURATION = 1;
17 const double MAX_TIME_DELTA = 0.5;
18 const double MIN_TIME_DELTA = 0.05;
19 // number of cyclic frame buffer used for motion detection
20 // (should, probably, depend on FPS)
28 IplImage *mhi = 0; // MHI
29 IplImage *orient = 0; // orientation
30 IplImage *mask = 0; // valid orientation mask
31 IplImage *segmask = 0; // motion segmentation map
32 CvMemStorage* storage = 0; // temporary storage
35 // img - input video frame
36 // dst - resultant motion picture
37 // args - optional parameters
38 void update_mhi( IplImage* img, IplImage* dst, int diff_threshold )
40 double timestamp = (double)clock()/CLOCKS_PER_SEC; // get current time in seconds
41 CvSize size = cvSize(img->width,img->height); // get current frame size
42 int i, idx1 = last, idx2;
52 // allocate images at the beginning or
53 // reallocate them if the frame size is changed
54 if( !mhi || mhi->width != size.width || mhi->height != size.height ) {
56 buf = (IplImage**)malloc(N*sizeof(buf[0]));
57 memset( buf, 0, N*sizeof(buf[0]));
60 for( i = 0; i < N; i++ ) {
61 cvReleaseImage( &buf[i] );
62 buf[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 );
65 cvReleaseImage( &mhi );
66 cvReleaseImage( &orient );
67 cvReleaseImage( &segmask );
68 cvReleaseImage( &mask );
70 mhi = cvCreateImage( size, IPL_DEPTH_32F, 1 );
71 cvZero( mhi ); // clear MHI at the beginning
72 orient = cvCreateImage( size, IPL_DEPTH_32F, 1 );
73 segmask = cvCreateImage( size, IPL_DEPTH_32F, 1 );
74 mask = cvCreateImage( size, IPL_DEPTH_8U, 1 );
77 cvCvtColor( img, buf[last], CV_BGR2GRAY ); // convert frame to grayscale
79 idx2 = (last + 1) % N; // index of (last - (N-1))th frame
83 cvAbsDiff( buf[idx1], buf[idx2], silh ); // get difference between frames
85 cvThreshold( silh, silh, diff_threshold, 1, CV_THRESH_BINARY ); // and threshold it
86 cvUpdateMotionHistory( silh, mhi, timestamp, MHI_DURATION ); // update MHI
88 // convert MHI to blue 8u image
89 cvCvtScale( mhi, mask, 255./MHI_DURATION,
90 (MHI_DURATION - timestamp)*255./MHI_DURATION );
92 cvCvtPlaneToPix( mask, 0, 0, 0, dst );
94 // calculate motion gradient orientation and valid orientation mask
95 cvCalcMotionGradient( mhi, mask, orient, MAX_TIME_DELTA, MIN_TIME_DELTA, 3 );
98 storage = cvCreateMemStorage(0);
100 cvClearMemStorage(storage);
102 // segment motion: get sequence of motion components
103 // segmask is marked motion components map. It is not used further
104 seq = cvSegmentMotion( mhi, segmask, storage, timestamp, MAX_TIME_DELTA );
106 // iterate through the motion components,
107 // One more iteration (i == -1) corresponds to the whole image (global motion)
108 for( i = -1; i < seq->total; i++ ) {
110 if( i < 0 ) { // case of the whole image
111 comp_rect = cvRect( 0, 0, size.width, size.height );
112 color = CV_RGB(255,255,255);
115 else { // i-th motion component
116 comp_rect = ((CvConnectedComp*)cvGetSeqElem( seq, i ))->rect;
117 if( comp_rect.width + comp_rect.height < 100 ) // reject very small components
119 color = CV_RGB(255,0,0);
123 // select component ROI
124 cvSetImageROI( silh, comp_rect );
125 cvSetImageROI( mhi, comp_rect );
126 cvSetImageROI( orient, comp_rect );
127 cvSetImageROI( mask, comp_rect );
129 // calculate orientation
130 angle = cvCalcGlobalOrientation( orient, mask, mhi, timestamp, MHI_DURATION);
131 angle = 360.0 - angle; // adjust for images with top-left origin
133 count = cvNorm( silh, 0, CV_L1, 0 ); // calculate number of points within silhouette ROI
135 cvResetImageROI( mhi );
136 cvResetImageROI( orient );
137 cvResetImageROI( mask );
138 cvResetImageROI( silh );
140 // check for the case of little motion
141 if( count < comp_rect.width*comp_rect.height * 0.05 )
144 // draw a clock with arrow indicating the direction
145 center = cvPoint( (comp_rect.x + comp_rect.width/2),
146 (comp_rect.y + comp_rect.height/2) );
148 cvCircle( dst, center, cvRound(magnitude*1.2), color, 3, CV_AA, 0 );
149 cvLine( dst, center, cvPoint( cvRound( center.x + magnitude*cos(angle*CV_PI/180)),
150 cvRound( center.y - magnitude*sin(angle*CV_PI/180))), color, 3, CV_AA, 0 );
155 int main(int argc, char** argv)
157 IplImage* motion = 0;
158 CvCapture* capture = 0;
160 if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
161 capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );
163 capture = cvCaptureFromFile( argv[1] );
167 cvNamedWindow( "Motion", 1 );
172 if( !cvGrabFrame( capture ))
174 image = cvRetrieveFrame( capture );
180 motion = cvCreateImage( cvSize(image->width,image->height), 8, 3 );
182 motion->origin = image->origin;
186 update_mhi( image, motion, 30 );
187 cvShowImage( "Motion", motion );
189 if( cvWaitKey(10) >= 0 )
192 cvReleaseCapture( &capture );
193 cvDestroyWindow( "Motion" );