生活随笔
收集整理的這篇文章主要介紹了
目标跟踪-粒子滤波算法
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
http://blog.csdn.net/hujingshuang/article/details/45535423
前言:
粒子濾波廣泛的應(yīng)用于目標(biāo)跟蹤,粒子濾波器是一種序列蒙特卡羅濾波方法,其實(shí)質(zhì)是利用一系列隨機(jī)抽取的樣本(即粒子)來替代狀態(tài)的后驗(yàn)概率分布。在此不打算介紹和推理繁雜的概率公式,我們來分析Rob Hess源碼從而深入理解粒子濾波算法。
試驗(yàn)平臺(tái):
VS2010 + opencv2.4.10 + gsl1.8庫 + RobHess粒子濾波源碼
相關(guān)資料:
? ? ? ?Rob Hess粒子濾波的相關(guān)代碼:http://blogs.oregonstate.edu/hess/code/particles/
? ? ? ?Rob Hess有關(guān)粒子濾波的文章:http://web.engr.oregonstate.edu/~afern/papers/cvpr09.pdf
? ? ? ?Rob Hess多目標(biāo)跟蹤效果視頻:http://v.youku.com/v_show/id_XOTQ5NDA5ODgw.html
? ? ? ?yangyangcv博主的分析及代碼(建議先看):http://www.cnblogs.com/yangyangcv/archive/2010/05/23/1742263.html
(下載?yangyangcv提供的代碼,配置好后即可使用;本博文也提供下載,見文章末尾)
源碼分析:
下面用粒子濾波算法來實(shí)現(xiàn)單目標(biāo)的跟蹤,在初始時(shí)需要手動(dòng)選取待跟蹤目標(biāo)區(qū)域。
步驟一:粒子初始化
1、目標(biāo)的選取:
在起始幀畫面中標(biāo)記待跟蹤的區(qū)域(目標(biāo)物體),在以后的連續(xù)幀視頻中跟蹤目標(biāo)物體。
2、粒子的定義:
粒子即樣本,Rob Hess源碼中默認(rèn)粒子數(shù)目PARTICLES=100,下面是粒子的屬性(可以看出一個(gè)粒子代表的就是一個(gè)矩形區(qū)域):
[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、特征提取:
目標(biāo)跟蹤最重要的就是特征,應(yīng)該選取好的特征(擁有各種不變性的特征當(dāng)然是最好的);另外考慮算法的效率,目標(biāo)跟蹤一般是實(shí)時(shí)跟蹤,所以對(duì)算法實(shí)時(shí)性有一定的要求。Rob Hess源碼提取的是目標(biāo)的顏色特征(顏色特征對(duì)圖像本身的尺寸、方向、視角的依賴性較小,從而具有較高的魯棒性),粒子與目標(biāo)的直方圖越相似,則說明越有可能是目標(biāo)。
捕捉到一幀圖像,標(biāo)記待跟蹤的區(qū)域,將其從BGR轉(zhuǎn)化到HSV空間,提取感興趣部分(目標(biāo))的HSV,進(jìn)行直方圖統(tǒng)計(jì)并歸一化直方圖。
[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是目標(biāo)矩形區(qū)域,h、s、v是個(gè)分量,hist就是直方圖統(tǒng)計(jì);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、粒子初始化
根據(jù)選定的目標(biāo)區(qū)域來初始化粒子,初始時(shí)所有粒子都為等權(quán)重,具有同樣的屬性。
[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;?? ????}?? }??
步驟二、粒子相似度搜索、計(jì)算
5、粒子搜索
在步驟一中,初始化了100個(gè)粒子,由于初始幀中指定了目標(biāo)區(qū)域,而該目標(biāo)會(huì)在下一幀中發(fā)生偏移,但是相鄰幀目標(biāo)移動(dòng)得不是太遠(yuǎn),所以在目標(biāo)區(qū)域附近隨機(jī)撒出100個(gè)粒子。(此處使用的是二階動(dòng)態(tài)回歸來估計(jì)偏移后的粒子位置)
[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、相似度計(jì)算
然后計(jì)算這100個(gè)粒子hsv空間直方圖與目標(biāo)hsv空間直方圖相似成度,馬氏距離(Battacharyya)來度量兩個(gè)粒子的相似度系數(shù)。
[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、重采樣
由步驟二知,經(jīng)過一次搜索后,粒子的權(quán)重會(huì)發(fā)生改變,離目標(biāo)距離遠(yuǎn)的粒子權(quán)重小,距離近的權(quán)重大。那么經(jīng)過多幀的跟蹤后,有的粒子權(quán)重會(huì)變得相當(dāng)?shù)男?#xff0c;也就是與目標(biāo)不相似了,即粒子退化現(xiàn)象,這種粒子我們要拋棄,那么什么時(shí)候該拋棄它呢?就得設(shè)一個(gè)權(quán)重閾值,凡是權(quán)重低于閾值的粒子就拋棄。OK,原來有100個(gè)粒子,然后總會(huì)有被拋棄的粒子,似的粒子總數(shù)不滿100個(gè),此時(shí)就要找一些新的粒子來補(bǔ)充,那么就用最大權(quán)值來填充。(比如現(xiàn)在拋棄了20個(gè)粒子,我們就復(fù)制20個(gè)權(quán)值最大的粒子,放到里面填滿100個(gè)。)——這就是重采樣的過程。
[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個(gè)粒子更新到步驟一4中。至此完成了一次粒子濾波。(需要注意的是,經(jīng)過一次迭代后,步驟一4中的粒子權(quán)值已經(jīng)不是等權(quán)值了)
9、小結(jié)
先初始化(完成1、2、3、4),再不停的迭代5、6、7、8過程(即:5—>6—>7—>8—>5......)。
以上是粒子濾波的全部過程,以及一些核心源碼,可以認(rèn)為權(quán)重最大的粒子是目標(biāo)物體。值得關(guān)注的是,重采樣會(huì)降低粒子的多樣性(因?yàn)槭窃S多粒子是直接復(fù)制過來的),這樣也會(huì)對(duì)目標(biāo)跟蹤產(chǎn)生影響,有興趣的可以繼續(xù)研究改進(jìn)算法以保證粒子的多樣性。
over!
以上是對(duì)粒子濾波的個(gè)人見解,至于理論上看著比較復(fù)雜的理論公式推導(dǎo)沒有體現(xiàn)出來(其實(shí)有些概率論知識(shí)我還是沒看懂),再次膜拜一下Rob Hess大嬸,牛的一逼(他也實(shí)現(xiàn)了Lowe的SIFT算法并開源代碼出來)。
本文所需材料都已打包上傳,點(diǎn)擊此處下載(配置gsl,請(qǐng)百度):http://download.csdn.net/detail/hujingshuang/8669945
總結(jié)
以上是生活随笔為你收集整理的目标跟踪-粒子滤波算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。