OpenCV Python - 均值漂移和CamShift



本章我們將學習OpenCV-Python中的均值漂移和CamShift演算法。首先,讓我們瞭解什麼是均值漂移。

均值漂移

均值漂移演算法識別資料集中資料點高度集中的位置,或稱為聚類。該演算法將一個核放置在每個資料點上,並將它們加起來以生成一個**核密度估計**(KDE)。

KDE將分別具有高資料點密度和低資料點密度的位置。均值漂移是一種非常有用的方法,可以跟蹤影片中特定物件。

影片的每個例項都以該幀中畫素分佈的形式進行檢查。初始視窗作為感興趣區域**(ROI)**,通常是正方形或圓形。為此,位置是透過硬編碼指定的,並識別最大畫素分佈的區域。

隨著影片的執行,ROI視窗向最大畫素分佈區域移動。移動方向取決於跟蹤視窗的中心與其視窗內所有k個畫素的質心之間的差異。

為了在OpenCV中使用均值漂移,首先找到目標的直方圖(其中只考慮色調),然後可以將其目標反向投影到每一幀中以計算均值漂移。我們還需要提供ROI視窗的初始位置。

我們重複計算直方圖的反向投影並計算均值漂移以獲得跟蹤視窗的新位置。之後,我們使用其尺寸在幀上繪製一個矩形。

函式

程式中使用的OpenCV函式如下:

  • **cv.calcBackProject()** - 計算直方圖的反向投影。

  • **cv.meanShift()** - 使用初始搜尋視窗和迭代搜尋演算法的停止條件來反向投影目標直方圖。

示例

以下是均值漂移的示例程式:

import numpy as np
import cv2 as cv

cap = cv.VideoCapture('traffic.mp4')

ret,frame = cap.read()

# dimensions of initial location of window
x, y, w, h = 300, 200, 100, 50
tracker = (x, y, w, h)

region = frame[y:y+h, x:x+w]
hsv_reg = cv.cvtColor(region, cv.COLOR_BGR2HSV)
mask = cv.inRange(hsv_reg, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
reg_hist = cv.calcHist([hsv_reg],[0],mask,[180],[0,180])
cv.normalize(reg_hist,reg_hist,0,255,cv.NORM_MINMAX)

# Setup the termination criteria
criteria = ( cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1 )

while(1):
   ret, frame = cap.read()

   if ret == True:
      hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
      dst = cv.calcBackProject([hsv],[0],reg_hist,[0,180],1)

      # apply meanshift
      ret, tracker = cv.meanShift(dst, tracker, criteria)

      # Draw it on image
      x,y,w,h = tracker
      img = cv.rectangle(frame, (x,y), (x+w,y+h), 255,2)
      cv.imshow('img',img)

      k = cv.waitKey(30) & 0xff
      if k==115:
         cv.imwrite('capture.png', img)
      if k == 27:
         break

程式執行時,均值漂移演算法將我們的視窗移動到密度最大的新位置。

輸出

以下是移動視窗的快照:

Meanshift

CamShift

均值漂移演算法的一個缺點是,跟蹤視窗的大小保持不變,無論物體與攝像機的距離如何。此外,只有當物體在該物體的區域內時,窗口才會跟蹤該物體。因此,我們必須手動硬編碼視窗,並且必須小心地進行。

CAMshift(代表**連續自適應均值漂移**)解決了這些問題。一旦均值漂移收斂,CamShift演算法就會更新視窗的大小,以便跟蹤視窗的大小可能會改變,甚至旋轉以更好地與被跟蹤物體的運動相關聯。

在下面的程式碼中,使用camshift()函式代替meanshift()函式。

首先,它使用meanShift查詢物件的中心,然後調整視窗大小並找到最佳旋轉。該函式返回物件的位姿、大小和方向。使用polylines()繪圖函式在幀上繪製位姿。

示例

在之前的程式中,將Meanshift()函式替換為CamShift()函式,如下所示:

# apply camshift
ret, tracker = cv.CamShift(dst, tracker, criteria)
pts = cv.boxPoints(ret)
pts = np.int0(pts)
img = cv.polylines(frame,[pts],True, 255,2)
cv.imshow('img',img)

輸出

以下是修改後的程式結果的一個快照,顯示了跟蹤視窗的旋轉矩形:

Camshift
廣告