【Python/OpenCV】フレーム間差分法で監視カメラの作成

この記事では、Python版OpenCVでフレーム間差分法を実装し、移動物体を検出する方法をソースコード付きで解説します。

フレーム間差分法で不審者の検出

フレーム間差分法は、移動物体の検出方法の1つです。
連続する画像の差分から動体を検出することができます。
この方法の大きな特徴としては、背景差分法のように背景画像(モデル)を用意する必要がない点です。
【参考】フレーム差分法の原理・特徴・計算式

今回は、PythonとOpenCVでフレーム間差分法を実装し、不審者を検出する簡単な監視カメラを作成してみました。

ソースコード(Python3+OpenCV3)

サンプルプログラムのソースコードです。

# -*- coding: utf-8 -*-
import cv2
import numpy as np

# フレーム差分の計算
def frame_sub(img1, img2, img3, th):
    # フレームの絶対差分
    diff1 = cv2.absdiff(img1, img2)
    diff2 = cv2.absdiff(img2, img3)

    # 2つの差分画像の論理積
    diff = cv2.bitwise_and(diff1, diff2)

    # 二値化処理
    diff[diff < th] = 0
    diff[diff >= th] = 255
    
    # メディアンフィルタ処理(ゴマ塩ノイズ除去)
    mask = cv2.medianBlur(diff, 5)

    return diff


def main():
    # 不審物判定の閾値
    min_moment = 1000

    # カメラのキャプチャ
    cap = cv2.VideoCapture(0)
    
    # フレームを3枚取得してグレースケール変換
    frame1 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY)
    frame2 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY)
    frame3 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY)
    
    # カウント変数の初期化
    cnt = 0

    while(cap.isOpened()):
        # フレーム間差分を計算
        mask = frame_sub(frame1, frame2, frame3, th=10)

        # 白色領域のピクセル数を算出
        moment = cv2.countNonZero(mask)

        # 白色領域のピクセル数が一定以上なら不審物有りと判定
        if moment > min_moment:
            print("不審物を検出しました:", cnt)
            filename = "frame" + str(cnt) + ".jpg"
            cv2.imwrite(filename, frame2)
            cnt += 1

        # 結果を表示
        cv2.imshow("Frame2", frame2)
        cv2.imshow("Mask", mask)

        # 3枚のフレームを更新
        frame1 = frame2
        frame2 = frame3
        frame3 = cv2.cvtColor(cap.read()[1], cv2.COLOR_RGB2GRAY)
        
        # qキーが押されたら途中終了
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    cap.release()
    cv2.destroyAllWindows()


if __name__ == '__main__':
    main()

実行結果

サンプルプログラムの実行結果です。

移動物体(不審物)を検知したら、その瞬間のフレームを自動的に保存します。

関連記事
1 PythonでOpenCV入門 サンプル集
2 【Python】画像処理プログラミング入門
3 【画像処理入門】アルゴリズム&プログラミング

シェア&フォローお願いします!