静的な (ほとんどの) BG 要素を削除して、opencv2 を使用してフォアグラウンド モーションを検出しようとしています。私が使用している方法は、背景を表す一連の画像の平均を取ることに基づいています。次に、その平均の上下に 1 つの標準偏差を計算します。それをウィンドウとして使用して、前景の動きを検出します。
このメカニズムは、BG で木が揺れるような適度にノイズの多い環境でうまく機能すると報告されています。
必要な出力は、以降の処理を最小限に抑えるために後続の操作で使用できるマスクです。具体的には、その領域内でオプティカル フロー検出を使用します。
cv2 ではこれがはるかに簡単になり、コードも読みやすく理解しやすくなりました。cv2 と numpy に感謝します。
しかし、正しい FG 検出を行うのが困難です。
理想的には、1 ピクセルのノイズを除去するために BG 平均を浸食/膨張させたいと考えています。
コードはすべて一緒なので、FG 検出が開始される前に BG データを収集するために、最初 (BGsample) に多数のフレームがあります。唯一の依存関係は opencv2 (> 2.3.1 ) と numpy (> opencv 2.3.1 に含まれている必要があります) です。
import cv2
import numpy as np
if __name__ == '__main__':
cap = cv2.VideoCapture(0) # webcam
cv2.namedWindow("input")
cv2.namedWindow("sig2")
cv2.namedWindow("detect")
BGsample = 20 # number of frames to gather BG samples from at start of capture
success, img = cap.read()
width = cap.get(3)
height = cap.get(4)
# can use img.shape(:-1) # cut off extra channels
if success:
acc = np.zeros((height, width), np.float32) # 32 bit accumulator
sqacc = np.zeros((height, width), np.float32) # 32 bit accumulator
for i in range(20): a = cap.read() # dummy to warm up sensor
# gather BG samples
for i in range(BGsample):
success, img = cap.read()
frame = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.accumulate(frame, acc)
cv2.accumulateSquare(frame, sqacc)
#
M = acc/float(BGsample)
sqaccM = sqacc/float(BGsample)
M2 = M*M
sig2 = sqaccM-M2
# have BG samples now
# start FG detection
key = -1
while(key < 0):
success, img = cap.read()
frame = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#Ideally we create a mask for future use that is B/W for FG objects
# (using erode or dilate to remove noise)
# this isn't quite right
level = M+sig2-frame
grey = cv2.morphologyEx(level, cv2.MORPH_DILATE,
cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3)), iterations=2)
cv2.imshow("input", frame)
cv2.imshow("sig2", sig2/60)
cv2.imshow("detect", grey/20)
key = cv2.waitKey(1)
cv2.destroyAllWindows()