【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 mask


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()

実行結果

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

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

【Python版OpenCV超入門】使い方とサンプルコードを解説
Python版OpenCVで画像処理プログラミングを行う方法を入門者向けにソースコード付きで解説するページです。
【画像処理入門】アルゴリズム&プログラミング
画像処理における基本的なアルゴリズムとその実装例(プログラム)についてまとめました。

コメント

  1. おでこ より:

    こんにちは.
    現在,フレーム間差分して差分が大きかった時のフレームを保存するプロセスと,保存された画像をftpサーバへ送信するプロセスを並列で行いたいと考えています.並列で行う理由としてはftpサーバへの送信に時間がかかり,その間フレーム取得できなくなってしまうからです.
    まだまだpython初心者で並列処理の書き方がわかりません.保存した画像ファイル名をリストに入れていき,ftpサーバのプロセスの方で先頭から順番に送っていきたいです.
    教えてください.

  2. ふもひい より:

    def frame_sub(img1, img2, img3, th):

    # メディアンフィルタ処理(ゴマ塩ノイズ除去)
    mask = cv2.medianBlur(diff, 5)
    の部分の
    maskはローカルスコープのように見えます。意図が理解できません。
    どこに効果が及ぶのでしょうか?