一、什么是光流?
光流(Optical Flow)是計算機視覺中描述圖像序列中像素運動模式的重要概念。它表示圖像中物體在連續幀之間的表觀運動,是由物體或相機的運動引起的。
光流的基本假設
- 亮度恒常性:同一物體點在連續幀中的亮度保持不變
- 時間持續性:運動隨時間緩慢變化
- 空間一致性:鄰近點有相似的運動
二、OpenCV中的光流算法
OpenCV提供了多種光流算法的實現,主要包括:
1. Lucas-Kanade方法
import cv2
import numpy as np# 讀取視頻
cap = cv2.VideoCapture('test.mp4')# 參數設置
feature_params = dict(maxCorners=100, qualityLevel=0.3, minDistance=7, blockSize=7)
lk_params = dict(winSize=(15,15), maxLevel=2, criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))# 讀取第一幀
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)# 創建隨機顏色
color = np.random.randint(0,255,(100,3))while(1):ret, frame = cap.read()if not ret:breakframe_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()frame = cv2.line(frame, (a,b),(c,d), color[i].tolist(), 2)frame = cv2.circle(frame,(a,b),5,color[i].tolist(),-1)cv2.imshow('frame',frame)k = cv2.waitKey(30) & 0xffif k == 27:break# 更新前一幀和特征點old_gray = frame_gray.copy()p0 = good_new.reshape(-1,1,2)cv2.destroyAllWindows()
cap.release()
2. Farneback稠密光流
import cv2
import numpy as npcap = cv2.VideoCapture('test.mp4')ret, frame1 = cap.read()
prvs = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1)
hsv[...,1] = 255while(1):ret, frame2 = cap.read()if not ret:breaknext = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)# 計算稠密光流flow = cv2.calcOpticalFlowFarneback(prvs, next, None, 0.5, 3, 15, 3, 5, 1.2, 0)# 轉換為極坐標mag, ang = cv2.cartToPolar(flow[...,0], flow[...,1])hsv[...,0] = ang*180/np.pi/2hsv[...,2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)cv2.imshow('frame2', bgr)k = cv2.waitKey(30) & 0xffif k == 27:breakelif k == ord('s'):cv2.imwrite('opticalfb.png',frame2)cv2.imwrite('opticalhsv.png',bgr)prvs = nextcap.release()
cv2.destroyAllWindows()
3. DeepFlow和DIS光流
OpenCV還提供了基于深度學習的DIS(Dense Inverse Search)光流算法:
# 初始化DIS光流
dis = cv2.DISOpticalFlow_create(cv2.DISOPTICAL_FLOW_PRESET_FAST)# 計算光流
flow = dis.calc(prev_frame, next_frame, None)
三、光流估計的應用
- 運動檢測與跟蹤:通過光流可以檢測視頻中的運動物體
- 視頻穩定:利用光流估計相機運動并進行補償
- 動作識別:分析人體關節點的光流模式來識別動作
- 自動駕駛:估計車輛自身運動和周圍物體的運動
- 視頻插幀:基于光流生成中間幀
四、光流估計的挑戰與改進
- 光照變化:亮度恒常性假設在實際中常被違反
- 遮擋問題:物體被遮擋時難以追蹤
- 快速運動:大位移運動難以捕捉
- 計算效率:實時性要求高的場景需要優化
改進方法:
- 使用深度學習模型如FlowNet、PWC-Net
- 多尺度處理
- 結合其他特征如深度信息
五、總結
OpenCV提供了豐富的光流估計算法實現,從經典的Lucas-Kanade到基于深度學習的方法。理解光流的基本原理并掌握OpenCV中的實現方法,能夠為計算機視覺應用的開發奠定堅實基礎。在實際應用中,需要根據具體場景選擇合適的光流算法,并考慮其精度和效率的平衡。