PythonでWebカメラの動体検知プログラムを作成する方法
本記事では、Webカメラから取得した映像を解析して動き(モーション)を自動的に検出し、その検出された時間帯をCSVファイルに記録するPythonプログラムを作成します。監視カメラやセキュリティシステムの基礎となる技術であり、OpenCVの画像処理機能を活用した実践的な例です。
必要なライブラリ
このプログラムではOpenCVとpandasを使用します。まだインストールされていない場合は、pipコマンドでインストールできます。
$ pip install opencv-python pandas
サンプルコード
# 必要なライブラリをインポート
import cv2
import pandas as pd
from datetime import datetime
# 変数の初期化
stillImage = None
motionImage = [None, None]
time = []
# 開始時刻と終了時刻を格納するDataFrameを初期化
df = pd.DataFrame(columns=["Start", "End"])
# Webカメラからの映像キャプチャを開始
video = cv2.VideoCapture(0)
while True:
# カメラからフレームを読み込む
check, frame = video.read()
motion = 0
# カラー画像をグレースケールに変換
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21, 21), 0)
# 最初のフレームを基準画像として保持
if stillImage is None:
stillImage = gray
continue
# 基準画像と現在の画像の差分を計算
diff_frame = cv2.absdiff(stillImage, gray)
# 差分の輝度が25より大きいピクセルを白にする(二値化)
thresh_frame = cv2.threshold(diff_frame, 25, 255, cv2.THRESH_BINARY)[1]
thresh_frame = cv2.dilate(thresh_frame, None, iterations=2)
# 動いている物体の輪郭を検出
contours, hierarchy = cv2.findContours(thresh_frame.copy(),
cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
if cv2.contourArea(contour) < 10000:
continue
motion = 1
(x, y, w, h) = cv2.boundingRect(contour)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3)
# 現在のモーション状態を履歴として保持
motionImage.append(motion)
motionImage = motionImage[-2:]
# モーション開始時刻を記録
if motionImage[-1] == 1 and motionImage[-2] == 0:
time.append(datetime.now())
# モーション終了時刻を記録
if motionImage[-1] == 0 and motionImage[-2] == 1:
time.append(datetime.now())
# 各種ウィンドウに画像を表示
cv2.imshow("Gray_Frame", gray)
cv2.imshow("Threshold Frame", thresh_frame)
cv2.imshow("Colored_Frame", frame)
key = cv2.waitKey(1)
# qキーで処理を終了
if key == ord('q'):
if motion == 1:
time.append(datetime.now())
break
# 検出されたモーションの時間をDataFrameに追加
for i in range(0, len(time), 2):
df = df.append({"Start": time[i], "End": time[i + 1]}, ignore_index=True)
# 動きの記録をCSVファイルとして保存
df.to_csv("FrameInMotion_time.csv")
# カメラデバイスを解放
video.release()
# 表示中のウィンドウをすべて閉じる
cv2.destroyAllWindows()
注意:pandas 2.0以降をご利用の場合
DataFrame.append()メソッドはpandas 2.0で廃止されました。新しいバージョンでは、該当箇所を以下のようにpd.concat()に置き換えてください。
new_row = pd.DataFrame([{"Start": time[i], "End": time[i + 1]}])
df = pd.concat([df, new_row], ignore_index=True)
プログラムの仕組み
- 背景との差分計算: 最初に取得したフレームを基準画像として保持し、以降のフレームとの絶対差分(
cv2.absdiff)を計算します。 - 二値化処理: 差分が閾値(25)を超えたピクセルを白、それ以外を黒に変換し、動いた領域だけを抽出します。
- 膨張処理(dilate): 白い領域を膨張させることで小さなノイズを消し、検出領域をつなげて認識精度を高めます。
- 輪郭検出:
findContoursで動体の輪郭を検出し、面積が10000以上ある輪郭に対してのみ緑色の矩形を描画します。これにより、微小な変化を無視できます。 - 時間の記録: 動きが始まった瞬間と終わった瞬間に
datetime.now()で時刻を記録し、最後にまとめてCSVに出力します。
実行結果
プログラムを実行すると、3つのウィンドウが表示されます。それぞれグレースケール、カラー(検出枠付き)、白黒(二値化)の3つのモードで、Webカメラの映像と動きの検出状況をリアルタイムに確認できます。
同時に、動きが検出された日時がCSVファイルにも記録されます。出力されるCSVファイルの中身は以下のようになります。
FrameInMotion_time.csv(出力例)
Start End 0 2019-02-21 18:08:35.791487 2019-02-21 18:10:59.718005
このように、動きが検出された開始時刻と終了時刻が1行ずつ記録されていきます。応用としては、閾値や最小面積の調整、特定時間帯のみ記録する機能の追加などを行うことで、簡易的な防犯カメラシステムとして拡張することも可能です。
-
OpenCV×Pythonで画像をぼかす方法|ガウシアンフィルタの基本と実装例
OpenCVは、画像処理に最も優れたPythonパッケージの一つです。信号にノイズが混入するのと同じように、画像にもさまざまな種類のノイズが含まれており、その主な発生源はカメラセンサーなど画像取得元そのものです。PythonのOpenCVパッケージには、画像を滑らかにする「スムージング(平滑化)」、いわゆる「ぼかし(ブラー)」処理を行うための機能が用意されています。 本記事では、その中でも特に一般的な手法であるガウシアンフィルタ(Gaussian Filter)を使った画像のぼかし方を解説します。ガウシアンフィルタを使用すると、画像内のシャープなエッジ(輪郭)を滑らかにしながら、過度なぼかしを
-
OpenCVを使って画像・動画のエッジを検出するPythonプログラムの書き方
この記事では、Pythonを使って画像や動画ファイルからエッジ(輪郭)を検出する方法を解説します。エッジ検出には、コンピュータビジョン向けに設計されたオープンソースライブラリ「OpenCV」を使用します。OpenCVはもともとIntelによって開発されたライブラリで、BSDライセンスのもとで無料で利用できます。OpenCVの機能を使うには、pipでインストールを行います。インストール時にNumPyモジュールも自動的にダウンロードされるため、別途用意する必要はありません。sudo pip3 install opencv-python今回の入力には動画ファイルを使用しますが、Webカメラを接続すれ