2

静的な (ほとんどの) 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()
4

2 に答える 2

1

代わりに、平均と標準偏差の使用を手動で計算する必要はないと思いますcv2.meanStdDev。以下のコードでは、から計算された平均背景行列を使用しています

M = acc/float(BGsample) 

これで、平均背景画像の平均と標準偏差を計算し、最終的にinRange必要な範囲を引き出すために使用できます (つまり、平均 +/- 1 標準偏差)。

(mu, sigma) = cv2.meanStdDev(M)
fg = cv2.inRange(M, (mu[0] - sigma[0]), (mu[0] + sigma[0]))
# proceed with morphological clean-up here...

それが役立つことを願っています!

于 2012-04-02T13:52:24.760 に答える
0

これまでの私の最善の推測。detectmin, max を使用して、cv2.inRange が使用できるように fp シグマをグレースケールに変換します。正常に動作しているようですが、より良いものを期待していました...有効な FG データに多くの穴があります。グレースケールではなくRGBの方がうまくいくと思います。dilate や erode を使ってノイズを減らすことができません。

改善点はありますか?

import cv2
import numpy as np


if __name__ == '__main__': 
    cap = cv2.VideoCapture(1)
    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)
    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
        # calculate upper and lower bounds of detection window around mean.
        # coerce into 8bit image space for cv2.inRange compare
        detectmin = cv2.convertScaleAbs(M-sig2)
        detectmax = cv2.convertScaleAbs(M+sig2)
        # start FG detection
        key = -1
        while(key < 0):
            success, img = cap.read()
            frame = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            level = cv2.inRange(frame, detectmin, detectmax)
            cv2.imshow("input", frame)
            #cv2.imshow("sig2", M/200)
            cv2.imshow("detect", level)
            key = cv2.waitKey(1)
    cv2.destroyAllWindows()
于 2012-04-03T11:54:50.990 に答える