一、LK光流法三個假設
LK (Lucas-Kanade) 光流法是一種經典的光流估計方法,它的基本思想是假設當前幀的鄰域基本保持不變,那麼在相鄰兩幀之間發生的小運動可以用鄰域內每個像素的位移來描述。LK光流法主要基於以下三個假設:
1. 亮度恆定假設
它假設在時間和空間上相鄰的像素點之間的亮度是恆定的,即對於同一物體表面上的點,在單位時間內,它們在圖像上呈現的亮度不變,即I(x, y, t) = I(x+dx, y+dy, t+dt),其中(x,y)是該像素的坐標,t是時間,I(x, y, t)是在該坐標和時間下的灰度值。
2. 運動場稠密性假設
它假設觀測場景的所有像素都有運動,即在圖像中的所有像素都有相應的運動向量。
3. 空間鄰域一致性假設
它假設位於空間鄰域內的像素點具有相似的運動向量。
二、KLT光流法
KLT (Kanade-Lucas-Tomasi) 光流法是在LK光流法的基礎上發展而來的一種光流算法,主要用於檢測角點並跟蹤它們在不同幀之間的運動。
具體而言,KLT光流法通過對圖像中的關鍵點進行跟蹤,來實現處於場景中的關鍵物體跟蹤。其基本思路是選取具有高變化率的像素點,即角點,作為特徵點進行跟蹤。
在實際應用中,KLT光流法最常用於運動圖像中關鍵特徵的跟蹤,如人臉、機械人等。
三、LK光流法估計旋轉
LK光流法雖然可以用於多種目標跟蹤問題,但是它存在一些問題。例如,當物體在原地旋轉時,它的像素值的亮度分佈不會改變,這樣LK光流法就無法捕捉到這些運動信息。
為了解決這個問題,LK光流法被更新成可以估計旋轉的方法,這個方法被稱為LK-R (Lucas-Kanade-Rotations) 光流法。
在LK-R光流法中,旋轉被認為是慣性運動的一種形式。當物體發生旋轉時,像素的亮度不會改變,但是它們會沿着圓周運動。因此,LK-R光流法不僅可以通過估計位移來捕捉水平和垂直運動的信息,還可以通過估計旋轉角度來捕捉目標的旋轉運動信息。
代碼示例
import cv2 cap = cv2.VideoCapture(0) # previous frame ret, previous_frame = cap.read() previous_frame_gray = cv2.cvtColor(previous_frame, cv2.COLOR_BGR2GRAY) # set first frame # to get initial keypoints and previous frame lk_params = dict(winSize=(15, 15), maxLevel=4, criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)) previous_keypoints = cv2.goodFeaturesToTrack(previous_frame_gray, 100, 0.3, 7) previous_keypoints = previous_keypoints.reshape(-1, 1, 2) # loop over video frames while cap.isOpened(): ret, frame = cap.read() if ret: # convert to grayscale current_frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # calculate optical flow current_keypoints, status, errors = cv2.calcOpticalFlowPyrLK(previous_frame_gray, current_frame_gray, previous_keypoints, None, **lk_params) # select good keypoints good_new = current_keypoints[status == 1] good_old = previous_keypoints[status == 1] # draw flow for i, (new, old) in enumerate(zip(good_new, good_old)): pa, pb = new.ravel() qa, qb = old.ravel() mask = cv2.line(mask, (pa, pb), (qa, qb), (0, 255, 0), 2) frame = cv2.circle(frame, (pa, pb), 5, (0, 0, 255), -1) # show flow img = cv2.add(frame, mask) cv2.imshow('flow', img) # update the previous frame and keypoints previous_frame_gray = current_frame_gray.copy() previous_keypoints = good_new.reshape(-1, 1, 2) # press "q" to quit if cv2.waitKey(100) & 0xFF == ord('q'): break else: break # release the capture and close the window cap.release() cv2.destroyAllWindows()
原創文章,作者:FRZT,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/142738.html