motempl.c
上传用户:banwdc
上传日期:2016-06-25
资源大小:2871k
文件大小:6k
源码类别:

OpenCV

开发平台:

Visual C++

  1. #include "cv.h"
  2. #include "highgui.h"
  3. #include <time.h>
  4. #include <math.h>
  5. #include <ctype.h>
  6. #include <stdio.h>
  7. // various tracking parameters (in seconds)
  8. const double MHI_DURATION = 0.5;
  9. const double MAX_TIME_DELTA = 0.5;
  10. const double MIN_TIME_DELTA = 0.05;
  11. // 用于运动检测的循环帧数,与机器速度以及FPS设置有关
  12. const int N = 2;
  13. // ring image buffer
  14. IplImage **buf = 0;
  15. int last = 0;
  16. // temporary images
  17. IplImage *mhi = 0; // MHI: motion history image
  18. IplImage *orient = 0; // orientation
  19. IplImage *mask = 0; // valid orientation mask
  20. IplImage *segmask = 0; // motion segmentation map
  21. CvMemStorage* storage = 0; // temporary storage
  22. // parameters:
  23. //  img - input video frame
  24. //  dst - resultant motion picture
  25. //  args - optional parameters
  26. void  update_mhi( IplImage* img, IplImage* dst, int diff_threshold )
  27. {
  28.     double timestamp = clock()/1000.; // get current time in seconds
  29.     CvSize size = cvSize(img->width,img->height); // get current frame size
  30.     int i, idx1 = last, idx2;
  31.     IplImage* silh;
  32.     CvSeq* seq;
  33.     CvRect comp_rect;
  34.     double count;
  35.     double angle;
  36.     CvPoint center;
  37.     double magnitude;          
  38.     CvScalar color;
  39.     // allocate images at the beginning or
  40.     // reallocate them if the frame size is changed
  41.     if( !mhi || mhi->width != size.width || mhi->height != size.height ) 
  42.     {
  43.         if( buf == 0 ) 
  44.         {
  45.             buf = (IplImage**)malloc(N*sizeof(buf[0]));
  46.             memset( buf, 0, N*sizeof(buf[0]));
  47.         }
  48.         
  49.         for( i = 0; i < N; i++ ) 
  50.         {
  51.             cvReleaseImage( &buf[i] );
  52.             buf[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 );
  53.             cvZero( buf[i] );
  54.         }
  55.         cvReleaseImage( &mhi );
  56.         cvReleaseImage( &orient );
  57.         cvReleaseImage( &segmask );
  58.         cvReleaseImage( &mask );
  59.         
  60.         mhi = cvCreateImage( size, IPL_DEPTH_32F, 1 );
  61.         cvZero( mhi ); // clear MHI at the beginning
  62.         orient = cvCreateImage( size, IPL_DEPTH_32F, 1 );
  63.         segmask = cvCreateImage( size, IPL_DEPTH_32F, 1 );
  64.         mask = cvCreateImage( size, IPL_DEPTH_8U, 1 );
  65.     }
  66.     cvCvtColor( img, buf[last], CV_BGR2GRAY ); // convert frame to grayscale
  67.     idx2 = (last + 1) % N; // index of (last - (N-1))th frame
  68.     last = idx2;
  69.     silh = buf[idx2];
  70.     // 相邻两帧的差
  71.     cvAbsDiff( buf[idx1], buf[idx2], silh ); // get difference between frames
  72.     
  73.     // 对差图像做二值化
  74.     cvThreshold( silh, silh, diff_threshold, 1, CV_THRESH_BINARY ); // and threshold it
  75.     cvUpdateMotionHistory( silh, mhi, timestamp, MHI_DURATION ); // update MHI
  76.     // convert MHI to blue 8u image
  77.     // cvCvtScale的第四个参数 shift = (MHI_DURATION - timestamp)*255./MHI_DURATION
  78.     // 控制帧差的消失速率
  79. cvCvtScale( mhi, mask, 255./MHI_DURATION,
  80.  (MHI_DURATION - timestamp)*255./MHI_DURATION );
  81.     cvZero( dst );
  82.     cvCvtPlaneToPix(mask, 0, 0, 0, dst );  // B,G,R,0 -> dist : convert to BLUE image
  83.     // 计算运动的梯度方向以及正确的方向掩模mask
  84.     // Filter size = 3
  85. cvCalcMotionGradient( mhi, mask, orient, 
  86. MAX_TIME_DELTA, MIN_TIME_DELTA, 3 ); 
  87.     
  88.     if( !storage )
  89.         storage = cvCreateMemStorage(0);
  90.     else
  91.         cvClearMemStorage(storage);
  92.     
  93.     // 运动分割: 获得运动部件的连续序列
  94.     // segmask is marked motion components map. It is not used further
  95.     seq = cvSegmentMotion( mhi, segmask, storage, timestamp, MAX_TIME_DELTA );
  96.     // iterate through the motion components,
  97.     // One more iteration (i == -1) corresponds to the whole image (global motion)
  98.     for( i = 0; i < seq->total; i++ ) 
  99.     {
  100.         if( i < 0 ) { // case of the whole image,对整幅图像做操作
  101.             comp_rect = cvRect( 0, 0, size.width, size.height );
  102.             color = CV_RGB(255,255,255);  // white color
  103.             magnitude = 100;  // 画线长度以及圆半径的大小控制
  104.         }
  105.         else { // i-th motion component
  106.             comp_rect = ((CvConnectedComp*)cvGetSeqElem( seq, i ))->rect;
  107. // 去掉小的部分
  108. if( comp_rect.width + comp_rect.height < 100 ) 
  109.                 continue;
  110.             color = CV_RGB(255,0,0);    // red color
  111.             magnitude = 30;
  112.             //if(seq->total > 0) MessageBox(NULL,"Motion Detected",NULL,0);
  113.         }
  114.         // select component ROI
  115.         cvSetImageROI( silh, comp_rect );
  116.         cvSetImageROI( mhi, comp_rect );
  117.         cvSetImageROI( orient, comp_rect );
  118.         cvSetImageROI( mask, comp_rect );
  119.         // 在选择的区域内, 计算运动方向
  120.         angle = cvCalcGlobalOrientation( orient, mask, mhi, timestamp,
  121.  MHI_DURATION);
  122.         angle = 360.0 - angle;  // adjust for images with top-left origin
  123.         // 在轮廓内计算点数
  124.         // Norm(L1) = sum of total pixel values
  125.         count = cvNorm( silh, 0, CV_L1, 0 ); 
  126.         // The function cvResetImageROI releases image ROI
  127.         cvResetImageROI( mhi );
  128.         cvResetImageROI( orient );
  129.         cvResetImageROI( mask );
  130.         cvResetImageROI( silh );
  131.         // check for the case of little motion
  132.         if( count < comp_rect.width*comp_rect.height * 0.05 )  // five percent of pixel
  133.             continue;
  134.         // draw a clock with arrow indicating the direction
  135.         center = cvPoint( (comp_rect.x + comp_rect.width/2),
  136.                           (comp_rect.y + comp_rect.height/2) );
  137.         cvCircle( dst, center, cvRound(magnitude*1.2), color, 3, CV_AA, 0 );
  138.         cvLine( dst, center, cvPoint( cvRound( center.x + 
  139. magnitude*cos(angle*CV_PI/180)),
  140.                  cvRound( center.y - magnitude*sin(angle*CV_PI/180))), 
  141. color, 3, CV_AA, 0 );
  142.     }
  143. }
  144. int main(int argc, char** argv)
  145. {
  146.     IplImage* motion = 0;
  147.     CvCapture* capture = 0;
  148.     
  149.     if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
  150.         capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );
  151.     else if( argc == 2 )
  152.         capture = cvCaptureFromAVI( argv[1] ); 
  153.     if( capture )
  154.     {
  155.         cvNamedWindow( "Motion", 1 );
  156.         for(;;)
  157.         {
  158.             IplImage* image;
  159.             if( !cvGrabFrame( capture ))
  160.                 break;
  161.             image = cvRetrieveFrame( capture );
  162.             if( image )
  163.             {
  164.                 if( !motion )
  165.                 {
  166. motion = cvCreateImage( cvSize(image->width,image->height), 
  167. 8, 3 );
  168.                     cvZero( motion );
  169.                     motion->origin = image->origin;
  170.                 }
  171.             }
  172.             update_mhi( image, motion, 60 );
  173.             cvShowImage( "Motion", motion );
  174.             if( cvWaitKey(10) >= 0 )
  175.                 break;
  176.         }
  177.         cvReleaseCapture( &capture );
  178.         cvDestroyWindow( "Motion" );
  179.     }
  180.     return 0;
  181. }