光流是空間運動物體在觀測成像平面上的像素運動的“瞬間速度”,根據各個像素點的速度矢量特征,可以對圖像進行動態分析,例如目標跟蹤
亮度恒定:同一點隨著時間的變化,其亮度不會發生改變
小運動:隨著時間的變化不會引起位置的劇烈變化,只有小運動情況下才能用前后幀之間單位位置變化引起的灰度變化去近似灰度對位置的偏導數
空間一致:一個場景上鄰近的點投影到圖像上也是鄰近點,且鄰近點速度一致。因為光流法基本方程約束只有一個,而要求x,y方向的速度,有兩個未知變量,所以需要聯立n多個方程求解
Lucas—Kanade算法
約束方程
如何求解方程組呢?看起來一個像素點根本不夠,在物體移動過程中還有哪些特性呢?
cv2.calcOpticalFlowPyrLK():
cv2.calcOpticalFlowPyrLK(old_gray,frame_gray,p0,None,**lk_params)
參數:
prevImage 前一幀圖像
nextImage 當前幀圖像
prePts 待跟蹤的特征點向量
winSize 搜索窗口的大小
maxLevel 最大的金字塔層數
返回:
nextPts 輸出跟蹤特征點向量
status 特征點是否找到,找到的狀態為1,未找到的狀態為0
import numpy as np
import cv2#E:\Jupyter_workspace\study\data/a.mp4視頻最好為攝像頭捕獲視頻,背景相對不變,變化得是行人汽車之類的較為容易識別得物體
cap = cv2.VideoCapture('E:\Jupyter_workspace\study\data/a.mp4')feature_params = dict(maxCorners = 100, qualityLevel = 0.3, minDistance = 7)#角點檢測所需參數
#maxCorners最大角點個數100個
#qualityLevel品質因子,越大的話,角點越少
#minDistance最小距離,在這個距離里面那個角點最好,品質因子最好lk_params = dict(winSize = (15,15), maxLevel = 2)#lucas kanade參數color = np.random.randint(0,255,(100,3))#隨機顏色條ret, old_frame = cap.read()#拿到第一幀圖像
old_gray = cv2.cvtColor(old_frame,cv2.COLOR_BGR2GRAY)#將第一幀圖像進行灰度圖轉換#返回所有檢測特征點,需要輸入圖像,角點最大數量(效率),品質因子(特征值越大得越好,來篩選)
#距離相當于這區間有比這個角點強的,就不要這個弱的了
p0 = cv2.goodFeaturesToTrack(old_gray,mask = None,**feature_params)#獲取第一幀圖像得角點mask = np.zeros_like(old_frame)#創建一個maskwhile(True):ret, frame = cap.read()#每次循環讀取一幀圖像frame_gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)#轉換為灰度圖p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)#需要傳入前一幀和當前圖像以及前一幀檢測到的角點good_new = p1[st==1]good_old = p0[st==1]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(150) & 0xffif k==27:break #更新old_gray = frame_gray.copy()p0 = good_new.reshape(-1,1,2)cv2.destroyAllWindows()
cap.release()