日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

光流的概念以及 Lucas-Kanade 光流法

發布時間:2023/12/20 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 光流的概念以及 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)

    # -*- coding: utf-8 -*- """ Created on Mon Jan 27 12:28:25 2014 @author: duan """ import numpy as np import cv2 cap = cv2.VideoCapture('slow.flv') # params for ShiTomasi corner detection feature_params = dict( maxCorners = 100, qualityLevel = 0.3, minDistance = 7, blockSize = 7 ) # Parameters for lucas kanade optical flow #maxLevel 為使用的圖像金字塔層數 lk_params = dict( winSize = (15,15), maxLevel = 2, criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)) # Create some random colors color = np.random.randint(0,255,(100,3)) # Take first frame and find corners in it ret, old_frame = cap.read() old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY) p0 = cv2.goodFeaturesToTrack(old_gray, mask = None, **feature_params) # Create a mask image for drawing purposes mask = np.zeros_like(old_frame) while(1): ret,frame = cap.read() frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # calculate optical flow 能夠獲取點的新位置 p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params) # Select good points good_new = p1[st==1] good_old = p0[st==1] # draw the tracks for i,(new,old) in enumerate(zip(good_new,good_old)): a,b = new.ravel() c,d = old.ravel() mask = cv2.line(mask, (a,b),(c,d), color[i].tolist(), 2) frame = cv2.circle(frame,(a,b),5,color[i].tolist(),-1) img = cv2.add(frame,mask) cv2.imshow('frame',img) k = cv2.waitKey(30) & 0xff if k == 27: break # Now update the previous frame and previous points old_gray = frame_gray.copy() p0 = good_new.reshape(-1,1,2) cv2.destroyAllWindows() cap.release()

    下面是我的到的結果:

    OpenCV 中的稠密光流
      Lucas-Kanade 法是計算一些特征點的光流(我們上面的例子使用的是Shi-Tomasi 算法檢測到的角點)。OpenCV 還提供了一種計算稠密光流的方法。它會圖像中的所有點的光流。這是基于 Gunner_Farneback 的算法(2003 年)。
      下面的例子就是使用上面的算法計算稠密光流。結果是一個帶有光流向量(u,v)的雙通道數組。通過計算我們能得到光流的大小和方向。我們使用顏色對結果進行編碼以便于更好的觀察。方向對應于 H(Hue)通道,大小對應于 V(Value)通道。代碼如下:

    # -*- coding: utf-8 -*- """ Created on Mon Jan 27 12:28:46 2014 @author: duan """ import cv2 import numpy as np cap = cv2.VideoCapture("vtest.avi") ret, frame1 = cap.read() prvs = cv2.cvtColor(frame1,cv2.COLOR_BGR2GRAY) hsv = np.zeros_like(frame1) hsv[...,1] = 255 while(1): ret, frame2 = cap.read() next = cv2.cvtColor(frame2,cv2.COLOR_BGR2GRAY) #cv2.calcOpticalFlowFarneback(prev, next, pyr_scale, levels, winsize, iterations, poly_n, #poly_sigma, flags[) #pyr_scale – parameter, specifying the image scale (<1) to build pyramids for each image; #pyr_scale=0.5 means a classical pyramid, where each next layer is twice smaller than the #previous one. #poly_n – size of the pixel neighborhood used to find polynomial expansion in each pixel; #typically poly_n =5 or 7. #poly_sigma – standard deviation of the Gaussian that is used to smooth derivatives used #as a basis for the polynomial expansion; for poly_n=5, you can set poly_sigma=1.1, for #poly_n=7, a good value would be poly_sigma=1.5. #flag 可選 0 或 1,0 計算快,1 慢但準確 flow = cv2.calcOpticalFlowFarneback(prvs,next, None, 0.5, 3, 15, 3, 5, 1.2, 0) #cv2.cartToPolar Calculates the magnitude and angle of 2D vectors. mag, ang = cv2.cartToPolar(flow[...,0], flow[...,1]) hsv[...,0] = ang*180/np.pi/2 hsv[...,2] = cv2.normalize(mag,None,0,255,cv2.NORM_MINMAX) rgb = cv2.cvtColor(hsv,cv2.COLOR_HSV2BGR) cv2.imshow('frame2',rgb) k = cv2.waitKey(30) & 0xff if k == 27: break elif k == ord('s'): cv2.imwrite('opticalfb.png',frame2) cv2.imwrite('opticalhsv.png',rgb) prvs = next cap.release() cv2.destroyAllWindows()

    結果如下:

    OpenCV 的官方示例中有一個更高級的稠密光流/samples/python2/opt_flow.py,去搞定它吧!

    總結

    以上是生活随笔為你收集整理的光流的概念以及 Lucas-Kanade 光流法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。