帰宅を家族に自動的に知らせる為にカメラで動体検知したらLINEで通知するシステムを費用を抑える為にラズパイzeroWとwebカメラ(C270)だけで作ってみました。
使用するもの
2019.11.24時点で以下の価格のものを使いました。
(3),(4)の電源は2A以上のものを選んでいますが、Pi Zero限定ならそこまで電流は必要ないとは思います。
(1) Raspberry Pi Zero W 1320円
(2) webカメラ C270 1842円
(3) USB充電器 1399円
(4) Micro USBケーブル 764円
(5) Micro USB - USB変換 478円
今回は別のPiで使用しており使えませんでしたが、
・カメラモジュール 780円
を使用すれば(2),(5)が不要となりより安く済みます。
見た目
かなりのバラックですが・・・
ソースコード
import datetime import numpy as np import subprocess import os import cv2 import time import requests token = 'abcdefghijklmnopqrstuvwxyz123456789----------' motion_th = 1000 #動体検知の閾値 while True: #時刻取得 time = datetime.datetime.now() strtime = time.strftime('%Y%m%d_%H:%M:%S') FileName = strtime + ".jpg" #image1 capture print("e1開始 %s" %(strtime)) cmd1 = 'fswebcam -r 640x480 --no-banner e1.jpg' ps1 = subprocess.run(cmd1.split(),stdout=subprocess.PIPE) #image2 capture print("e2開始") cmd2 = 'fswebcam -r 640x480 --no-banner e2.jpg' ps2 = subprocess.run(cmd2.split(),stdout=subprocess.PIPE) #動体検知 img1 = cv2.imread("e1.jpg") img2 = cv2.imread("e2.jpg") #背景差分の設定 fgbg = cv2.bgsegm.createBackgroundSubtractorMOG() # 背景オブジェクトを作成 fgmask = fgbg.apply(img1) fgmask = fgbg.apply(img2) motion = cv2.countNonZero(fgmask) print("動体検知:%d"%(motion)) if (motion > motion_th): cv2.imwrite(FileName,img2) print("----Captured!----") payload = {'message': '動体検知しました'} # 送信メッセージ url = 'https://notify-api.line.me/api/notify' headers = {'Authorization': 'Bearer ' + token} files={"imageFile":open(FileName,"rb")} res = requests.post(url, data=payload, headers=headers,files=files,) # LINE NotifyへPOST print(res) #検出画像 cv2.imwrite('./diff.jpg',fgmask) time.sleep(60) else: pass # 表示 #cv2.imshow('frame',fgmask) cv2.waitKey(0) cv2.destroyAllWindows()
内容説明
2枚の静止画を比較した動体検知を行い、指定した閾値以上の時にLINEでメッセージと静止画を送信します。
当初はOpenCVによる動画からの動体検知を試みましたが、処理に時間がかかり過ぎたので静止画のみを使う事にしました。
(参考:動画を用いた動体検知)
RaspberryPi+Python+OpenCVで動体検知の値を画像に表示する
コードの説明
9行目:
下記の記事を参考に事前準備としてLINE Notifyから送り先のトークンを取得し、9行目のtokenに代入します。
【LINE Notify】 PythonでLINEの メッセージと画像を送信する方法
10行目:動体検知の閾値を置きます。今回は1000にしました。
18〜26行目:比較用の画像を取得。画像取得にはfswebcamコマンドを使用。
36行目:背景差分を検出する為のOpenCVの関数を使用。
fgmaskに背景差分の結果が入ります。
1枚目の画像:e1.jpg
2枚目の画像:e2.jpg
背景差分画像:diff.jpg
38行目:diff.jpgの白くなっている画素のカウント数を動体検知の値(motion)としています。
41行目:動体検知の値(motion)が閾値(motion_th)以上だった時にLINE通知します。
42行目:時間をファイル名とした画像を保存します。
上記のe2.jpgをLINE通知します。
45〜51行目:9行目で指定したトークン宛てに送信するメッセージと画像を設定しています。
LINE通知が成功すると<Response[200]>とシェルに表示されます。
結果
LINEにも通知が届きました。
56行目にtime.sleep(60)を入れて1回通知したら60秒間は通知しないようにしています。
まとめ
webカメラの静止画2枚の差分をOpenCVで検出し、LINE通知するシステムを
作成しました。
なるべく費用を安くする為Pi zero Wを使用したためごく簡単な動体検知としました。
今回の目的は玄関の帰宅を家族に知らせる為に玄関に設置しましたが、自宅周辺の監視カメラやペットの見守り等にも応用できそうです。