神社 地域 にデジタルを
簡易で安価なカメラで防犯・外出対策を
在宅中でも外出先であっても、社務所の前の様子が確認ができる。そして、来訪者があった場合には、Lineに通知して素早く情報をキャッチできるようにしてみました。
USB接続のWebカメラを使った、お手軽で安価な方法になります。何かの参考になれば幸いです。
当方は神職一人であるため、基本、日中留守はできない原則です。
いつ来訪があるかもわからないため、休日の概念もありません。
ただ、四六時中激務が続くというわけではなく、待機中・空き時間・・・のような状態の場合も少なくはありません。
とはいえ、実際には出張祭典他、留守にせざるを得ない場合も多々あります。そこで、来訪者があったかどうか確認し、然るべき手が取れるようにしたいと考えました。
また、日常の防犯といった上でも有効だと考えています。
概要になりますが、以下に記します。
まずカメラを接続
暗視カメラ機能があり、屋外対応となっていたので、これにしました。
しかしはっきりいって、このカメラで屋外での暗視は全く機能しません。夜間は真っ暗です。ですので、もっと安いWEBカメラで十分だと思います。
Flaskで動かす
今回は、Webアプリの構築が簡易にできるFlaskを用いました。
動体検知のプログラムを記述し、来訪の動きをキャッチできるように工夫します。
<app.py>
import cv2
import time
from flask import Flask, render_template, Response
import datetime
import requests
token = 'Vxxxxx3JBxxxxxxpaytSxxxxxxxxxxaxxxqwz7bxx' # lineのアクセストークン
# Webcam 監視
video = cv2.VideoCapture(0)
def get_frame():
red = (0, 0, 255) # 枠線の色
before = None # 前回の画像を保存する変数
fps = int(video.get(cv2.CAP_PROP_FPS)) #動画のFPSを取得
# 監視範囲
xmin, xmax = 340,630
ymin, ymax = 220,460
# 背景差分の設定
fgbg = cv2.bgsegm.createBackgroundSubtractorMOG() # 背景オブジェクト
while True:
success, frame = video.read()
detframe = frame[ymin:ymax,xmin:xmax] # 背景差分する範囲を指定
cv2.rectangle(frame,(xmin,ymin),(xmax,ymax),(255,255,255),1)
fgmask = fgbg.apply(detframe) # 前景領域のマスクを取得
moment = cv2.countNonZero(fgmask) # 動体検知した画素数を取得
text = 'Motion:' + str(moment)
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(frame,text,(20,440),font,1,(0,255,0),2,cv2.LINE_AA) #フレームに表示
# 全体の動体検知
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
if before is None:
before = gray.astype("float")
continue
#現在のフレームと移動平均との差を計算
cv2.accumulateWeighted(gray, before, 0.5)
frameDelta = cv2.absdiff(gray, cv2.convertScaleAbs(before))
#frameDeltaの画像を2値化
thresh = cv2.threshold(frameDelta, 3, 255, cv2.THRESH_BINARY)[1]
#輪郭のデータを得る
contours = cv2.findContours(thresh,
cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)[0]
# 差分があった点を画面に描く
for i, target in enumerate(contours):
x, y, w, h = cv2.boundingRect(target)
# print("width:",x+w, "height:", y+h)
if w < 30: continue # 小さな変更点は無視
cv2.rectangle(frame, (x, y), (x+w, y+h), red, 2)
# 画像保存とLine通知の条件
if moment > 5000 and moment < 15500:
if (x+w) >450 and (y+h) > 400:
print("動体検知しました。:", moment, "width:", (x+w), "height:", (y+h))
time_now = datetime.datetime.now()
strtime = time_now.strftime('%Y%m%d_%H_%M_%S')
print(strtime + '_' + str(i))
# cv2.imwrite(f"./images/{FileName}", frame)
cv2.imwrite(
f'C:/Users/xxxo/Documents/ot_xxxn/APP_Flask/images/diff{strtime}_{str(i)}.jpg',frame)
# Line
payload = {'message': '動体検知しました'} # 送信メッセージ
url = 'https://notify-api.line.me/api/notify'
headers = {'Authorization': 'Bearer ' + token}
files={'imageFile':open(
f"C:/Users/xxxo/Documents/ot_xxxn/APP_Flask/images/diff{strtime}_{str(i)}.jpg","rb")}
res = requests.post(url, data=payload, headers=headers,files=files,) # LINE NotifyへPOST
#ウィンドウでの再生速度を元動画と合わせる
time.sleep(1/fps)
# ウィンドウで表示
# cv2.imshow('target_frame', frame)
sc, encoded_image = cv2.imencode(".jpg", frame)
frame = encoded_image.tobytes()
yield (b'--frame\r\nContent-Type: image/jpeg\r\n\r\n' + \
frame + b'\r\n')
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/video_feed_url')
def video_feed():
return Response(get_frame(), mimetype="multipart/x-mixed-replace; boundary=frame")
# if __name__ == '__main__':
# app.run(debug=True)
# 別のコンピュータでアクセスできるようにする
if __name__ == '__main__':
app.run(debug=False, host="0.0.0.0", port=x3x1x)
実行すると、こんなふうに動きます。
俊敏に動作をキャッチしますが、調整を施さないと、人物がいない状態での検知が多量になります。
そこで、白枠内の領域内限定で一定以上の大きなモージョンがあって、かつ、赤枠で捉える変化の幅と高さを一定レベル以上のものに限定しました。このダブルチェックで得た検知のみを、ローカルに保管・Lineに通知するように工夫してみました。
ただしこれでも、天気の移り変わり(曇から晴れ)や日の出・日の入りなど、画面変化が激しい場合、人がいなくとも検知がかなり生じます。
このあたりは、機械学習を採用するとより正確になるかと思います。
参考にさせていただきました。
参照:https://qiita.com/seri28/items/3ae4a2c87e352e976b46
参照:https://non-it-engineer.com/pythonopencv%E3%81%A7%E6%8C%87%E5%AE%9A%E7%AF%84%E5%9B%B2%E3%81%AE%E3%81%BF%E3%81%AB%E7%94%BB%E5%83%8F%E5%87%A6%E7%90%86%E3%82%92%E8%A1%8C%E3%81%86%E6%96%B9%E6%B3%95/
他のデバイスからも確認できるようにする
host="0.0.0.0"(112行目)とすることで、外部の接続が可能になるので、同じLANにあれば、どのデバイス(スマートフォンなど)からも接続して確認が可能になります。
(アドレスは、ipconfigコマンドでIPV4を探して設定します。192.xxx.xxx...)
検出した画像を保存
以下のような画像がフォルダに保存されます
画像は私です外出先から確認
遠方のどこにいても、社務所の前を確認できるようにします。
ngrokというツールを活用します。
ngrokはローカルホスト接続を外部から見れるようにしてくれるもので、大変ありがたいものです。
ngrokのサイトでトークンを作成し、最初に以下コマンドを入力
ngrok config add-authtoken ここにコピーしたトークンを貼り付け
ポート設定のコマンドを入力します
ngrok http 設定したポート番号
外出先から確認できるURLが生成されています
Lineに通知
Lineのアクセストークンを取得しておきます。
(検索すると詳しい説明のあるサイトが多数ありますので割愛します)
<
画像とともに通知が送られてきます
日常的に使うために
画像を消去する
日々の画像がどんどんたまっていくので、Pythonコードを用意して、一括で削除できるようにしておきます。
(Lineは程よいあたりで、自分で手動でデータを削除します)
img_delete.py
from pathlib import Path
target_folder = Path("C:/Users/xxxo/Documents/oxxxon/APP_Flask/images")
for path in target_folder.glob("*.jpg"):
with open(path, "wb") as f:
f.write(b"")
path.unlink()
Windows環境であれば
バッチファイルで一連の動作ができるようにしておくと便利です。
毎朝、ダブルクリックで起動するなどと決めておくと良いかもしれません。
motion_monitor.bat
"C:/Users/oxxxo/AppData/Local/pypoetry/Cache/virtualenvs/app-flask-zgkzrAnn-py3.9/Scripts/python.exe" c:/Users/oxxxo/Documents/oxxxxxhon/APP_Flask/img_delete.py
"C:/Users/oxxxo/AppData/Local/pypoetry/Cache/virtualenvs/app-flask-zgkzrAnn-py3.9/Scripts/python.exe" c:/Users/oxxxo/Documents/oxxxxhon/APP_Flask/app.py
あくまで簡易なものですが、拡張していくと賽銭泥をキャッチするのに有用な転用ができるかと思います。
投稿内容 ランダム表示
豊中市MAPの基データの説明
最終更新:2023年07月14日
❝グラフで見る豊中市データ❞の使い方
最終更新:2023年07月14日
❝ユーチューブのダウンロード❞のコーディング
最終更新:2023年08月18日
❝画像のトリミング❞のコーディング
最終更新:2023年07月14日
python3.10 Django4 wsl bootstrap javascript
カテゴリ
私の願い
私は神社の宮司です。神社や地域を担う次世代の人々に対し、何かを残してお役に立ててもらいたいとの願いが、強く芽生えました。個業としての神社や、小規模な地域社会に、恩恵が届くのが遅くなりそうな「デジタル」の分野。門外漢として奮闘した実体験から得た経験則を、わずかずつでも残し未来につなぎたいと願うばかりです。
最近の投稿
- 簡易で安価なカメラで防犯・外出対策を
最終更新:2023年09月08日
- 神社のオリジナルTシャツを作ってみた
最終更新:2023年08月07日
- HTMLメールを活用してみた
最終更新:2023年07月14日
- 豊中市Graphの基データの説明
最終更新:2023年07月14日