文章目錄
- 前言
- 一、光流估計
- 二、使用步驟
- 1、導庫讀取視頻、隨機初始化顏色
- 2、初始化光流跟蹤
- 3、視頻幀處理循環
- 4、光流計算與可視化
- 5、循環控制與資源釋放
- 完整代碼
- 總結
前言
在計算機視覺領域,光流估計是捕捉圖像序列中像素點運動信息的核心技術。它描述了圖像中每個像素點在相鄰幀間的運動方向和速度,能從靜態圖像幀中解析出動態變化。
光流估計基于像素亮度不變和運動平滑兩個關鍵假設,通過數學建模解算出像素運動場,為視頻分析、目標跟蹤等任務提供基礎。OpenCV 集成了稀疏光流、稠密光流等計算方法,廣泛應用于無人機避障、電影特效等場景。
接下來,我們將深入解析光流估計原理、OpenCV 函數使用及實戰應用,探索這項技術的奧秘。
一、光流估計
光流估計是空間運動物體在觀測成像平面上的像素運動的“瞬時速度”,根據各個像素點的速度矢量特征,可以對圖像進行動態分析,例如目標跟蹤。
光流估計的前提:
(1)亮度恒定:同一點隨著時間的變化,其亮度不會發生改變。
(2)小運動:隨著時間的變化不會引起位置的劇烈變化,只有小運動情況下才能用前后幀之間單位位置變化引起的灰度變化去近似灰度對位置的偏導數。
(3)空間一致:一個場景上鄰近的點投影到圖像上也是鄰近點,且鄰近點速度一致。因為光流法基本方程約束只有一個,而要求x,y方向的速度,有兩個未知變量。所以需要連立n多個方程求解。
?
二、使用步驟
1、導庫讀取視頻、隨機初始化顏色
# 導入數值計算庫和計算機視覺庫
import numpy as np
import cv2# 創建視頻捕獲對象,讀取測試視頻
cap = cv2.VideoCapture('../data/test.avi')# 生成100種隨機顏色,用于不同特征點的軌跡繪制
# 格式為(100,3)的數組,每個元素代表BGR顏色值
color = np.random.randint(0, 255, (100, 3))
2、初始化光流跟蹤
# 讀取視頻第一幀
ret, old_frame = cap.read()# 將第一幀轉換為灰度圖像(光流算法需要灰度輸入)
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)# 設置特征點檢測參數字典
feature_params = dict(maxCorners = 100, # 檢測的最大特征點數量qualityLevel = 0.3, # 特征點質量閾值(0-1,值越大質量越高)minDistance = 7 # 特征點之間的最小像素距離
)# 使用Shi-Tomasi算法檢測角點特征
# goodFeaturesToTrack:在灰度圖像中尋找適合跟蹤的強角點
p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)# 創建與視頻幀同尺寸的全黑圖像,用于繪制運動軌跡
mask = np.zeros_like(old_frame)# 設置Lucas-Kanade光流算法參數
lk_params = dict(winSize = (15, 15), # 每個金字塔層的搜索窗口大小maxLevel = 2 # 金字塔層數(0表示不使用金字塔)
)
3、視頻幀處理循環
while True:# 讀取新幀ret, frame = cap.read()# 視頻結束或讀取失敗時退出循環if not ret:break# 將當前幀轉換為灰度圖像frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
4、光流計算與可視化
# 使用Lucas-Kanade金字塔光流法計算特征點運動# p1:新幀中特征點位置# st:狀態標記(1表示成功跟蹤,0表示丟失)# err:跟蹤誤差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().astype(int)c, d = old.ravel().astype(int)# 在mask圖像上繪制運動軌跡線# 參數:目標圖像,起點,終點,顏色,線寬mask = cv2.line(mask, (a, b), (c, d), color[i].tolist(), 2)# 顯示純軌跡圖像cv2.imshow("mask", mask)# 將軌跡疊加到原始幀上img = cv2.add(frame, mask)# 顯示疊加后的結果幀cv2.imshow('frame', img)
5、循環控制與資源釋放
# 等待150ms并檢測ESC按鍵(ASCII 27)k = cv2.waitKey(150)if k == 27:break# 更新前一幀數據old_gray = frame_gray.copy() # 更新灰度圖像# 更新特征點(只保留成功跟蹤的點)# reshape(-1,1,2)保持與原始p0相同的維度結構p0 = good_new.reshape(-1, 1, 2)# 釋放視頻資源并銷毀所有窗口
cv2.destroyAllWindows()
cap.release()
效果:
完整代碼
# 導入必要的庫
import numpy as np
import cv2# 創建視頻捕獲對象,讀取視頻文件
cap = cv2.VideoCapture('../data/test.avi')# 生成隨機顏色數組,用于繪制不同特征點的軌跡(100種顏色)
color = np.random.randint(0, 255, (100, 3))# 讀取視頻的第一幀
ret, old_frame = cap.read()# 將第一幀轉換為灰度圖像
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)# 設置特征點檢測參數
feature_params = dict(maxCorners=100, # 最大特征點數量qualityLevel=0.3, # 特征點質量等級(0-1之間,越大質量越高)minDistance=7 # 特征點之間的最小歐氏距離
)# 使用Shi-Tomasi方法檢測初始特征點(角點檢測)
p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)# 創建一個與視頻幀大小相同的全黑圖像,用于繪制軌跡
mask = np.zeros_like(old_frame)# Lucas-Kanade光流算法參數設置
lk_params = dict(winSize=(15, 15), # 每個金字塔層的搜索窗口大小maxLevel=2 # 金字塔層數(0表示僅當前層)
)# 主循環處理視頻幀
while True:# 讀取新的一幀ret, frame = cap.read()if not ret: # 如果讀取失敗(如視頻結束)則退出循環break# 將當前幀轉換為灰度圖像frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 計算光流(Lucas-Kanade方法)p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, # 前一幀的灰度圖像frame_gray, # 當前幀的灰度圖像p0, # 需要跟蹤的特征點None, # 不使用前一幀的特征點位置**lk_params)# 篩選成功跟蹤的特征點(st=1表示成功跟蹤)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().astype(int)c, d = old.ravel().astype(int)# 在mask上繪制運動軌跡線(使用隨機顏色)mask = cv2.line(mask, (a, b), (c, d), color[i].tolist(), 2)# 將軌跡mask與當前幀疊加顯示img = cv2.add(frame, mask)cv2.imshow('frame', img)cv2.imshow('mask', mask) # 單獨顯示軌跡mask# 等待按鍵(150ms延遲),ESC鍵退出k = cv2.waitKey(150)if k == 27:break# 更新前一幀的灰度圖像和特征點old_gray = frame_gray.copy()p0 = good_new.reshape(-1, 1, 2) # 更新為當前幀的有效特征點# 釋放資源并關閉所有窗口
cv2.destroyAllWindows()
cap.release()
總結
光流估計的應用:
視頻增強與創作:光流不僅用于運動補償壓縮(如MPEG標準),還被應用于視頻插幀(生成中間幀提升流暢度)和特效合成(如電影中動態背景替換),英偉達SDK已展示其商業化潛力。
醫療精準化:在超聲影像中,光流估計校正探頭移動導致的圖像偏移,輔助心臟手術的實時導航;還可量化器官運動參數(如心肌應變率),為疾病診斷提供動態指標。
工業智能化升級:生產線中,光流實時監測機械臂運動軌跡,結合異常檢測算法預防故障;在精密裝配場景,通過微位移分析提升質檢精度。