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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章