meanshift 与 camshift 跟踪算法比较

 

MeanShift Algorithm

思想很简单:利用概率密度的梯度爬升来寻找局部最优...具体参考文献:

[1]The Estimation of the Gradient of a Density Function, with Applications in Pattern Recognition   (1975)

[2]Mean shift, mode seeking, and clustering (1995)

[3]Mean Shift: a robust approach toward feature space analysis (2002)

[4]Real-time tracking of non-rigid objects using mean shift (2000)

[5]Mean-shift Blob Tracking through Scale Space (2003)

[6]An algorithm for data-driven bandwidth selection(2003)

 

对于OpenCV的Meanshift算法 貌似只是简化成了一个重心跟踪法,没有引入核函数与巴氏系数....

怪不得跟踪的效果那么差...

 

 

具体计算过程如下:

 

1.计算区域内0阶矩
for(int i=0;i<height;i++)
  for(int j=0;j<width;j++)
     M00+=I(i,j)
2.区域内1阶矩:
for(int i=0;i<height;i++)
  for(int j=0;j<width;j++)
  {
    M10+=i*I(i,j);
    M01+=j*I(i,j);
  }
3.则Mass Center为:
Xc=M10/M00; Yc=M01/M00

 

具体的CVMEANSHIFT算法可以分为以下4步:
1.选择窗的大小和初始位置.
2.计算此时窗口内的Mass Center.
3.调整窗口的中心到Mass Center.
4.重复2和3,直到窗口中心"会聚",即每次窗口移动的距离小于一定的阈值,或者迭代次数达到设定值。

 

 

int cvMeanShift(IplImage* imgprob,CvRect windowIn,
                    CvTermCriteria criteria,CvConnectedComp* out);

 

  1. 函数说明:  
  2. 需要的参数为:  
  3. 1.IplImage* imgprob:2D概率分布图像,传入;  
  4. 2.CvRect windowIn:初始的窗口,传入;  
  5. 3.CvTermCriteria criteria:停止迭代的标准,传入;  
  6. 4.CvConnectedComp* out:查询结果,传出。  
  7. (注:构造CvTermCriteria变量需要三个参数,一个是类型,另一个是迭代的最大次数,最后一个表示特定的阈值。例如可以这样构造criteria:criteria=cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,10,0.1)。)  
  8.   
  9.    
  10.      Parameters:  
  11.        imgProb     - 2D object probability distribution  
  12.        windowIn    - CvRect of CAMSHIFT Window intial size  
  13.        numIters    - If CAMSHIFT iterates this many times, stop  
  14.        windowOut   - Location, height and width of converged CAMSHIFT window  
  15.        len         - If != NULL, return equivalent len  
  16.        width       - If != NULL, return equivalent width  
  17.        itersUsed   - Returns number of iterations CAMSHIFT took to converge  
  18.      Returns:  
  19.        The function itself returns the area found  
  20.    
  21.    
  22.   
  23.    
  24.   
  25.    
  26.   
  27. int cvMeanShift( const void* imgProb, CvRect windowIn,  
  28.    CvTermCriteria criteria, CvConnectedComp* comp )  
  29. {  
  30.  CvMoments moments;  
  31.  int    i = 0, eps;  
  32.  CvMat  stub, *mat = (CvMat*)imgProb;  
  33.  CvMat  cur_win;  
  34.  CvRect cur_rect = windowIn;  
  35.    
  36.  CV_FUNCNAME( "cvMeanShift" );  
  37.    
  38.  if( comp )  
  39.   comp->rect = windowIn;  
  40.    
  41.  moments.m00 = moments.m10 = moments.m01 = 0;  
  42.    
  43.  __BEGIN__;  
  44.    
  45.  CV_CALL( mat = cvGetMat( mat, &stub ));  
  46.    
  47.   
  48.    
  49.  if( windowIn.height <= 0 || windowIn.width <= 0 )  
  50.   CV_ERROR( CV_StsBadArg, "Input window has non-positive sizes" );  
  51.    
  52.  if( windowIn.x < 0 || windowIn.x + windowIn.width > mat->cols ||  
  53.   windowIn.y < 0 || windowIn.y + windowIn.height > mat->rows )  
  54.   CV_ERROR( CV_StsBadArg, "Initial window is not inside the image ROI" );  
  55.    
  56.  CV_CALL( criteria = cvCheckTermCriteria( criteria, 1., 100 ));  
  57.    
  58.  eps = cvRound( criteria.epsilon * criteria.epsilon );  
  59.    
  60.  for( i = 0; i < criteria.max_iter; i++ )  
  61.  {  
  62.   int dx, dy, nx, ny;  
  63.   double inv_m00;  
  64.     
  65.   CV_CALL( cvGetSubRect( mat, &cur_win, cur_rect ));  
  66.   CV_CALL( cvMoments( &cur_win, &moments ));  
  67.     
  68.     
  69.   if( fabs(moments.m00) < DBL_EPSILON )  
  70.    break;  
  71.     
  72.   inv_m00 = moments.inv_sqrt_m00*moments.inv_sqrt_m00;  
  73.   dx = cvRound( moments.m10 * inv_m00 - windowIn.width*0.5 );  
  74.   dy = cvRound( moments.m01 * inv_m00 - windowIn.height*0.5 );  
  75.     
  76.   nx = cur_rect.x + dx;  
  77.   ny = cur_rect.y + dy;  
  78.     
  79.   if( nx < 0 )  
  80.    nx = 0;  
  81.   else if( nx + cur_rect.width > mat->cols )  
  82.    nx = mat->cols - cur_rect.width;  
  83.     
  84.   if( ny < 0 )  
  85.    ny = 0;  
  86.   else if( ny + cur_rect.height > mat->rows )  
  87.    ny = mat->rows - cur_rect.height;  
  88.     
  89.   dx = nx - cur_rect.x;  
  90.   dy = ny - cur_rect.y;  
  91.   cur_rect.x = nx;  
  92.   cur_rect.y = ny;  
  93.   
  94.     
  95.     
  96.   if( dx*dx + dy*dy < eps )  
  97.    break;  
  98.  }  
  99.    
  100.  __END__;  
  101.    
  102.  if( comp )  
  103.  {  
  104.   comp->rect = cur_rect;  
  105.   comp->area = (float)moments.m00;  
  106.  }  
  107.    
  108.  return i;  
  109.  }  
  110.    

 


Camshift Algorithm

它是MeanShift算法的改进,称为连续自适应的MeanShift算法,CamShift算法的全称是"Continuously Apaptive Mean-SHIFT",它的基本思想是视频图像的所有帧作MeanShift运算,并将上一帧的结果(即Search Window的中心和大小)作为下一帧MeanShift算法的Search Window的初始值,如此迭代下去。

 

Camshift 是由Meanshift 推倒而來 Meanshift主要是用在單張影像上,但
是獨立一張影像分析對追蹤而言並無意義,Camshift 就是利用MeanShift的方
法,對影像串列進行分析。
(1) 首先在影像串列中選擇ㄧ區域。
(2) 計算此區域的顏色2D機率分布。
(3) 用MeanShift演算法來收斂欲追蹤的區域。
(4) 集中收斂的區域,並標示之。
(5) 每個frame重複(3)(4)。

 

 

 

Camshift 关键就在于当目标的大小发生改变的时候,此算法可以自适应调整目标区域继续跟踪。没什么多说的,给出源码吧,里面有部分代码是计算代码执行时间的,不需要的可以去掉。

 

如果要详细了解,去看下这篇参考文献吧:

Bradski, Computer Video Face Tracking for use in a Perceptual User Interface. Intel Technology Journal, Q2, 1998.

 

 

  1. 函数说明:  
  2.   
  3.   
  4.      Parameters:  
  5.        imgProb     - 2D object probability distribution  
  6.        windowIn    - CvRect of CAMSHIFT Window intial size  
  7.        criteria    - criteria of stop finding window  
  8.        windowOut   - Location, height and width of converged CAMSHIFT window  
  9.        orientation - If != NULL, return distribution orientation  
  10.        len         - If != NULL, return equivalent len  
  11.        width       - If != NULL, return equivalent width  
  12.        area        - sum of all elements in result window  
  13.        itersUsed   - Returns number of iterations CAMSHIFT took to converge  
  14.      Returns:  
  15.       The function itself returns the area found  
  16.    
  17.   
  18.    
  19.   
  20.    
  21.   
  22.    
  23.   
  24. int cvCamShift( const void* imgProb, CvRect windowIn,  
  25.     CvTermCriteria criteria,  
  26.     CvConnectedComp* _comp,  
  27.     CvBox2D* box )  
  28.  {  
  29.   QueryPerformanceFrequency(&freq);  
  30.   QueryPerformanceCounter(&start1);  
  31.   
  32.   const int TOLERANCE = 10;  
  33.   CvMoments moments;  
  34.   double m00 = 0, m10, m01, mu20, mu11, mu02, inv_m00;  
  35.   double a, b, c, xc, yc;  
  36.   double rotate_a, rotate_c;  
  37.   double theta = 0, square;  
  38.   double cs, sn;  
  39.   double length = 0, width = 0;  
  40.   int itersUsed = 0;  
  41.   CvConnectedComp comp;  
  42.   CvMat  cur_win, stub, *mat = (CvMat*)imgProb;  
  43.   
  44.   CV_FUNCNAME( "cvCamShift" );  
  45.   
  46.   comp.rect = windowIn;  
  47.   
  48.   __BEGIN__;  
  49.   
  50.   CV_CALL( mat = cvGetMat( mat, &stub ));  
  51.   
  52.   CV_CALL( itersUsed = cvMeanShift( mat, windowIn, criteria, &comp ));  
  53.   windowIn = comp.rect;  
  54.   
  55.     
  56.   windowIn.x -= TOLERANCE;  
  57.   if( windowIn.x < 0 )  
  58.    windowIn.x = 0;  
  59.   
  60.   windowIn.y -= TOLERANCE;  
  61.   if( windowIn.y < 0 )  
  62.    windowIn.y = 0;  
  63.   
  64.   windowIn.width += 2 * TOLERANCE;  
  65.   if( windowIn.x + windowIn.width > mat->width )  
  66.    windowIn.width = mat->width - windowIn.x;  
  67.   
  68.   windowIn.height += 2 * TOLERANCE;  
  69.   if( windowIn.y + windowIn.height > mat->height )  
  70.    windowIn.height = mat->height - windowIn.y;  
  71.   
  72.   CV_CALL( cvGetSubRect( mat, &cur_win, windowIn ));  
  73.   
  74.     
  75.   CV_CALL( cvMoments( &cur_win, &moments ));  
  76.   
  77.   m00 = moments.m00;  
  78.   m10 = moments.m10;  
  79.   m01 = moments.m01;  
  80.   mu11 = moments.mu11;  
  81.   mu20 = moments.mu20;  
  82.   mu02 = moments.mu02;  
  83.   
  84.   if( fabs(m00) < DBL_EPSILON )  
  85.    EXIT;  
  86.   
  87.   inv_m00 = 1. / m00;  
  88.   xc = cvRound( m10 * inv_m00 + windowIn.x );  
  89.   yc = cvRound( m01 * inv_m00 + windowIn.y );  
  90.   a = mu20 * inv_m00;  
  91.   b = mu11 * inv_m00;  
  92.   c = mu02 * inv_m00;  
  93.   
  94.     
  95.   square = sqrt( 4 * b * b + (a - c) * (a - c) );  
  96.   
  97.     
  98.   theta = atan2( 2 * b, a - c + square );  
  99.   
  100.     
  101.   cs = cos( theta );  
  102.   sn = sin( theta );  
  103.   
  104.   rotate_a = cs * cs * mu20 + 2 * cs * sn * mu11 + sn * sn * mu02;  
  105.   rotate_c = sn * sn * mu20 - 2 * cs * sn * mu11 + cs * cs * mu02;  
  106.   length = sqrt( rotate_a * inv_m00 ) * 4;  
  107.   width = sqrt( rotate_c * inv_m00 ) * 4;  
  108.   
  109.     
  110.   if( length < width )  
  111.   {  
  112.    double t;  
  113.      
  114.    CV_SWAP( length, width, t );  
  115.    CV_SWAP( cs, sn, t );  
  116.    theta = CV_PI*0.5 - theta;  
  117.   }  
  118.   
  119.     
  120.   if( _comp || box )  
  121.   {  
  122.    int t0, t1;  
  123.    int _xc = cvRound( xc );  
  124.    int _yc = cvRound( yc );  
  125.   
  126.    t0 = cvRound( fabs( length * cs ));  
  127.    t1 = cvRound( fabs( width * sn ));  
  128.   
  129.    t0 = MAX( t0, t1 ) + 2;  
  130.    comp.rect.width = MIN( t0, (mat->width - _xc) * 2 );  
  131.   
  132.    t0 = cvRound( fabs( length * sn ));  
  133.    t1 = cvRound( fabs( width * cs ));  
  134.   
  135.    t0 = MAX( t0, t1 ) + 2;  
  136.    comp.rect.height = MIN( t0, (mat->height - _yc) * 2 );  
  137.   
  138.    comp.rect.x = MAX( 0, _xc - comp.rect.width / 2 );  
  139.    comp.rect.y = MAX( 0, _yc - comp.rect.height / 2 );  
  140.   
  141.    comp.rect.width = MIN( mat->width - comp.rect.x, comp.rect.width );  
  142.    comp.rect.height = MIN( mat->height - comp.rect.y, comp.rect.height );  
  143.    comp.area = (float) m00;  
  144.   }  
  145.   
  146.   __END__;  
  147.   
  148.   if( _comp )  
  149.    *_comp = comp;  
  150.     
  151.   if( box )  
  152.   {  
  153.    box->size.height = (float)length;  
  154.    box->size.width = (float)width;  
  155.    box->angle = (float)(theta*180./CV_PI);  
  156.    box->center = cvPoint2D32f( comp.rect.x + comp.rect.width*0.5f,  
  157.           comp.rect.y + comp.rect.height*0.5f);  
  158.   }  
  159.   
  160.   
  161.   QueryPerformanceCounter(&end1);  
  162.   
  163.   time_origin<<(double)(end1.QuadPart - start1.QuadPart) / (double)freq.QuadPart<<endl;  
  164.   
  165.   return itersUsed;  
  166.   
  167. }  

 

 

对于OPENCV中的CAMSHIFT例子,是通过计算目标HSV空间下的HUE分量直方图,通过直方图反向投影得到目标像素的概率分布,然后通过调用CV库中的CAMSHIFT算法,自动跟踪并调整目标窗口的中心位置与大小。

 

这个算法对于纯色物体在黑白背景下的跟踪效果是很好的,但是如果背景的颜色与目标相近,或者目标附近有与目标的色调相近的算法比较物体,则CAMSHIFT会自动将其包括在内,导致跟踪窗口扩大,甚至有时会将跟踪窗口扩大到整个视频框架。

 

昨天看Learning OpenCV 看完了第十章,课后习题里有题就是将camshift改成meanshift算法比较一下结果,我自己改了一下,用meanshift的矩形框跟踪物体,由于meanshift不会改变核窗口的大小,所以矩形框当然是不变的...

 

与camshift比较了一下,由于都是通过H直方图反向投影的算法,实际是大差不差的,实验证明,对于较远的小的目标,使用meanshift算法比较好,因为目标大小一般不变,而且窗口不容易受外界影响,对于近距离的目标,尺寸会与镜头距离的远近而改变的,使用camshift可以自适应的改变。

 

Learning OpenCV 中也提到了可以使用两种方法结合来加强跟踪的鲁棒性,我个人觉得这两种方法其实没什么根本区别,也就不存在什么结合的问题了 呵呵。

 

下面是修改的代码 选取目标采用了蓝色方框 跟踪的目标采用了红色方框

 

 

  1. //---------------------------------------------------------------------------  
  2. #include <vcl.h>  
  3. //-------open cv macro begin-------------  
  4. #ifdef _CH_  
  5. #pragma package <opencv>  
  6. #endif  
  7.   
  8. #define phi2xy(mat)                                                  /  
  9.   cvPoint( cvRound(img->width/2 + img->width/3*cos(mat->data.fl[0])),/  
  10.     cvRound( img->height/2 - img->width/3*sin(mat->data.fl[0])) )  
  11.   
  12.    
  13.   
  14. #include <stdio.h>  
  15. #include <iostream.h>  
  16. #include <fstream.h>  
  17. #include "cv.h"  
  18. #include "highgui.h"  
  19. //-------open cv macro end-------------  
  20.   
  21. #pragma hdrstop  
  22.    
  23. #include "Unit1.h"  
  24. //---------------------------------------------------------------------------  
  25. #pragma package(smart_init)  
  26. #pragma resource "*.dfm"  
  27. TForm1 *Form1;  
  28.   
  29.   
  30. IplImage *image = 0, *hsv = 0, *hue = 0, *mask = 0, *backproject = 0, *histimg = 0;  
  31. CvHistogram *hist = 0;  
  32.   
  33. int backproject_mode = 0;  
  34. int select_object = 0;  
  35. int track_object = 0;  
  36. int show_hist = 1;  
  37. CvPoint origin;  
  38. CvRect selection;  
  39. CvRect track_window;  
  40. CvBox2D track_box;  
  41. CvConnectedComp track_comp;  
  42. int hdims = 256;  
  43. float hranges_arr[] = {0,180};  
  44. float* hranges = hranges_arr;  
  45. int vmin = 10, vmax = 256, smin = 30;  
  46.   
  47.    
  48.   
  49.  //---------------------------------------------------------------------------  
  50.   
  51.   
  52. CvSize cvGetSize( IplImage *img )  
  53. {  
  54.  CvSize aa;  
  55.  aa.width=img->width;  
  56.  aa.height=img->height;  
  57.  return aa;  
  58. }  
  59.   
  60.    
  61.   
  62.    
  63.   
  64.   
  65. //---------------------------------------------------------------------------  
  66. __fastcall TForm1::TForm1(TComponent* Owner)  
  67.         : TForm(Owner)  
  68. {  
  69. }  
  70.   
  71. //---------------------------------------------------------------------------  
  72.   
  73.   
  74. void on_mouse( int event, int x, int y, int flags, void* param )  
  75. {  
  76.     if( !image )  
  77.         return;  
  78.   
  79.     if( image->origin )  
  80.         y = image->height - y;  
  81.   
  82.     if( select_object )  
  83.     {  
  84.         selection.x = MIN(x,origin.x);  
  85.         selection.y = MIN(y,origin.y);  
  86.         selection.width = selection.x + CV_IABS(x - origin.x);  
  87.         selection.height = selection.y + CV_IABS(y - origin.y);  
  88.           
  89.         selection.x = MAX( selection.x, 0 );  
  90.         selection.y = MAX( selection.y, 0 );  
  91.         selection.width = MIN( selection.width, image->width );  
  92.         selection.height = MIN( selection.height, image->height );  
  93.         selection.width -= selection.x;  
  94.         selection.height -= selection.y;  
  95.     }  
  96.   
  97.     switch( event )  
  98.     {  
  99.     case CV_EVENT_LBUTTONDOWN:  
  100.         origin = cvPoint(x,y);  
  101.         selection = cvRect(x,y,0,0);  
  102.         select_object = 1;  
  103.         break;  
  104.     case CV_EVENT_LBUTTONUP:  
  105.         select_object = 0;  
  106.         if( selection.width > 0 && selection.height > 0 )  
  107.             track_object = -1;  
  108.         break;  
  109.     }  
  110. }  
  111.   
  112.   
  113. CvScalar hsv2rgb( float hue )  
  114. {  
  115.     int rgb[3], p, sector;  
  116.     static const int sector_data[][3]=  
  117.         {{0,2,1}, {1,2,0}, {1,0,2}, {2,0,1}, {2,1,0}, {0,1,2}};  
  118.     hue *= 0.033333333333333333333333333333333f;  
  119.     sector = cvFloor(hue);  
  120.     p = cvRound(255*(hue - sector));  
  121.     p ^= sector & 1 ? 255 : 0;  
  122.   
  123.     rgb[sector_data[sector][0]] = 255;  
  124.     rgb[sector_data[sector][1]] = 0;  
  125.     rgb[sector_data[sector][2]] = p;  
  126.   
  127.     return cvScalar(rgb[2], rgb[1], rgb[0],0);  
  128. }  
  129.   
  130.   
  131. //---------------------------------------------------------------------------  
  132.   
  133.    
  134.   
  135. void __fastcall TForm1::Button1Click(TObject *Sender)  
  136. {  
  137.   CvCapture* capture = 0;  
  138.   
  139.        // capture = cvCaptureFromCAM(  0 );  
  140.   
  141.     capture = cvCaptureFromAVI("video.avi" );  
  142.     ShowMessage( "Hot keys: /n"  
  143.         "/tESC - quit the program/n"  
  144.         "/tc - stop the tracking/n"  
  145.         "/tb - switch to/from backprojection view/n"  
  146.         "/th - show/hide object histogram/n"  
  147.         "To initialize tracking, select the object with mouse/n" );  
  148.   
  149.     cvNamedWindow( "Histogram", 1 );  
  150.     cvNamedWindow( "CamShiftDemo", 1 );  
  151.     cvSetMouseCallback( "CamShiftDemo", on_mouse, 0 );  
  152.     cvCreateTrackbar( "Vmin""CamShiftDemo", &vmin, 256, 0 );  
  153.     cvCreateTrackbar( "Vmax""CamShiftDemo", &vmax, 256, 0 );  
  154.     cvCreateTrackbar( "Smin""CamShiftDemo", &smin, 256, 0 );  
  155.   
  156.     for(;;)  
  157.     {  
  158.         IplImage* frame = 0;  
  159.         int i, bin_w, c;  
  160.   
  161.         frame = cvQueryFrame( capture );  
  162.         if( !frame )  
  163.             break;  
  164.   
  165.         if( !image )  
  166.         {  
  167.             /* allocate all the buffers */  
  168.             image = cvCreateImage( cvGetSize(frame), 8, 3 );  
  169.             image->origin = frame->origin;  
  170.             hsv = cvCreateImage( cvGetSize(frame), 8, 3 );  
  171.             hue = cvCreateImage( cvGetSize(frame), 8, 1 );  
  172.             mask = cvCreateImage( cvGetSize(frame), 8, 1 );  
  173.             backproject = cvCreateImage( cvGetSize(frame), 8, 1 );  
  174.             hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 );  
  175.             histimg = cvCreateImage( cvSize(320,200), 8, 3 );  
  176.             cvZero( histimg );  
  177.         }  
  178.   
  179.         cvCopy( frame, image, 0 );  
  180.         cvCvtColor( image, hsv, CV_BGR2HSV );  
  181.   
  182.         if( track_object )  
  183.         {  
  184.             int _vmin = vmin, _vmax = vmax;  
  185.   
  186.             cvInRangeS( hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0),  
  187.                         cvScalar(180,256,MAX(_vmin,_vmax),0), mask );  
  188.             cvSplit( hsv, hue, 0, 0, 0 );  
  189.   
  190.             if( track_object < 0 )  
  191.             {  
  192.                 float max_val = 0.f;  
  193.                 cvSetImageROI( hue, selection );  
  194.                 cvSetImageROI( mask, selection );  
  195.                 cvCalcHist( &hue, hist, 0, mask );  
  196.                 cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );  
  197.                 cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 );  
  198.                 cvResetImageROI( hue );  
  199.                 cvResetImageROI( mask );  
  200.                 track_window = selection;  
  201.                 track_object = 1;  
  202.   
  203.                 cvZero( histimg );  
  204.                 bin_w = histimg->width / hdims;  
  205.                 for( i = 0; i < hdims; i++ )  
  206.                 {  
  207.                     int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 );  
  208.                     CvScalar color = hsv2rgb(i*180.f/hdims);  
  209.                     cvRectangle( histimg, cvPoint(i*bin_w,histimg->height),  
  210.                                  cvPoint((i+1)*bin_w,histimg->height - val),  
  211.                                  color, -1, 8, 0 );  
  212.                 }  
  213.             }  
  214.   
  215.             cvCalcBackProject( &hue, backproject, hist );  
  216.             cvAnd( backproject, mask, backproject, 0 );  
  217.             //cvCamShift( backproject, track_window,  
  218.             //            cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),  
  219.             //            &track_comp, &track_box );  
  220.             cvMeanShift( backproject, track_window,  
  221.                         cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),  
  222.                         &track_comp );  
  223.             track_window = track_comp.rect;  
  224.               
  225.             if( backproject_mode )  
  226.                 cvCvtColor( backproject, image, CV_GRAY2BGR );  
  227.             if( image->origin )  
  228.                 track_box.angle = -track_box.angle;  
  229.             //cvEllipseBox( image, track_box, CV_RGB(255,0,0), 3, CV_AA, 0 );  
  230.              cvRectangle(image, cvPoint(track_comp.rect.x , track_comp.rect.y),  
  231.              cvPoint(track_comp.rect.x+track_comp.rect.width , track_comp.rect.y+track_comp.rect.height)  
  232.              ,  CV_RGB(255,0,0), 1,  CV_AA, 0);  
  233.               }  
  234.           
  235.         if( select_object && selection.width > 0 && selection.height > 0 )  
  236.         {  
  237.              cvRectangle(image, cvPoint(selection.x , selection.y),  
  238.              cvPoint(selection.x+selection.width , selection.y+selection.height)  
  239.               ,  CV_RGB(0,0,255), 1,  CV_AA , 0);  
  240.         }  
  241.   
  242.         cvShowImage( "CamShiftDemo", image );  
  243.         cvShowImage( "Histogram", histimg );  
  244.   
  245.         c = cvWaitKey(100);  
  246.         if( (char) c == 27 )  
  247.             break;  
  248.         switch( (char) c )  
  249.         {  
  250.         case 'b':  
  251.             backproject_mode ^= 1;  
  252.             break;  
  253.         case 'c':  
  254.             track_object = 0;  
  255.             cvZero( histimg );  
  256.             break;  
  257.         case 'h':  
  258.             show_hist ^= 1;  
  259.             if( !show_hist )  
  260.                 cvDestroyWindow( "Histogram" );  
  261.             else  
  262.                 cvNamedWindow( "Histogram", 1 );  
  263.             break;  
  264.         default:  
  265.             ;  
  266.         }  
  267.     }  
  268.   
  269.     cvReleaseCapture( &capture );  
  270.     cvDestroyWindow("CamShiftDemo");  
  271.   
  272. }  
  273. //---------------------------------------------------------------------------  
  274.   
  275.    
  276.   
  277.    

原文地址为:http://blog.csdn.net/henhen2002/article/details/4322113


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值