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