2 #pragma package <opencv>
5 #define CV_NO_BACKWARD_COMPATIBILITY
8 // motion templates sample code
17 // various tracking parameters (in seconds)
18 const double MHI_DURATION = 1;
19 const double MAX_TIME_DELTA = 0.5;
20 const double MIN_TIME_DELTA = 0.05;
21 // number of cyclic frame buffer used for motion detection
22 // (should, probably, depend on FPS)
30 IplImage *mhi = 0; // MHI
31 IplImage *orient = 0; // orientation
32 IplImage *mask = 0; // valid orientation mask
33 IplImage *segmask = 0; // motion segmentation map
34 CvMemStorage* storage = 0; // temporary storage
37 // img - input video frame
38 // dst - resultant motion picture
39 // args - optional parameters
40 void update_mhi( IplImage* img, IplImage* dst, int diff_threshold )
42 double timestamp = (double)clock()/CLOCKS_PER_SEC; // get current time in seconds
43 CvSize size = cvSize(img->width,img->height); // get current frame size
44 int i, idx1 = last, idx2;
54 // allocate images at the beginning or
55 // reallocate them if the frame size is changed
56 if( !mhi || mhi->width != size.width || mhi->height != size.height ) {
58 buf = (IplImage**)malloc(N*sizeof(buf[0]));
59 memset( buf, 0, N*sizeof(buf[0]));
62 for( i = 0; i < N; i++ ) {
63 cvReleaseImage( &buf[i] );
64 buf[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 );
67 cvReleaseImage( &mhi );
68 cvReleaseImage( &orient );
69 cvReleaseImage( &segmask );
70 cvReleaseImage( &mask );
72 mhi = cvCreateImage( size, IPL_DEPTH_32F, 1 );
73 cvZero( mhi ); // clear MHI at the beginning
74 orient = cvCreateImage( size, IPL_DEPTH_32F, 1 );
75 segmask = cvCreateImage( size, IPL_DEPTH_32F, 1 );
76 mask = cvCreateImage( size, IPL_DEPTH_8U, 1 );
79 cvCvtColor( img, buf[last], CV_BGR2GRAY ); // convert frame to grayscale
81 idx2 = (last + 1) % N; // index of (last - (N-1))th frame
85 cvAbsDiff( buf[idx1], buf[idx2], silh ); // get difference between frames
87 cvThreshold( silh, silh, diff_threshold, 1, CV_THRESH_BINARY ); // and threshold it
88 cvUpdateMotionHistory( silh, mhi, timestamp, MHI_DURATION ); // update MHI
90 // convert MHI to blue 8u image
91 cvCvtScale( mhi, mask, 255./MHI_DURATION,
92 (MHI_DURATION - timestamp)*255./MHI_DURATION );
94 cvMerge( mask, 0, 0, 0, dst );
96 // calculate motion gradient orientation and valid orientation mask
97 cvCalcMotionGradient( mhi, mask, orient, MAX_TIME_DELTA, MIN_TIME_DELTA, 3 );
100 storage = cvCreateMemStorage(0);
102 cvClearMemStorage(storage);
104 // segment motion: get sequence of motion components
105 // segmask is marked motion components map. It is not used further
106 seq = cvSegmentMotion( mhi, segmask, storage, timestamp, MAX_TIME_DELTA );
108 // iterate through the motion components,
109 // One more iteration (i == -1) corresponds to the whole image (global motion)
110 for( i = -1; i < seq->total; i++ ) {
112 if( i < 0 ) { // case of the whole image
113 comp_rect = cvRect( 0, 0, size.width, size.height );
114 color = CV_RGB(255,255,255);
117 else { // i-th motion component
118 comp_rect = ((CvConnectedComp*)cvGetSeqElem( seq, i ))->rect;
119 if( comp_rect.width + comp_rect.height < 100 ) // reject very small components
121 color = CV_RGB(255,0,0);
125 // select component ROI
126 cvSetImageROI( silh, comp_rect );
127 cvSetImageROI( mhi, comp_rect );
128 cvSetImageROI( orient, comp_rect );
129 cvSetImageROI( mask, comp_rect );
131 // calculate orientation
132 angle = cvCalcGlobalOrientation( orient, mask, mhi, timestamp, MHI_DURATION);
133 angle = 360.0 - angle; // adjust for images with top-left origin
135 count = cvNorm( silh, 0, CV_L1, 0 ); // calculate number of points within silhouette ROI
137 cvResetImageROI( mhi );
138 cvResetImageROI( orient );
139 cvResetImageROI( mask );
140 cvResetImageROI( silh );
142 // check for the case of little motion
143 if( count < comp_rect.width*comp_rect.height * 0.05 )
146 // draw a clock with arrow indicating the direction
147 center = cvPoint( (comp_rect.x + comp_rect.width/2),
148 (comp_rect.y + comp_rect.height/2) );
150 cvCircle( dst, center, cvRound(magnitude*1.2), color, 3, CV_AA, 0 );
151 cvLine( dst, center, cvPoint( cvRound( center.x + magnitude*cos(angle*CV_PI/180)),
152 cvRound( center.y - magnitude*sin(angle*CV_PI/180))), color, 3, CV_AA, 0 );
157 int main(int argc, char** argv)
159 IplImage* motion = 0;
160 CvCapture* capture = 0;
162 if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
163 capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );
165 capture = cvCaptureFromFile( argv[1] );
169 cvNamedWindow( "Motion", 1 );
173 IplImage* image = cvQueryFrame( capture );
179 motion = cvCreateImage( cvSize(image->width,image->height), 8, 3 );
181 motion->origin = image->origin;
184 update_mhi( image, motion, 30 );
185 cvShowImage( "Motion", motion );
187 if( cvWaitKey(10) >= 0 )
190 cvReleaseCapture( &capture );
191 cvDestroyWindow( "Motion" );