光流的概念以及 Lucas-Kanade 光流法
光流
目標(biāo)
本節(jié)我們將要學(xué)習(xí):
? 光流的概念以及 Lucas-Kanade 光流法
? 使用函數(shù) cv2.calcOpticalFlowPyrLK() 對圖像中的特征點(diǎn)進(jìn)行跟蹤
光流
由于目標(biāo)對象或者攝像機(jī)的移動造成的圖像對象在連續(xù)兩幀圖像中的移動被稱為光流。它是一個 2D 向量場,可以用來顯示一個點(diǎn)從第一幀圖像到第二幀圖像之間的移動。如下圖所示(Image Courtesy: Wikipedia article on Optical Flow):
上圖顯示了一個點(diǎn)在連續(xù)的五幀圖像間的移動。箭頭表示光流場向量。光流在很多領(lǐng)域中都很有用:
? 由運(yùn)動重建結(jié)構(gòu)
? 視頻壓縮
? Video Stabilization 等
光流是基于一下假設(shè)的:
第一幀圖像中的像素 I (x,y,t) 在時(shí)間 dt 后移動到第二幀圖像的(x+dx,y+dy)處。根據(jù)第一條假設(shè):灰度值不變。所以我們可以得到:
對等號右側(cè)進(jìn)行泰勒級數(shù)展開,消去相同項(xiàng),兩邊都除以 dt,得到如下方程:
上邊的等式叫做光流方程。其中 fx 和 fy 是圖像梯度,同樣 ft 是時(shí)間方向的梯度。但(u,v)是不知道的。我們不能在一個等式中求解兩個未知數(shù)。有幾個方法可以幫我們解決這個問題,其中的一個是 Lucas-Kanade 法
Lucas-Kanade 法
現(xiàn)在我們要使用第二條假設(shè),鄰域內(nèi)的所有點(diǎn)都有相似的運(yùn)動。LucasKanade 法就是利用一個 3x3 鄰域中的 9 個點(diǎn)具有相同運(yùn)動的這一點(diǎn)。這樣我們就可以找到這 9 個點(diǎn)的光流方程,用它們組成一個具有兩個未知數(shù) 9 個等式的方程組,這是一個約束條件過多的方程組。一個好的解決方法就是使用最小二乘擬合。下面就是求解結(jié)果:
(有沒有發(fā)現(xiàn)上邊的逆矩陣與 Harris 角點(diǎn)檢測器非常相似,這說明角點(diǎn)很適合被用來做跟蹤)
從使用者的角度來看,想法很簡單,我們?nèi)「櫼恍c(diǎn),然后我們就會獲得這些點(diǎn)的光流向量。但是還有一些問題。直到現(xiàn)在我們處理的都是很小的運(yùn)動。如果有大的運(yùn)動怎么辦呢?圖像金字塔。我們可以使用圖像金字塔的頂層,此時(shí)小的運(yùn)動被移除,大的運(yùn)動裝換成了小的運(yùn)動,現(xiàn)在再使用 Lucas-Kanade算法,我們就會得到尺度空間上的光流。
OpenCV 中的 Lucas-Kanade 光流
上述所有過程都被 OpenCV 打包成了一個函數(shù)cv2.calcOpticalFlowPyrLK()。現(xiàn)在我們使用這個函數(shù)創(chuàng)建一個小程序來跟蹤視頻中的一些點(diǎn)。要跟蹤那些點(diǎn)呢?我們使用函數(shù)cv2.goodFeatureToTrack() 來確定要跟蹤的點(diǎn)。我們首先在視頻的第一幀圖像中檢測一些 Shi-Tomasi 角點(diǎn),然后我們使用 LucasKanade 算法迭代跟蹤這些角點(diǎn)。我們要給函數(shù) cv2.calcOpticlaFlowPyrLK()傳入前一幀圖像和其中的點(diǎn),以及下一幀圖像。函數(shù)將返回帶有狀態(tài)數(shù)的點(diǎn),如果狀態(tài)數(shù)是 1,那說明在下一幀圖像中找到了這個點(diǎn)(上一幀中角點(diǎn)),如果狀態(tài)數(shù)是 0,就說明沒有在下一幀圖像中找到這個點(diǎn)。我們再把這些點(diǎn)作為參數(shù)傳給函數(shù),如此迭代下去實(shí)現(xiàn)跟蹤。代碼如下:
(上面的代碼沒有對返回角點(diǎn)的正確性進(jìn)行檢查。圖像中的一些特征點(diǎn)甚至在丟失以后,光流還會找到一個預(yù)期相似的點(diǎn)。所以為了實(shí)現(xiàn)穩(wěn)定的跟蹤,我們應(yīng)該每個一定間隔就要進(jìn)行一次角點(diǎn)檢測。OpenCV 的官方示例中帶有這樣一個例子,它是每 5 幀進(jìn)行一個特征點(diǎn)檢測。它還對光流點(diǎn)使用反向檢測來選取好的點(diǎn)進(jìn)行跟蹤。示例為/samples/python2/lk_track.py)
下面是我的到的結(jié)果:
OpenCV 中的稠密光流
Lucas-Kanade 法是計(jì)算一些特征點(diǎn)的光流(我們上面的例子使用的是Shi-Tomasi 算法檢測到的角點(diǎn))。OpenCV 還提供了一種計(jì)算稠密光流的方法。它會圖像中的所有點(diǎn)的光流。這是基于 Gunner_Farneback 的算法(2003 年)。
下面的例子就是使用上面的算法計(jì)算稠密光流。結(jié)果是一個帶有光流向量(u,v)的雙通道數(shù)組。通過計(jì)算我們能得到光流的大小和方向。我們使用顏色對結(jié)果進(jìn)行編碼以便于更好的觀察。方向?qū)?yīng)于 H(Hue)通道,大小對應(yīng)于 V(Value)通道。代碼如下:
結(jié)果如下:
OpenCV 的官方示例中有一個更高級的稠密光流/samples/python2/opt_flow.py,去搞定它吧!
總結(jié)
以上是生活随笔為你收集整理的光流的概念以及 Lucas-Kanade 光流法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言程序设计项目化教程第二版130,C
- 下一篇: 酷狗繁星新人如何把握第一个月?酷狗繁星新