生活随笔
收集整理的這篇文章主要介紹了
Optical_Flow(4)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
申明:本文非筆者原創,原文轉載自:http://blog.csdn .NET/crzy_sparrow/article/details/7407604
本文目錄:
????? 一.基于特征點的目標跟蹤的一般方法
????? 二.光流法
????? 三.OpenCV中的光流法函數
??? ? 四.用類封裝基于光流法的目標跟蹤方法
????? 五.完整代碼
????? 六.參考文獻
一.基于特征點的目標跟蹤的一般方法
????? 基于特征點的跟蹤算法大致可以分為兩個步驟:
????? 1)探測當前幀的特征點;
????? 2)通過當前幀和下一幀灰度比較,估計當前幀特征點在下一幀的位置;
????? 3)過濾位置不變的特征點,余下的點就是目標了。
????? 很顯然,基于特征點的目標跟蹤算法和1),2)兩個步驟有關。特征點可以是Harris角點(見我的另外一篇博文),也可以是邊緣點等等,而估計下一幀位置的方法也有不少,比如這里要講的光流法,也可以是卡爾曼濾波法(咱是控制系的,上課經常遇到這個,所以看光流法看著看著就想到這個了)。
????? 本文中,用改進的Harris角點提取特征點(見我另一篇博文:http://blog.csdn.Net/crzy_sparrow/article/details/7391511),用Lucas-Kanade光流法實現目標跟蹤。
二.光流法
????? 這一部分《learing opencv》一書的第10章 Lucas-Kanade 光流部分寫得非常詳細,推薦大家看書。我這里也粘帖一些選自書中的內容。
????? 另外我對這一部分附上一些個人的看法(謬誤之處還望不吝指正):
????? 1.首先是假設條件:
?? ??? (1)亮度恒定,就是同一點隨著時間的變化,其亮度不會發生改變。這是基本光流法的假定(所有光流法變種都必須滿足),用于得到光流法基本方程;
?????? (2)小運動,這個也必須滿足,就是時間的變化不會引起位置的劇烈變化,這樣灰度才能對位置求偏導(換句話說,小運動情況下我們才能用前后幀之間單位位置變化引起的灰度變化去近似灰度對位置的偏導數),這也是光流法不可或缺的假定;
?????? (3)空間一致,一個場景上鄰近的點投影到圖像上也是鄰近點,且鄰近點速度一致。這是Lucas-Kanade光流法特有的假定,因為光流法基本方程約束只有一個,而要求x,y方向的速度,有兩個未知變量。我們假定特征點鄰域內做相似運動,就可以連立n多個方程求取x,y方向的速度(n為特征點鄰域總點數,包括該特征點)。
????? 2.方程求解
????? 多個方程求兩個未知變量,又是線性方程,很容易就想到用最小二乘法,事實上opencv也是這么做的。其中,最小誤差平方和為最優化指標。
????? 3.好吧,前面說到了小運動這個假定,聰明的你肯定很不爽了,目標速度很快那這貨不是二掉了。幸運的是多尺度能解決這個問題。首先,對每一幀建立一個高斯金字塔,最大尺度圖片在最頂層,原始圖片在底層。然后,從頂層開始估計下一幀所在位置,作為下一層的初始位置,沿著金字塔向下搜索,重復估計動作,直到到達金字塔的底層。聰明的你肯定發現了:這樣搜索不僅可以解決大運動目標跟蹤,也可以一定程度上解決孔徑問題(相同大小的窗口能覆蓋大尺度圖片上盡量多的角點,而這些角點無法在原始圖片上被覆蓋)。
三.opencv中的光流法函數
????? opencv2.3.1中已經實現了基于光流法的特征點位置估計函數(當前幀位置已知,前后幀灰度已知),介紹如下(摘自opencv2.3.1參考手冊):
[cpp] ?view plaincopy
calcOpticalFlowPyrLK?? Calculates?an?optical?flow?for ?a?sparse?feature?set? using ?the?iterative?Lucas-Kanade?method?with?pyramids.?? ?? void ?calcOpticalFlowPyrLK(InputArray?prevImg,?InputArray?nextImg,?InputArray?prevPts,?? InputOutputArray?nextPts,?OutputArray?status,?OutputArray?err,?? Size?winSize=Size(15,15),?int ?maxLevel=3,?TermCriteria?crite-?? ria=TermCriteria(TermCriteria::COUNT+TermCriteria::EPS,?30,?0.01),?? double ?derivLambda=0.5,? int ?flags=0?)?? ?? Parameters?? prevImg?–?First?8-bit?single-channel?or?3-channel?input?image.?? nextImg?–?Second?input?image?of?the?same?size?and?the?same?type?as?prevImg?.?? prevPts?–?Vector?of?2D?points?for ?which?the?flow?needs?to?be?found.?The?point?coordinates?? must?be?single-precision?floating-point?numbers.?? nextPts?–?Output?vector?of?2D?points?(with?single-precision?floating-point?coordinates)?? containing?the?calculated?new ?positions?of?input?features?in?the?second?image.?When?? OPTFLOW_USE_INITIAL_FLOW?flag?is?passed,?the?vector?must?have?the?same?size?as?in?the?? input.?? status?–?Output?status?vector.?Each?element?of?the?vector?is?set?to?1?if ?the?flow? for ?the?? corresponding?features?has?been?found.?Otherwise,?it?is?set?to?0.?? err?–?Output?vector?that?contains?the?difference?between?patches?around?the?original?and?? moved?points.?? winSize?–?Size?of?the?search?window?at?each?pyramid?level.?? ?? maxLevel?–?0-based?maximal?pyramid?level?number.?If?set?to?0,?pyramids?are?not?used?? (single?level).?If?set?to?1,?two?levels?are?used,?and?so?on.?? criteria?–?Parameter?specifying?the?termination?criteria?of?the?iterative?search?algorithm?? (after?the?specified?maximum?number?of?iterations?criteria.maxCount?or?when?the?search?? window?moves?by?less?than?criteria.epsilon?.?? derivLambda?–?Not?used.?? ?? flags?–?Operation?flags:?? –?OPTFLOW_USE_INITIAL_FLOW?Use?initial?estimations?stored?in?nextPts?.?If?the?? flag?is?not?set,?then?prevPts?is?copied?to?nextPts?and?is?considered?as?the?initial?estimate.??
四.用類封裝基于光流法的目標跟蹤方法
????? 廢話少說,附上代碼,包括特征點提取,跟蹤特征點,標記特征點等。
[cpp] ?view plaincopy
<span?style= "font-size:18px;" > ?? class ?FrameProcessor{?? ????public :?? ????????virtual ? void ?process(Mat?&input,Mat?&ouput)=0;?? };?? ?? ?? class ?FeatureTracker?:?? public ?FrameProcessor{?? ????Mat?gray;???? ????Mat?gray_prev;???? ????vector<Point2f>?points[2];?? ????vector<Point2f>?initial;?? ????vector<Point2f>?features;?? ????int ?max_count;? ?? ????double ?qlevel;? ?? ????double ?minDist; ?? ????vector<uchar>?status;??? ????vector<float >?err;? ?? public :?? ????FeatureTracker():max_count(500),qlevel(0.01),minDist(10.){}?? ????void ?process(Mat?&frame,Mat?&output){?? ?????????? ????????cvtColor?(frame,gray,CV_BGR2GRAY);?? ????????frame.copyTo?(output);?? ?????????? ????????if (addNewPoint()){?? ????????????detectFeaturePoint?();?? ?????????????? ????????????points[0].insert?(points[0].end?(),features.begin?(),features.end?());?? ????????????initial.insert?(initial.end?(),features.begin?(),features.end?());?? ????????}?? ?????????? ????????if (gray_prev.empty?()){?? ????????????????gray.copyTo?(gray_prev);?? ????????}?? ?????????? ?????????? ????????calcOpticalFlowPyrLK?(?? ????????????????gray_prev,?? ????????????????gray,?? ????????????????points[0],?? ????????????????points[1],?? ????????????????status,?? ????????????????err);?? ????????int ?k?=?0;?? ?????????? ????????for ( int ?i=0;i<points[1].size?();i++){?? ????????????if (acceptTrackedPoint?(i)){?? ????????????????initial[k]=initial[i];?? ????????????????points[1][k++]?=?points[1][i];?? ????????????}?? ????????}?? ????????points[1].resize?(k);?? ????????initial.resize?(k);?? ?????????? ????????handleTrackedPoint?(frame,output);?? ?????????? ????????std::swap(points[1],points[0]);?? ????????cv::swap(gray_prev,gray);?? ????}?? ?? ????void ?detectFeaturePoint(){?? ????????goodFeaturesToTrack?(gray,?? ?????????????????????????????????features,?? ?????????????????????????????????max_count,?? ?????????????????????????????????qlevel,?? ?????????????????????????????????minDist);?? ????}?? ????bool ?addNewPoint(){?? ?????????? ????????return ?points[0].size?()<=10;?? ????}?? ?? ?????? ????bool ?acceptTrackedPoint( int ?i){?? ????????return ?status[i]&&?? ????????????????(abs(points[0][i].x-points[1][i].x)+?? ??????????????????abs(points[0][i].y-points[1][i].y)?>2);?? ????}?? ?? ?????? ????void ??handleTrackedPoint(Mat?&frame,Mat?&output){?? ????????????for ( int ?i=0;i<points[i].size?();i++){?? ?????????????????? ????????????????line(output,initial[i],points[1][i],Scalar::all?(0));?? ?????????????????? ????????????????circle(output,points[1][i],3,Scalar::all(0),(-1));?? ????????????}?? ????????}?? };</span>??
五.完整代碼 ? 完整的運行代碼有300+行,粘上來太多了,大家去我傳的資源里下載吧。
? 下載地址:http://download.csdn.net/detail/crzy_sparrow/4183674
? 運行結果:
六.參考文獻
【1】The classic article by B. Lucas and T. Kanade, An iterative image registration technique with an application to stereo vision in Int. Joint Conference in Artificial Intelligence, pp. 674-679,1981, that describes the original feature point tracking algorithm. 【2】The article by J. Shi and C. Tomasi, Good Features to Track in IEEE Conference on Computer Vision and Pattern Recognition, pp. 593-600, 1994, that describes an improved version of the original feature point tracking algorithm.
總結
以上是生活随笔 為你收集整理的Optical_Flow(4) 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。