# -*- coding: utf-8 -*-
import time
import datetime
import cv2 as cv

# WEBカメラを使って監視カメラを実現するプログラム
# 動体検知、そのときの日付時刻を埋め込んだjpgファイルを保存する


#画像を保存するディレクトリ
save_dir  = '/home/pi/Desktop/image_recognition/'

#ファイル名は日付時刻を含む文字列とする
#日付時刻のあとに付加するファイル名を指定する
fn_suffix = 'motion_detect.jpg'

# VideoCaptureのインスタンスを作成する。
cap = cv.VideoCapture(0) 

#縦と横の解像度指定
cap.set(cv.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv.CAP_PROP_FRAME_HEIGHT, 480)

#2値化したときのピクセルの値
DELTA_MAX = 255

#各ドットの変化を検知するしきい値
DOT_TH = 20

#モーションファクター(どれくらいの点に変化があったか)が
#どの程度以上なら記録するか。
MOTHON_FACTOR_TH = 0.20

#比較用のデータを格納
avg = None

while True:

    ret, frame = cap.read()     # 1フレーム読み込む
    motion_detected = False     # 動きが検出されたかどうかを示すフラグ

    dt_now = datetime.datetime.now() #データを取得した時刻

    #ファイル名と、画像中に埋め込む日付時刻
    dt_format_string = dt_now.strftime('%Y-%m-%d %H:%M:%S') 
    f_name = dt_now.strftime('%Y%m%d%H%M%S%f') + "_" + fn_suffix


    # モノクロにする
    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)

    #比較用のフレームを取得する
    if avg is None:
        avg = gray.copy().astype("float")
        continue


    # 現在のフレームと移動平均との差を計算
    cv.accumulateWeighted(gray, avg, 0.6)
    frameDelta = cv.absdiff(gray, cv.convertScaleAbs(avg))

    # デルタ画像を閾値処理を行う
    thresh = cv.threshold(frameDelta, DOT_TH, DELTA_MAX, cv.THRESH_BINARY)[1]

    #モーションファクターを計算する。全体としてどれくらいの割合が変化したか。
    motion_factor = thresh.sum() * 1.0 / thresh.size / DELTA_MAX 
    motion_factor_str = '{:.08f}'.format(motion_factor)

    #画像に日付時刻を書き込み
    cv.putText(frame,dt_format_string,(25,50),cv.FONT_HERSHEY_SIMPLEX, 1.5,(0,0,255), 2)
   #画像にmotion_factor値を書き込む
    cv.putText(frame,motion_factor_str,(25,470),cv.FONT_HERSHEY_SIMPLEX, 1.5,(0,0,255), 2)

    #モーションファクターがしきい値を超えていれば動きを検知したことにする
    if motion_factor > MOTHON_FACTOR_TH:
        motion_detected = True

    # 動き検出していれば画像を保存する
    if motion_detected  == True:
        #save
        cv.imwrite(save_dir + f_name, frame)
        print("DETECTED:" + f_name)


    # ここからは画面表示する画像の処理
    # 画像の閾値に輪郭線を入れる
    contours, hierarchy = cv.findContours(thresh.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    frame = cv.drawContours(frame, contours, -1, (0, 255, 0), 3)


    # 結果の画像を表示する
    cv.imshow('camera', frame)


    # 何かキーが押されるまで待機する
    k = cv.waitKey(1000)  #引数は待ち時間(ms)
    if k == 27: #Esc入力時は終了
        break


print("Bye!\n")
# 表示したウィンドウを閉じる
cap.release()
cv.destroyAllWindows()

 

参考

https://qiita.com/hasekou_tech/items/acd0d9159a9001ebfbd3