この記事では、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で画像処理プログラミングを行う方法を入門者向けにソースコード付きで解説するページです。
【画像処理入門】アルゴリズム&プログラミング
画像処理における基本的なアルゴリズムとその実装例(プログラム)についてまとめました。
コメント
こんにちは.
現在,フレーム間差分して差分が大きかった時のフレームを保存するプロセスと,保存された画像をftpサーバへ送信するプロセスを並列で行いたいと考えています.並列で行う理由としてはftpサーバへの送信に時間がかかり,その間フレーム取得できなくなってしまうからです.
まだまだpython初心者で並列処理の書き方がわかりません.保存した画像ファイル名をリストに入れていき,ftpサーバのプロセスの方で先頭から順番に送っていきたいです.
教えてください.
※おでこ様
コメントありがとうございます。
並列処理については私もPythonで試したことがないのですが、
下記のサイト様を参考にされてはいかかがでしょうか。
Python並列処理(multiprocessingとJoblib)
https://qiita.com/yukiB/items/203a6248c2d466b80d38
def frame_sub(img1, img2, img3, th):
の
# メディアンフィルタ処理(ゴマ塩ノイズ除去)
mask = cv2.medianBlur(diff, 5)
の部分の
maskはローカルスコープのように見えます。意図が理解できません。
どこに効果が及ぶのでしょうか?
ご指摘ありがとうございます。誤記でしたので修正しました。
ありがとうございます。
腑に落とすことができました。