CamShift.cpp
上传用户:lijia5631
上传日期:2008-11-10
资源大小:1214k
文件大小:7k
源码类别:

视频捕捉/采集

开发平台:

MultiPlatform

  1. /**
  2.   * HandVu - a library for computer vision-based hand gesture
  3.   * recognition.
  4.   * Copyright (C) 2004 Mathias Kolsch, matz@cs.ucsb.edu
  5.   *
  6.   * This program is free software; you can redistribute it and/or
  7.   * modify it under the terms of the GNU General Public License
  8.   * as published by the Free Software Foundation; either version 2
  9.   * of the License, or (at your option) any later version.
  10.   *
  11.   * This program is distributed in the hope that it will be useful,
  12.   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.   * GNU General Public License for more details.
  15.   *
  16.   * You should have received a copy of the GNU General Public License
  17.   * along with this program; if not, write to the Free Software
  18.   * Foundation, Inc., 59 Temple Place - Suite 330, 
  19.   * Boston, MA  02111-1307, USA.
  20.   *
  21.   * $Id: CamShift.cpp,v 1.7 2005/01/06 06:53:41 matz Exp $
  22. **/
  23. #include "Common.h"
  24. #include "CamShift.h"
  25. #include "Exceptions.h"
  26. CamShift::CamShift() 
  27. : m_bins(20),
  28.   m_threshold(0),
  29.   m_Smin(20),
  30.   m_Vmin(40),
  31.   m_Vmax(255),
  32.   m_tracking(false),
  33.   m_pProbProv(NULL)
  34. {
  35. }
  36. void CamShift::Initialize(int width, int height)
  37. {
  38.   m_img_width = width;
  39.   m_img_height = height;
  40.   m_prob_map = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
  41. }
  42. //
  43. // Process
  44. //
  45. // init or adjust CamShift 
  46. //
  47. void CamShift::PrepareTracking(IplImage* image, const ProbDistrProvider* pProbProv, const CRect& area)
  48. {
  49.   m_pProbProv = pProbProv;
  50.   if (m_pProbProv) {
  51.     m_comp.rect.x = area.left;
  52.     m_comp.rect.y = area.top;
  53.     m_comp.rect.width = area.right-area.left;
  54.     m_comp.rect.height = area.bottom-area.top;
  55.     DoExternal(image);
  56.   } else {
  57.     m_object.x = area.left;
  58.     m_object.y = area.top;
  59.     m_object.width = area.right-area.left;
  60.     m_object.height = area.bottom-area.top;
  61.     ASSERT(image->roi==0);
  62.     DoHSV(image, true);
  63.   }
  64.   m_tracking = true;
  65. } // Start
  66. //
  67. // Process
  68. //
  69. // init or adjust CamShift 
  70. //
  71. void CamShift::Track(IplImage* image)
  72. {
  73.   if (m_tracking) {
  74.     if (m_pProbProv) {
  75.       DoExternal(image);
  76.     } else {
  77.       DoHSV(image, false);
  78.     }
  79.   }
  80. } // Process
  81. //
  82. // Draw
  83. //
  84. void CamShift::DrawOverlay(IplImage* image, int overlay_level) const
  85. {
  86.   if (m_tracking && overlay_level>1) {
  87.     if (overlay_level>2 && m_pProbProv==NULL) {
  88.       CheckBackProject(image, 1);
  89.     }
  90.     DrawCross(image);
  91.   }
  92. } // Draw
  93. void CamShift::DoHSV(IplImage* image, bool initialize)
  94. {
  95.   m_cCamShift.set_hist_dims( 1, &m_bins );
  96.   m_cCamShift.set_hist_bin_range( 0, 0, 180 );
  97.   m_cCamShift.set_threshold( 0 );
  98.   m_cCamShift.set_min_ch_val( 1, m_Smin );
  99.   m_cCamShift.set_max_ch_val( 1, 255 );
  100.   m_cCamShift.set_min_ch_val( 2, m_Vmin );
  101.   m_cCamShift.set_max_ch_val( 2, m_Vmax );
  102.   
  103.   CvSize size;
  104.   cvGetImageRawData( image, 0, 0, &size );
  105.   if( m_object.x < 0 ) m_object.x = 0;
  106.   if( m_object.x > size.width - m_object.width - 1 )
  107.       m_object.x = MAX(0, size.width - m_object.width - 1);
  108.   if( m_object.y < 0 ) m_object.y = 0;
  109.   if( m_object.y > size.height - m_object.height - 1 )
  110.       m_object.y = MAX(0, size.height - m_object.height - 1);
  111.   if( m_object.width > size.width - m_object.x )
  112.       m_object.width = MIN(size.width, size.width - m_object.x);
  113.   if( m_object.height > size.height - m_object.y )
  114.       m_object.height = MIN(size.height, size.height - m_object.y);
  115.   m_cCamShift.set_window(m_object);
  116.   
  117.   if (initialize) {
  118.       m_cCamShift.reset_histogram();
  119.       m_cCamShift.update_histogram( image );
  120.   }
  121.   m_cCamShift.track_object( image );
  122.   m_object = m_cCamShift.get_window();
  123. }
  124. void CamShift::DoExternal(IplImage* image)
  125. {
  126.   ASSERT(m_pProbProv);
  127.   ASSERT(m_comp.rect.width != 0 && m_comp.rect.height != 0);
  128.   
  129.   CvRect rect = m_comp.rect;
  130.   if( rect.x < 0 )
  131.       rect.x = 0;
  132.   if( rect.x + rect.width > m_img_width )
  133.       rect.width = m_img_width - rect.x;
  134.   if( rect.y < 0 )
  135.       rect.y = 0;
  136.   if( rect.y + rect.height > m_img_height )
  137.       rect.height = m_img_height - rect.y;
  138.   CRect roi;
  139.   roi.left = m_comp.rect.x-m_comp.rect.width/2;
  140.   roi.right = roi.left+m_comp.rect.width*2;
  141.   roi.top = m_comp.rect.y-m_comp.rect.height/2;
  142.   roi.bottom = roi.top+m_comp.rect.height*2;
  143.   m_pProbProv->CreateMap(image, m_prob_map, roi);
  144.   cvCamShift(m_prob_map, rect,
  145.      cvTermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1),
  146.      &m_comp, &m_box );
  147.   if( m_comp.rect.width == 0 || m_comp.rect.height == 0 )
  148.       m_comp.rect = rect; // do not allow tracker to loose the object
  149. }
  150. void CamShift::CheckBackProject(IplImage* image, int view) const
  151. {
  152.   if( view == 1 )
  153.   {
  154.     IplImage* src = ((CvCamShiftTracker&)m_cCamShift).get_back_project();
  155.     if( src && src->imageData && image )
  156.     {
  157.       cvSetImageROI( image, cvRect( m_object.x, m_object.y, m_object.width, m_object.height )); 
  158.       cvSetImageROI( src, cvRect( m_object.x, m_object.y, m_object.width, m_object.height )); 
  159.       cvCvtColor( src, image, CV_GRAY2BGR );
  160.       cvResetImageROI( image );
  161.       cvResetImageROI( src );
  162.     }
  163.   }
  164.   else if( view == 2 && m_tracking ) 
  165.   {
  166.     int i, dims;
  167.     CvSize size;
  168.     m_cCamShift.get_hist_dims( &dims );
  169.     cvGetImageRawData( image, 0, 0, &size );
  170.     for( i = 0; i < dims; i++ )
  171.     {
  172.       int val = cvRound(m_cCamShift.query(&i));
  173.       CvPoint p[4];
  174.       p[0].x = p[1].x = i*size.width/(2*dims);
  175.       p[2].x = p[3].x = (i+1)*size.width/(2*dims);
  176.       p[1].y = p[2].y = 0;
  177.       p[0].y = p[3].y = (val*size.height)/(3*255);
  178.       cvFillConvexPoly( image, p, 4, CV_RGB(255,0,0));
  179.     }
  180.   }
  181. }
  182. void  CamShift::DrawCross( IplImage* image ) const
  183. {
  184.   if (m_pProbProv) {
  185.     float cs = (float)cos( m_box.angle );
  186.     float sn = (float)sin( m_box.angle );
  187.     int x = m_comp.rect.x + m_comp.rect.width / 2;
  188.     int y = m_comp.rect.y + m_comp.rect.height / 2;
  189.     CvPoint p1 = {(int)(x + m_box.size.height * cs / 2),
  190.       (int)(y + m_box.size.height * sn / 2)};
  191.     CvPoint p2 = {(int)(x - m_box.size.height * cs / 2),
  192.       (int)(y - m_box.size.height * sn / 2)};
  193.     CvPoint p3 = {(int)(x + m_box.size.width * sn / 2),
  194.       (int)(y - m_box.size.width * cs / 2)};
  195.     CvPoint p4 = {(int)(x - m_box.size.width * sn / 2),
  196.       (int)(y + m_box.size.width * cs / 2)};
  197.     cvLine( image, p1, p2, CV_RGB(0,255,0) );
  198.     cvLine( image, p4, p3, CV_RGB(0,255,0) );
  199.   } else {
  200.     float cs = (float)cos( m_cCamShift.get_orientation() );
  201.     float sn = (float)sin( m_cCamShift.get_orientation() );
  202.     int x = m_object.x + m_object.width / 2;
  203.     int y = m_object.y + m_object.height / 2;
  204.     CvPoint p1 = {(int)(x + m_cCamShift.get_length() * cs / 2),
  205.       (int)(y + m_cCamShift.get_length() * sn / 2)};
  206.     CvPoint p2 = {(int)(x - m_cCamShift.get_length() * cs / 2),
  207.       (int)(y - m_cCamShift.get_length() * sn / 2)};
  208.     CvPoint p3 = {(int)(x + m_cCamShift.get_width() * sn / 2),
  209.       (int)(y - m_cCamShift.get_width() * cs / 2)};
  210.     CvPoint p4 = {(int)(x - m_cCamShift.get_width() * sn / 2),
  211.       (int)(y + m_cCamShift.get_width() * cs / 2)};
  212.     cvLine( image, p1, p2, CV_RGB(255,255,255) );
  213.     cvLine( image, p4, p3, CV_RGB(255,255,255) );
  214.   }
  215. }
  216. void CamShift::GetArea(CRect& area) const {
  217.   if (m_pProbProv) {
  218.     area.left = m_comp.rect.x;
  219.     area.top = m_comp.rect.y;
  220.     area.right = m_comp.rect.x+m_comp.rect.width;
  221.     area.bottom = m_comp.rect.y+m_comp.rect.height;
  222.   } else {
  223.     area.left = m_object.x;
  224.     area.top = m_object.y;
  225.     area.right = m_object.x+m_object.width;
  226.     area.bottom = m_object.y+m_object.height;
  227.   }
  228. }