生活随笔
收集整理的這篇文章主要介紹了
目标跟踪-粒子滤波算法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
http://blog.csdn.net/hujingshuang/article/details/45535423
前言:
粒子濾波廣泛的應用于目標跟蹤,粒子濾波器是一種序列蒙特卡羅濾波方法,其實質是利用一系列隨機抽取的樣本(即粒子)來替代狀態的后驗概率分布。在此不打算介紹和推理繁雜的概率公式,我們來分析Rob Hess源碼從而深入理解粒子濾波算法。
試驗平臺:
VS2010 + opencv2.4.10 + gsl1.8庫 + RobHess粒子濾波源碼
相關資料:
? ? ? ?Rob Hess粒子濾波的相關代碼:http://blogs.oregonstate.edu/hess/code/particles/
? ? ? ?Rob Hess有關粒子濾波的文章:http://web.engr.oregonstate.edu/~afern/papers/cvpr09.pdf
? ? ? ?Rob Hess多目標跟蹤效果視頻:http://v.youku.com/v_show/id_XOTQ5NDA5ODgw.html
? ? ? ?yangyangcv博主的分析及代碼(建議先看):http://www.cnblogs.com/yangyangcv/archive/2010/05/23/1742263.html
(下載?yangyangcv提供的代碼,配置好后即可使用;本博文也提供下載,見文章末尾)
源碼分析:
下面用粒子濾波算法來實現單目標的跟蹤,在初始時需要手動選取待跟蹤目標區域。
步驟一:粒子初始化
1、目標的選取:
在起始幀畫面中標記待跟蹤的區域(目標物體),在以后的連續幀視頻中跟蹤目標物體。
2、粒子的定義:
粒子即樣本,Rob Hess源碼中默認粒子數目PARTICLES=100,下面是粒子的屬性(可以看出一個粒子代表的就是一個矩形區域):
[cpp]?view plaincopy
typedef?struct?particle?{?? ??float?x;???????????? ??float?y;???????????? ??float?s;???????????? ??float?xp;??????????? ??float?yp;??????????? ??float?sp;??????????? ??float?x0;??????????? ??float?y0;??????????? ??int?width;?????????? ??int?height;????????? ??histogram*?histo;??? ??float?w;???????????? }?particle;??
3、特征提取:
目標跟蹤最重要的就是特征,應該選取好的特征(擁有各種不變性的特征當然是最好的);另外考慮算法的效率,目標跟蹤一般是實時跟蹤,所以對算法實時性有一定的要求。Rob Hess源碼提取的是目標的顏色特征(顏色特征對圖像本身的尺寸、方向、視角的依賴性較小,從而具有較高的魯棒性),粒子與目標的直方圖越相似,則說明越有可能是目標。
捕捉到一幀圖像,標記待跟蹤的區域,將其從BGR轉化到HSV空間,提取感興趣部分(目標)的HSV,進行直方圖統計并歸一化直方圖。
[cpp]?view plaincopy
?? ?? for(?r?=?0;?r?<?img->height;?r++?)?? ????for(?c?=?0;?c?<?img->width;?c++?)?? ????{?? ????????bin?=?histo_bin(?((float*)(h->imageData?+?h->widthStep*r)?)[c],?? ????????????????????((float*)(s->imageData?+?s->widthStep*r)?)[c],?? ????????????????????((float*)(v->imageData?+?v->widthStep*r)?)[c]?);?? ????????hist[bin]?+=?1;?? ????}??
[cpp]?view plaincopy
int?histo_bin(?float?h,?float?s,?float?v?)?? {?? ??int?hd,?sd,?vd;?? ?? ???? ??vd?=?MIN(?(int)(v?*?NV?/?V_MAX),?NV-1?);?? ??if(?s?<?S_THRESH??||??v?<?V_THRESH?)?? ????return?NH?*?NS?+?vd;?? ???? ???? ??hd?=?MIN(?(int)(h?*?NH?/?H_MAX),?NH-1?);?? ??sd?=?MIN(?(int)(s?*?NS?/?S_MAX),?NS-1?);?? ??return?sd?*?NH?+?hd;?? }??
img是目標矩形區域,h、s、v是個分量,hist就是直方圖統計;NV、V_MAX....等是宏定義的固定值。
[cpp]?view plaincopy
void?normalize_histogram(?histogram*?histo?)?? {?? ??float*?hist;?? ??float?sum?=?0,?inv_sum;?? ??int?i,?n;?? ?? ??hist?=?histo->histo;?? ??n?=?histo->n;?? ?? ???? ??for(?i?=?0;?i?<?n;?i++?)?? ????sum?+=?hist[i];?? ??inv_sum?=?1.0?/?sum;?? ??for(?i?=?0;?i?<?n;?i++?)?? ????hist[i]?*=?inv_sum;?? }??
4、粒子初始化
根據選定的目標區域來初始化粒子,初始時所有粒子都為等權重,具有同樣的屬性。
[cpp]?view plaincopy
?? for(?i?=?0;?i?<?n;?i++?)?? {?? ????width?=?regions[i].width;?? ????height?=?regions[i].height;?? ????x?=?regions[i].x?+?width?/?2;<span?style="white-space:pre">???</span>?? ????y?=?regions[i].y?+?height?/?2;?? ????for(?j?=?0;?j?<?np;?j++?)?? ????{?? ????????particles[k].x0?=?particles[k].xp?=?particles[k].x?=?x;?? ????????particles[k].y0?=?particles[k].yp?=?particles[k].y?=?y;?? ????????particles[k].sp?=?particles[k].s?=?1.0;?? ????????particles[k].width?=?width;?? ????????particles[k].height?=?height;?? ????????particles[k].histo?=?histos[i];?? ????????particles[k++].w?=?0;?? ????}?? }??
步驟二、粒子相似度搜索、計算
5、粒子搜索
在步驟一中,初始化了100個粒子,由于初始幀中指定了目標區域,而該目標會在下一幀中發生偏移,但是相鄰幀目標移動得不是太遠,所以在目標區域附近隨機撒出100個粒子。(此處使用的是二階動態回歸來估計偏移后的粒子位置)
[cpp]?view plaincopy
particle?transition(?particle?p,?int?w,?int?h,?gsl_rng*?rng?)?? {?? ??float?x,?y,?s;?? ??particle?pn;?? ???? ???? ??x?=?A1?*?(?p.x?-?p.x0?)?+?A2?*?(?p.xp?-?p.x0?)?+?? ????B0?*?gsl_ran_gaussian(?rng,?TRANS_X_STD?)?+?p.x0;?? ??pn.x?=?MAX(?0.0,?MIN(?(float)w?-?1.0,?x?)?);?? ??y?=?A1?*?(?p.y?-?p.y0?)?+?A2?*?(?p.yp?-?p.y0?)?+?? ????B0?*?gsl_ran_gaussian(?rng,?TRANS_Y_STD?)?+?p.y0;?? ??pn.y?=?MAX(?0.0,?MIN(?(float)h?-?1.0,?y?)?);?? ??s?=?A1?*?(?p.s?-?1.0?)?+?A2?*?(?p.sp?-?1.0?)?+?? ????B0?*?gsl_ran_gaussian(?rng,?TRANS_S_STD?)?+?1.0;?? ??pn.s?=?MAX(?0.1,?s?);?? ??pn.xp?=?p.x;?? ??pn.yp?=?p.y;?? ??pn.sp?=?p.s;?? ??pn.x0?=?p.x0;?? ??pn.y0?=?p.y0;?? ??pn.width?=?p.width;?? ??pn.height?=?p.height;?? ??pn.histo?=?p.histo;?? ??pn.w?=?0;?? ?? ??return?pn;?? }??
6、相似度計算
然后計算這100個粒子hsv空間直方圖與目標hsv空間直方圖相似成度,馬氏距離(Battacharyya)來度量兩個粒子的相似度系數。
[cpp]?view plaincopy
?? particles[j].w?=?likelihood(?hsv_frame,?cvRound(particles[j].y),?? ????????????cvRound(?particles[j].x?),?? ????????????cvRound(?particles[j].width?*?s?),?? ????????????cvRound(?particles[j].height?*?s?),?? ????????????particles[j].histo?);??
[cpp]?view plaincopy
float?histo_dist_sq(?histogram*?h1,?histogram*?h2?)?? {?? ??float*?hist1,?*?hist2;?? ??float?sum?=?0;?? ??int?i,?n;?? ?? ??n?=?h1->n;?? ??hist1?=?h1->histo;?? ??hist2?=?h2->histo;?? ?? ??? ? ? ? ?? ??for(?i?=?0;?i?<?n;?i++?)?? ????sum?+=?sqrt(?hist1[i]*hist2[i]?);?? ??return?1.0?-?sum;?? }??
步驟三、重采樣
7、重采樣
由步驟二知,經過一次搜索后,粒子的權重會發生改變,離目標距離遠的粒子權重小,距離近的權重大。那么經過多幀的跟蹤后,有的粒子權重會變得相當的小,也就是與目標不相似了,即粒子退化現象,這種粒子我們要拋棄,那么什么時候該拋棄它呢?就得設一個權重閾值,凡是權重低于閾值的粒子就拋棄。OK,原來有100個粒子,然后總會有被拋棄的粒子,似的粒子總數不滿100個,此時就要找一些新的粒子來補充,那么就用最大權值來填充。(比如現在拋棄了20個粒子,我們就復制20個權值最大的粒子,放到里面填滿100個。)——這就是重采樣的過程。
[cpp]?view plaincopy
particle*?resample(?particle*?particles,?int?n?)?? {?? ??particle*?new_particles;?? ??int?i,?j,?np,?k?=?0;?? ?? ??qsort(?particles,?n,?sizeof(?particle?),?&particle_cmp?);?? ??new_particles?=?malloc(?n?*?sizeof(?particle?)?);?? ????for(?i?=?0;?i?<?n;?i++?)?? ????{?? ????????np?=?cvRound(?particles[i].w?*?n?);?? ????????for(?j?=?0;?j?<?np;?j++?)?? ????????{?? ????????????new_particles[k++]?=?particles[i];?? ????????????if(?k?==?n?)?? ????????????goto?exit;?? ????????}?? ????}?? ??while(?k?<?n?)?? ????new_particles[k++]?=?particles[0];?? ?? ?exit:?? ??return?new_particles;?? }??
8、更新粒子
將重采樣后的100個粒子更新到步驟一4中。至此完成了一次粒子濾波。(需要注意的是,經過一次迭代后,步驟一4中的粒子權值已經不是等權值了)
9、小結
先初始化(完成1、2、3、4),再不停的迭代5、6、7、8過程(即:5—>6—>7—>8—>5......)。
以上是粒子濾波的全部過程,以及一些核心源碼,可以認為權重最大的粒子是目標物體。值得關注的是,重采樣會降低粒子的多樣性(因為是許多粒子是直接復制過來的),這樣也會對目標跟蹤產生影響,有興趣的可以繼續研究改進算法以保證粒子的多樣性。
over!
以上是對粒子濾波的個人見解,至于理論上看著比較復雜的理論公式推導沒有體現出來(其實有些概率論知識我還是沒看懂),再次膜拜一下Rob Hess大嬸,牛的一逼(他也實現了Lowe的SIFT算法并開源代碼出來)。
本文所需材料都已打包上傳,點擊此處下載(配置gsl,請百度):http://download.csdn.net/detail/hujingshuang/8669945
總結
以上是生活随笔為你收集整理的目标跟踪-粒子滤波算法的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。