機器學習進階-光流估計 1.cv2.goodFeaturesToTrack(找出光流估計所需要的角點) 2.cv2.calcOpticalFlowPyrLK(獲得光流檢測后的角點位置) 3.cv2.add(進行像素點的加和)


1.cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)  用於獲得光流估計所需要的角點
參數說明:old_gray表示輸入圖片,mask表示掩模,feature_params:maxCorners=100角點的最大個數,qualityLevel=0.3角點品質,minDistance=7即在這個范圍內只存在一個品質最好的角點
2. pl, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)  用於獲得光流檢測后的角點位置

參數說明:pl表示光流檢測后的角點位置,st表示是否是運動的角點,err表示是否出錯,old_gray表示輸入前一幀圖片,frame_gray表示后一幀圖片,p0表示需要檢測的角點,lk_params:winSize表示選擇多少個點進行u和v的求解,maxLevel表示空間金字塔的層數

3. cv2.add(frame, mask) # 將兩個圖像的像素進行加和操作

參數說明:frame表示輸入圖片,mask表示掩模

光流估計:通過當前時刻與前一時刻的亮度不變的特性I(x, y, t) = I(x+∆x, y+∆y, t+∆t) 使用lucas-kanade算法進行求解問題, 我們需要求得的是x,y方向的速度

下面是lucas-kanade的推導公式, 即位置發生變動時,其像素點的大小沒有發生變化, 

I(x, y, t) = I(x+dx, y+dy, t+dt)  

             = I(x, y, t) + Ixdx + Iydy + Itdt 使用泰勒基數進行展開
       對上式進行化解即: 

                               Ixdx + Iydy + Itdt = 0  Ix表示x軸的梯度方向,Iy表示y軸的梯度方向,It表示單位時間上的像素點的變化
                               如果我們使用前后兩幀的變化, 那么dx和dy也就是表示x軸和y軸的速度,返回的結果是dx和dy,即在x軸和y軸方向上移動的步數,我們就可以知道目標的位置了

下面是實際求解u和v的過程,根據上述的空間一致性,我們選擇出關鍵點周圍的25個點進行求解,即(5, 5)的方框, 構造Au = b 進行求解,我們可以看出(A^T*A)^-1

但是當前像素點不一定可逆,如果保證可逆呢,即A^T*A的特征值λ1和λ2接近相等且較大,符合條件的就是角點, 因此使用角點去求解u和v

代碼:

第一步:使用cv2.capture讀入視頻

第二步:構造角點檢測所需參數, 構造lucas kanade參數

第三步:拿到第一幀圖像,並做灰度化, 作為光流檢測的前一幀圖像

第四步:使用cv2.goodFeaturesToTrack獲得光流檢測所需要的角點

第五步:構造一個mask用於畫直線

第六步:讀取一張圖片,進行灰度化,作為光流檢測的后一幀圖像

第七步:使用cv2.caclOpticalFlowPyrLK進行光流檢測

第八步:使用st==1獲得運動后的角點,原始的角點位置

第九步:循環獲得角點的位置,在mask圖上畫line,在后一幀圖像上畫角點

第十步:使用cv2.add()將mask和frame的像素點相加並進行展示

第十一步:使用后一幀的圖像更新前一幀的圖像,同時使用運動的后一幀的角點位置來代替光流檢測需要的角點

import numpy as np
import cv2


# 第一步:視頻的讀入
cap = cv2.VideoCapture('test.avi')

# 第二步:構建角點檢測所需參數
feature_params = dict(maxCorners=100,
                      qualityLevel=0.3,
                      minDistance=7)

# lucas kanade參數
lk_params = dict(winSize=(15, 15),
                 maxLevel=2)

# 隨機顏色條
color = np.random.randint(0, 255, (100, 3))

# 第三步:拿到第一幀圖像並灰度化作為前一幀圖片
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
# 第四步:返回所有檢測特征點,需要輸入圖片,角點的最大數量,品質因子,minDistance=7如果這個角點里有比這個強的就不要這個弱的
p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)

# 第五步:創建一個mask, 用於進行橫線的繪制
mask = np.zeros_like(old_frame)

while(True):
    # 第六步:讀取圖片灰度化作為后一張圖片的輸入
    ret, frame = cap.read()
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 第七步:進行光流檢測需要輸入前一幀和當前圖像及前一幀檢測到的角點
    pl, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)

    # 第八步:讀取運動了的角點st == 1表示檢測到的運動物體,即v和u表示為0
    good_new = pl[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) & 0xff
    if k == 27:
        break

    # 第十一步:更新前一幀圖片和角點的位置
    old_gray = frame_gray.copy()
    p0 = good_new.reshape(-1, 1, 2)
    # p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)

cv2.destroyAllWindows()
cap.release()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM