施錠状態を監視するスマートシステム
2025年2月上旬~2025年3月末開発形態:個人開発
背景・目的
外出時に家の鍵を施錠したかどうかを忘れ、不安から家まで戻る手間を省くために、このシステムを開発する。画像認識技術を活用した施錠状態の監視システムを構築することで、日常生活の利便性を向上させるとともに、関連技術の学習と実践を目的としている。
システム概要
特定の時間帯にカメラを用いて鍵の施錠状態を監視する。画像認識にはOpenCVを活用し、施錠状態を判断する。
この情報をデータベースにアップロードし、スマホアプリから「施錠中」「解除中」をリアルタイムで確認できるシステムを構築する。
使用技術
- ハードウェア:Raspberry Pi + カメラモジュール
- 画像認識:OpenCV + ArUcoマーカーによる鍵状態の識別
- データベース/サーバー:AWS EC2 (Apache/Tomcat), RDS(MySQL)
- ネットワーク通信:SSH, WinSCP, IP固定化, ドメイン移管
- アプリ開発:Java + Eclipse によるWebアプリ構築
- データ同期:Raspberry Pi → AWSへの状態送信(時刻指定制御)
開発
ラズパイのカメラからpython言語を使った撮影OpenCVを使った画像認識プログラムの開発
OpenCVを使ってカメラモジュール(以下「カメラ」とする)から受け取った画像からArUcoマーカー(以下「マーカー」とする)を検出した場合は「Lock」、検出できなかった場合は「UnLock」と表記することにした。
import cv2
from picamera2 import Picamera2
from time import sleep
import numpy as np
from PIL import Image
from libcamera import controls
import cv2.aruco as aruco
cv2.startWindowThread()
picam2 = Picamera2()
picam2.start()
# マーカー検出用の関数
def detectArucoFromImage():
# 画像を読み込む
image = picam2.capture_array()
# ArUco辞書を指定
dictionary = aruco.Dictionary_get(aruco.DICT_6X6_250)
parameters = aruco.DetectorParameters_create()
# グレースケール変換
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# ArUcoマーカーの検出
corners, ids, rejectedImgPoints = aruco.detectMarkers(gray, dictionary, parameters=parameters)
# マーカーを検出した場合
if ids is not None:
print("Lock")
else:
print("UnLock")
#カメラ映像を表示
cv2.imshow("Result",image)
while True:
detectArucoFromImage()
key = cv2.waitKey(1)
if key == 27:
break
picam2.stop()
cv2.destroyAllWindows()
print("成功")
運用
本番環境時の写真
マーカーサイズを2.0cmにし、最大認識距離が70cm以内、電源位置などを考慮し本番環境に設置した。
なお、写真では鍵の上下にマーカーを設置しているが、認識するマーカーは上段の方である。
ラズパイに電源を入れたのち、別コンピュータでSSH接続をしプログラムを常時バックグラウンド実行した。
また、結果を詳細に確認するため以下の二点をプログラムに追記した。
- ①...6時45分から7時00分まで及び16時40分から17時10分まで1分ごとに写真を撮影しローカル上に記録する。
- ②...7時00分から16時40分までの間で解除判定になった場合、写真を撮影しローカル上に記録する。
そのため最終的なプログラムは次の通りになる。
import cv2
from picamera2 import Picamera2
from time import sleep
import numpy as np
from PIL import Image
from libcamera import controls
import cv2.aruco as aruco
import pymysql
import traceback
import datetime
import subprocess
cv2.startWindowThread()
picam2 = Picamera2()
picam2.set_controls({"ExposureTime":5000,"AnalogueGain":1.0})
picam2.start()
marker_now = None
# マーカー検出用の関数
def detectArucoFromImage():
global marker_now
# 画像を読み込む
now = datetime.datetime.now().strftime("%H:%M:%S")
file_path = f"/home/pi/picture/picture_{now}.jpg"
image = picam2.capture_array()
mor = "07:00:00" #1の終わり / 2の開始 7:00
aft = "16:40:00" #1の開始 16:40
ma = "06:45:00" # 1の開始 6:45
at = "17:10:00" #1の終わり / 2の終わり 17:10
# 時間の比較
if now > ma:
if now < mor:
cv2.imwrite(file_path, image)
if now > aft:
if now < at:
cv2.imwrite(file_path, image)
# ArUco辞書を指定
dictionary = aruco.Dictionary_get(aruco.DICT_6X6_250)
parameters = aruco.DetectorParameters_create()
parameters.adaptiveThreshWinSizeMin= 5
parameters.adaptiveThreshWinSizeMax= 100
parameters.adaptiveThreshWinSizeStep= 5
parameters.minMarkerPerimeterRate = 0.005
# グレースケール変換
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.resize(gray,(960,540))
# ArUcoマーカーの検出
corners, ids, rejectedImgPoints = aruco.detectMarkers(gray, dictionary, parameters=parameters)
# マーカーを検出した場合
if ids is not None:
print("Lock")
a=0
else:
print("UnLock")
a=1
# 結果を表示
try:
connection = pymysql.connect(
host = "",
user = "",
password = "",
database = "LSMSystem",
port = 3306
)
#print("Excellent!")
with connection.cursor() as cursor:
if a!=marker_now:
print("変更有")
if a==0:
marker_now = a
sql = "UPDATE LSMS SET ima = 0 , today = %s WHERE id = 0"
cursor.execute(sql,(now))
else:
marker_now = a
sql = "UPDATE LSMS SET ima = 1 , today = %s WHERE id = 0"
cursor.execute(sql,(now))
connection.commit()
connection.close()
except Exception as e:
print("DBerr:",e)
traceback.print_exc()
while True:
detectArucoFromImage()
key = cv2.waitKey(1)
if key == 27:
break
picam2.stop()
cv2.destroyAllWindows()
結果と考察
グラフ1:2025/02/13 00:00:06 - 23:59:59までの施錠状況
グラフ1では、1日を通じた施錠状態の変化を可視化している。値が1の場合は「解除中」、0の場合は「施錠中」を示す。
グラフ2:2025/02/13 06:45:05 - 07:00:56までの施錠状況
朝6:55〜7:00の時間帯に絞って分析。
- 6:47:41までは太陽光不足のためマーカーを認識できていなかった。
- 6:51:37に一時的に「解除中」となったが、定期撮影の対象外で画像は取得されていない。
- 6:55:35に定期撮影が開始(グラフ2の画像3)。
- 6:56:35に「解除中」判定となり撮影された画像1では、暗くマーカーが視認困難だった。
- 6:58:31に撮影された画像2ではドアが実際に開いており、正確な判定と確認できる。
グラフ3:2025/02/13 07:00:07 - 16:39:49までの施錠状況
朝7時〜16時40分までの記録:
- 8:35:13に「解除中」判定、グラフ3の画像5では施錠状態であり誤認識の可能性あり。
- 8:43:36に再度「解除中」、グラフ3の画像6ではドアが開いており正常に動作。
- 10:09:40、11:53:12も同様にドア開閉を正確に検出(グラフ3の画像7・8)。
- 11:57:22に数分間「解除中」となったが、グラフ3の画像9では施錠されており、原因は不明。
グラフ4:2025/02/13 16:40:00 - 17:10:56までの施錠状況
本来は16:40〜17:10に定期撮影を行う予定だったが、プログラムの時間指定ミスにより16:45までしか撮影されていなかった。
「解除中」判定が出た原因は、日没に近づき光量が不足し、マーカー認識精度が低下したことと推測される。
課題と考えられる解決策
夜間の施錠状態が認識できていない。
解決策:赤外線カメラまたはライトを設置し、夜間の認識制度を向上できると考えられる。
誤認識
解決策:AIを用いた画像認識や、ライトをつけるなどして光量が一定以上にすることで解決できると考えられる。
終わりに
本システムを数か月間運用した結果、施錠を忘れたか不安になった際にも、外出先から施錠状態を確認でき、実用的な成果が得られた。 また、PythonやJavaによる開発、AWS上でのサーバ構築、画像認識処理の実装など、広範な技術を実践的に学ぶことができた。 これにより、当初の目的であった「日常生活の利便性の向上」および「関連技術の習得」を達成することができた。