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

OpenCV

开发平台:

Visual C++

  1. #include "cv.h"
  2. #include "highgui.h"
  3. #include <stdio.h>
  4. #include <ctype.h>
  5. IplImage *image = 0, *hsv = 0, *hue = 0, *mask = 0, *backproject = 0, *histimg = 0;
  6. CvHistogram *hist = 0;
  7. int backproject_mode = 0;
  8. int select_object = 0;
  9. int track_object = 0;
  10. int show_hist = 1;  
  11. CvPoint origin;
  12. CvRect selection;
  13. CvRect track_window;
  14. CvBox2D track_box;  // tracking 返回的区域 box,带角度
  15. CvConnectedComp track_comp;
  16. int hdims = 48;     // 划分HIST的个数,越高越精确
  17. float hranges_arr[] = {0,180};
  18. float* hranges = hranges_arr;
  19. int vmin = 10, vmax = 256, smin = 30;
  20. void on_mouse( int event, int x, int y, int flags )
  21. {
  22.     if( !image )
  23.         return;
  24.     if( image->origin )
  25.         y = image->height - y;
  26.     if( select_object )
  27.     {
  28.         selection.x = MIN(x,origin.x);
  29.         selection.y = MIN(y,origin.y);
  30.         selection.width = selection.x + CV_IABS(x - origin.x);
  31.         selection.height = selection.y + CV_IABS(y - origin.y);
  32.         
  33.         selection.x = MAX( selection.x, 0 );
  34.         selection.y = MAX( selection.y, 0 );
  35.         selection.width = MIN( selection.width, image->width );
  36.         selection.height = MIN( selection.height, image->height );
  37.         selection.width -= selection.x;
  38.         selection.height -= selection.y;
  39.     }
  40.     switch( event )
  41.     {
  42.     case CV_EVENT_LBUTTONDOWN:
  43.         origin = cvPoint(x,y);
  44.         selection = cvRect(x,y,0,0);
  45.         select_object = 1;
  46.         break;
  47.     case CV_EVENT_LBUTTONUP:
  48.         select_object = 0;
  49.         if( selection.width > 0 && selection.height > 0 )
  50.             track_object = -1;
  51. #ifdef _DEBUG
  52.     printf("n # 鼠标的选择区域:"); 
  53.     printf("n   X = %d, Y = %d, Width = %d, Height = %d",
  54.         selection.x, selection.y, selection.width, selection.height);
  55. #endif
  56.         break;
  57.     }
  58. }
  59. CvScalar hsv2rgb( float hue )
  60. {
  61.     int rgb[3], p, sector;
  62.     static const int sector_data[][3]=
  63.         {{0,2,1}, {1,2,0}, {1,0,2}, {2,0,1}, {2,1,0}, {0,1,2}};
  64.     hue *= 0.033333333333333333333333333333333f;
  65.     sector = cvFloor(hue);
  66.     p = cvRound(255*(hue - sector));
  67.     p ^= sector & 1 ? 255 : 0;
  68.     rgb[sector_data[sector][0]] = 255;
  69.     rgb[sector_data[sector][1]] = 0;
  70.     rgb[sector_data[sector][2]] = p;
  71. #ifdef _DEBUG
  72.     printf("n # Convert HSV to RGB:"); 
  73.     printf("n   HUE = %f", hue);
  74.     printf("n   R = %d, G = %d, B = %d", rgb[0],rgb[1],rgb[2]);
  75. #endif
  76.     return cvScalar(rgb[2], rgb[1], rgb[0],0);
  77. }
  78. int main( int argc, char** argv )
  79. {
  80.     CvCapture* capture = 0;
  81.     IplImage* frame = 0;
  82.     
  83.     if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
  84.         capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );
  85.     else if( argc == 2 )
  86.         capture = cvCaptureFromAVI( argv[1] ); 
  87.     if( !capture )
  88.     {
  89.         fprintf(stderr,"Could not initialize capturing...n");
  90.         return -1;
  91.     }
  92.     printf( "Hot keys: n"
  93.         "tESC - quit the programn"
  94.         "tc - stop the trackingn"
  95.         "tb - switch to/from backprojection viewn"
  96.         "th - show/hide object histogramn"
  97.         "To initialize tracking, select the object with mousen" );
  98.     //cvNamedWindow( "Histogram", 1 );
  99.     cvNamedWindow( "CamShiftDemo", 1 );
  100.     cvSetMouseCallback( "CamShiftDemo", on_mouse, NULL ); // on_mouse 自定义事件
  101.     cvCreateTrackbar( "Vmin", "CamShiftDemo", &vmin, 256, 0 );
  102.     cvCreateTrackbar( "Vmax", "CamShiftDemo", &vmax, 256, 0 );
  103.     cvCreateTrackbar( "Smin", "CamShiftDemo", &smin, 256, 0 );
  104.     for(;;)
  105.     {
  106.         int i, bin_w, c;
  107.         frame = cvQueryFrame( capture );
  108.         if( !frame )
  109.             break;
  110.         if( !image )
  111.         {
  112.             /* allocate all the buffers */
  113.             image = cvCreateImage( cvGetSize(frame), 8, 3 );
  114.             image->origin = frame->origin;
  115.             hsv = cvCreateImage( cvGetSize(frame), 8, 3 );
  116.             hue = cvCreateImage( cvGetSize(frame), 8, 1 );
  117.             mask = cvCreateImage( cvGetSize(frame), 8, 1 );
  118.             backproject = cvCreateImage( cvGetSize(frame), 8, 1 );
  119.             hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 );  // 计算直方图
  120.             histimg = cvCreateImage( cvSize(320,200), 8, 3 );
  121.             cvZero( histimg );
  122.         }
  123.         cvCopy( frame, image, 0 );
  124.         cvCvtColor( image, hsv, CV_BGR2HSV );  // 彩色空间转换 BGR to HSV 
  125.         if( track_object )
  126.         {
  127.             int _vmin = vmin, _vmax = vmax;
  128.             cvInRangeS( hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0),
  129.                         cvScalar(180,256,MAX(_vmin,_vmax),0), mask );  // 得到二值的MASK
  130.             cvSplit( hsv, hue, 0, 0, 0 );  // 只提取 HUE 分量
  131.             if( track_object < 0 )
  132.             {
  133.                 float max_val = 0.f;
  134.                 cvSetImageROI( hue, selection );  // 得到选择区域 for ROI
  135.                 cvSetImageROI( mask, selection ); // 得到选择区域 for mask
  136.                 cvCalcHist( &hue, hist, 0, mask ); // 计算直方图
  137.                 cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );  // 只找最大值
  138.                 cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 ); // 缩放 bin 到区间 [0,255] 
  139.                 cvResetImageROI( hue );  // remove ROI
  140.                 cvResetImageROI( mask );
  141.                 track_window = selection;
  142.                 track_object = 1;
  143.                 cvZero( histimg );
  144.                 bin_w = histimg->width / hdims;  // hdims: 条的个数,则 bin_w 为条的宽度
  145.                 
  146.                 // 画直方图
  147.                 for( i = 0; i < hdims; i++ )
  148.                 {
  149.                     int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 );
  150.                     CvScalar color = hsv2rgb(i*180.f/hdims);
  151.                     cvRectangle( histimg, cvPoint(i*bin_w,histimg->height),
  152.                                  cvPoint((i+1)*bin_w,histimg->height - val),
  153.                                  color, -1, 8, 0 );
  154.                 }
  155.             }
  156.             cvCalcBackProject( &hue, backproject, hist );  // 使用 back project 方法
  157.             cvAnd( backproject, mask, backproject, 0 );
  158.             
  159.             // calling CAMSHIFT 算法模块
  160.             cvCamShift( backproject, track_window,
  161.                         cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),
  162.                         &track_comp, &track_box );
  163.             track_window = track_comp.rect;
  164.             
  165.             if( backproject_mode )
  166.                 cvCvtColor( backproject, image, CV_GRAY2BGR ); // 使用backproject灰度图像
  167.             if( image->origin )
  168.                 track_box.angle = -track_box.angle;
  169.             cvEllipseBox( image, track_box, CV_RGB(255,0,0), 3, CV_AA, 0 );
  170.         }
  171.         
  172.         if( select_object && selection.width > 0 && selection.height > 0 )
  173.         {
  174.             cvSetImageROI( image, selection );
  175.             cvXorS( image, cvScalarAll(255), image, 0 );
  176.             cvResetImageROI( image );
  177.         }
  178.         cvShowImage( "CamShiftDemo", image );
  179.         cvShowImage( "Histogram", histimg );
  180.         c = cvWaitKey(10);
  181.         if( c == 27 )
  182.             break;  // exit from for-loop
  183.         switch( c )
  184.         {
  185.         case 'b':
  186.             backproject_mode ^= 1;
  187.             break;
  188.         case 'c':
  189.             track_object = 0;
  190.             cvZero( histimg );
  191.             break;
  192.         case 'h':
  193.             show_hist ^= 1;
  194.             if( !show_hist )
  195.                 cvDestroyWindow( "Histogram" );
  196.             else
  197.                 cvNamedWindow( "Histogram", 1 );
  198.             break;
  199.         default:
  200.             ;
  201.         }
  202.     }
  203.     cvReleaseCapture( &capture );
  204.     cvDestroyWindow("CamShiftDemo");
  205.     return 0;
  206. }