前言:
人生自己整理的第一篇文章,归因于明天要回家,所以现在心情比较激动,不能好好干活,比较适合整理东西,虽然现在项目还没搞定,还是整理一下,过年回来不至于重新来过~
正题:
简介:
现在的思路大概是camshift+kalman,就是先利用kalman预测出目标的大概位置,然后在这个位置附近增大搜索区域。利用camshift方法,定位目标的精确位置。
CvCamShiftTracker:
opencv(我的版本是2.4.8)官方文档中还没有关于这个类的说明,所以,需要自己磕源代码。2.4.8里面有利用camshift算法跟踪的封装类,声明是在安装文件下的这个目录:opencv\build\include\opencv2\legacy\legacy.hpp文件中,实现在\opencv\modules\legacy\src\camshift.cpp文件中,下面,就说一下死磕的过程。(还没有磕明白,还望各位大侠指教)
关于camshift算法的思路,不明白的可以出门路转下面的博客:
http://blog.csdn.net/lanbing510/article/details/8764270
总结来说主要是三个步骤:计算上一帧目标的直方图(数据类型CvHistogram *)→计算当前帧ROI的的backproject(数据类型IplImage *)→camshift方法计算。
根据源码来分析下用法:
class CV_EXPORTS CvCamShiftTracker { public: CvCamShiftTracker(); virtual ~CvCamShiftTracker(); /**** Characteristics of the object that are calculated by track_object method *****/ float get_orientation() const // orientation of the object in degrees { return m_box.angle; } float get_length() const // the larger linear size of the object { return m_box.size.height; } float get_width() const // the smaller linear size of the object { return m_box.size.width; } CvPoint2D32f get_center() const // center of the object { return m_box.center; } CvRect get_window() const // bounding rectangle for the object { return m_comp.rect; } /*********************** Tracking parameters ************************/ int get_threshold() const // thresholding value that applied to back project { return m_threshold; } int get_hist_dims( int* dims = 0 ) const // returns number of histogram dimensions and sets { return m_hist ? cvGetDims( m_hist->bins, dims ) : 0; } int get_min_ch_val( int channel ) const // get the minimum allowed value of the specified channel { return m_min_ch_val[channel]; } int get_max_ch_val( int channel ) const // get the maximum allowed value of the specified channel { return m_max_ch_val[channel]; } // set initial object rectangle (must be called before initial calculation of the histogram) bool set_window( CvRect window) { m_comp.rect = window; return true; } bool set_threshold( int threshold ) // threshold applied to the histogram bins { m_threshold = threshold; return true; } bool set_hist_bin_range( int dim, int min_val, int max_val ); bool set_hist_dims( int c_dims, int* dims );// set the histogram parameters bool set_min_ch_val( int channel, int val ) // set the minimum allowed value of the specified channel { m_min_ch_val[channel] = val; return true; } bool set_max_ch_val( int channel, int val ) // set the maximum allowed value of the specified channel { m_max_ch_val[channel] = val; return true; } /************************ The processing methods *********************************/ // update object position virtual bool track_object( const IplImage* cur_frame ); // update object histogram virtual bool update_histogram( const IplImage* cur_frame ); //根据m_comp和m_hist来更新直方图,参数cur_frame是当前的整幅图片,而不是只包含目 标区域的ROI,这里mark,我在这里翻过错误 //这里的思路大概是先set_window,set_hist_dims,set_hist_bin_range,update_histogram //(但是这里目前还有bug,就是在set_hist_bin_range中设置了直方 图每个bin的范围之后,在update_histogram中却成了乱七八糟的数值,很郁闷,还没找到///原因 // reset histogram virtual void reset_histogram(); /************************ Retrieving internal data *******************************/ // get back project image virtual IplImage* get_back_project() { return m_back_project; } float query( int* bin ) const { return m_hist ? (float)cvGetRealND(m_hist->bins, bin) : 0.f; }
/*这里可以好好理解下CvHistogram这个数据类型,CV_MAX_DIM=32,也就是说这里默认做多包含32个,一般来说,灰度直方图为1channel,彩色直方图为3channels,所以这里的32个channel中我们一般只使用前3个channels,而对应的range是表示直方图每个bin取值范围,这里的[2]分别代表最小值和最大值,默认构造函数是0,255*/ protected: // internal method for color conversion: fills m_color_planes group virtual void color_transform( const IplImage* img ); CvHistogram* m_hist; CvBox2D m_box; CvConnectedComp m_comp; float m_hist_ranges_data[CV_MAX_DIM][2]; float* m_hist_ranges[CV_MAX_DIM]; int m_min_ch_val[CV_MAX_DIM]; int m_max_ch_val[CV_MAX_DIM]; int m_threshold; IplImage* m_color_planes[CV_MAX_DIM];//这个参数还没理解具体含义是什么,但是在update_histogram中用到,所以猜想:如果是RGB图像,那这里的前三个应 //该就是分别代表三个通道。 IplImage* m_back_project; IplImage* m_temp; IplImage* m_mask; }; //在track_object函数的参数,结合kalman的方法,我用的是ROI的方式,所以在此函数之前需要重新设置m_comp的位置,track函数完成后记得还原回来就好了。
现在程序的问题主要出在两个地方:
一个就是上面提到过的在update_histogram中m_bin_ranges设置无效;
没太搞明白类的析构函数在什么情况下调用,在第五帧(序号为4)中id为1的人变为4,这个时候如果析构之后再析构应该会出现错误,具体的错误需要搞清楚1)类的析构函数在哪里会调用(目前来看的话,应该是在FillPool函数里面会调用);2)搞清楚如果该序号在当前帧没有被用到的话,会怎样。
//********************************************************************************************************************************************
暂时更新这么多,后面把这些问题搞清楚了,再来更新。
http://blog.csdn.net/ljbkiss/article/details/7582229 histPrepareImages函数的应用,刚才在用的时候出现了错误。