今回の目的

プロジェクトKという名称で、ラズパイを使ってある事をしようと思います。
具体的な説明と、実装作業をしていきたいと思います。


プロジェクトKという具体的な説明

何をするのかというと、
現在、一戸建てに住んでいるのですが、
一戸建てだと、玄関の鍵を閉め忘れが、かなりのセキュリティリスクとなります。

マンションだとエントランスのオートロックがあるので、まだギリギリ大丈夫ですよね。。
子供がいるとなると、彼の行動に目が行ってしまい、意外と鍵の閉め忘れとかがあるのです。

ということで、
ラズパイを使って、その玄関の鍵の締め忘れをチェックしたいと思います!

ちなみにプロジェクトKのKは=鍵のことです。


ラズパイ設置

まず、ラズパイを玄関に設置します。
今の家では、鍵の前に下駄箱があり、そこに貼り付けました。
仮設置なので、ラズパイについてはガムテで汚くハリボテ感満載で貼り付け。



家に入りにくいと感じたことはないのですが、なぜこの位置に下駄箱を配置したのかは意味が分かりません。
ただ、ここに下駄箱があったことで、今回のプロジェクトを思いつきませんでした。


鍵について

このプロジェクトの真髄となる鍵について説明します。
鍵の形状は以下です。



以下が開いている状態で、基準画像はこちらの開いているものとしました。


以下が閉まっている状態



つまり、鍵の締め忘れチェック
とは、閉まっている状態を基準として

画像の類似度が近い=似ているならば開いているので危険
類似度が遠く=似ていないならば閉まっているのでOK
というのをチェックすることです。

画像の類似度について以下の記事を参照してください。
[ラズパイ]画像類似度チェック
次の項目のプログラムも上の記事を参照しています。


プログラム

それでは、実行するpythonファイルについてです。
以下の流れでプログラムを実行します。

  1. 比較用イメージをあらかじめラズパイカメラで撮影しておく
  2. あるタイミングで、ラズパイカメラで鍵を撮影する
  3. 比較用画像と撮影画像を比較する
  4. 比較値より条件に当てはまる場合、数秒後にもう一度ラズパイカメラで鍵を撮影する
  5. もう一度やっても条件に当てはまる場合、LINEで自分のアカウントに警告メッセージを送信する
  6. 上記2~5までを一定期間で実行するようにする

としました。
条件に当てはまるというのは鍵が開いていることとなります。
4、5で同じことを繰り返してますが、本当に開いていることの信頼度強化のためです。

上記の2〜5までの処理を行うpythonファイルが以下となります。
match.pyとしました。

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import cv2
import picamera
import requests
import time

# 比較元イメージを読み込む
okImage = cv2.imread("/home/pi/work/okImage.JPG",1)

def diff():
    # カメラでの撮影
    with picamera.PiCamera() as camera:
        # カメラでの撮影
        camera.resolution = (3280, 2464)
        camera.capture('/home/pi/work/taImage.JPG')
        taImage = cv2.imread("/home/pi/work/taImage.JPG",1)
        taImage = taImage[830:1110, 1070:1380]

        # 比較する
        try:
            orb = cv2.ORB_create()
            kpOk, desOk = orb.detectAndCompute(okImage, None)
            kpTa, desTa = orb.detectAndCompute(taImage, None)
            bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
            matches = bf.match(desOk, desTa)
            matches = sorted(matches, key = lambda x:x.distance)
            dist = [m.distance for m in matches]
            
            # 比較結果を出力する
            result = sum(dist) / len(dist)
            return result
        except Exception:
            return 99

result = diff()
if result < 54:
    time.sleep(10)
    resultSecond = diff()
    if resultSecond < 54:
        line_notify_token = '設定したLINEトークン'
        line_notify_api = 'https://notify-api.line.me/api/notify'
        message = '鍵開いてるよ'

        payload = {'message': message}
        headers = {'Authorization': 'Bearer ' + line_notify_token}
        line_notify = requests.post(line_notify_api, data=payload, headers=headers)

上記の補足をしていきます。

上でも書きましたが、先にラズパイで撮影していた比較元イメージを読み込みます。

プログラムを使って前もって画像の類似度チェックをしたのですが、
開いている時と閉じている時の値は54を境に区別できるようでした。

開いている時 は基準画像に似ているということで、54より小さい値に。
閉じている時54より大きい値に。


1回目のチェックして、鍵が開いている状態であれば、その10秒後に2回目のチェックを行います。
2回目も鍵が開いている状態と判定されれば、LINEで自分のアカウントに通知するようにしました。
プログラムに関しては以上です。


一定のタイミングでプログラムを実行する処理

上記のpythonファイルを一定のタイミングで実行する処理を実装します。(6の処理です。)
実装にはcronライブラリを使用します。

ラズパイより以下コマンドを実行します。
Chooseについては、デフォルトは2となってますが、3を入力します。

$ crontab -e
no crontab for pi - using an empty one

Select an editor.  To change later, run 'select-editor'.
  1. /bin/ed
  2. /bin/nano        <---- easiest
  3. /usr/bin/vim.tiny

Choose 1-3 [2]: 

-> 3


今回は1分毎にmatching.pyファイルを実行するようにしたく、
ファイルの最後に1行以下のように追加します。

# Edit this file to introduce tasks to be run by cron.
....
# m h  dom mon dow   command
* * * * * python /home/pi/work/matching.py

cron設定をした後から、すでに実行されています。


以上で準備は完了です。

次回は実行編として上記の検証をしていきます。