Raspberry Piで最強の防犯カメラを作ってみる(動画記録・配信、動体検知・Line通知、顔検知・顔認証、Alexa搭載)[4/6]

スマートホーム
スポンサーリンク
このエントリーをはてなブックマークに追加

やりたいこと(再掲)

最終的にやりたいことは、以下の5つの機能を持つ「最強の防犯カメラ」を作ることです。機能①〜機能③は、市販されている多くの防犯カメラでも持っている機能ですが、機能④や機能⑤の顔認証機能を持つ監視カメラはまだ多くないと思います。

 機能①.動画を24時間撮影し、カメラ本体に動画で記録する
 機能②.動画をWebブラウザや他の機器から参照できるようにライブ配信する
 機能③.動体を検知したら、静止画をLineに通知する
 機能④.家族の顔を認証したら、静止画をLineに通知する
 機能⑤.家族の顔を認証したら、◯◯さんおかえり!と喋る

家に帰ると、顔を見て「○○さん、おかえり!」と言ってくれる辺りが、スマートハウスに一歩づ近づいている気がします。

実現に向けた連載

最強の「防犯カメラ」を作成するために、以下のように少しずつに記事を書いていきます。
 1回目:カメラの設定と動画記録
 2回目:カメラ映像のライブ配信
 3回目:動体検知機能とLineへの通知
 4回目:顔認証機能とLineへの通知 ←この記事
 5回目:Raspberry PiへのAlexaの搭載
 6回目:顔認証後にAlexaで音声通知

4回目:顔認証機能とLineへの通知

前回は動体検知機能を作って、カメラが動体を検知した時にLineに通知するようにしてみました。今回は、いよいよ顔検知・顔認証機能を作っていきます。

今回はReal-Time Face Recognition: An End-to-End Projectで紹介されている方法で、顔検知・顔認証機能を作っていきます。

認証用の顔データの学習

顔認証を行うためには、認証する顔データを予め学習させておく必要があります。まずは、顔データの撮影と学習を行っていきます。

①防犯カメラサービスの停止

まずは、防犯カメラサービスを止めておきます。

②顔データ撮影用のプログラムのダウンロード

顔データ撮影用のプログラムは自分で作っても良いですが、Real-Time Face Recognition: An End-to-End Projectで利用しているものがGitHubにあるので、これを利用します。以下のコマンドを入力して「01_face_dataset.py」をダウンロードします。

このプログラムでは、カメラで画像を撮影し、その画像の中にある人の顔を認識して30枚の顔画像ファイルを出力するものです。

③顔検知用の正面顔特徴分類器のダウンロード

次に「01_face_dataset.py」で顔検知するために必要な、正面顔用の特徴分類器「haarcascade_frontalface_default.xml」をOpenCVのGitHubからダウンロードします。

④画像の格納ディレクトリの作成

画像を保存するディレクトリ「dataset」を作成しておきます。

⑤登録用画像の撮影

それでは「01_face_dataset.py」を実行して、顔を撮影します。このプログラムは、画面に撮影の様子を表示するので、VNCでログインしたコンソールから実行します。また、カメラにアクセスするのでroot権限での実行が必要です。

プログラムを実行すると、以下のようにユーザIDを聞かれます。ユーザIDは、登録する人ごとに1からの連番を振るものです。一人目の登録であれば「1」を入力してエンターを押します。すると、画面にカメラの映像が表示されるので、カメラの前に立って顔を撮影します。顔を認識すると、青色の枠で表示されるので、様々な表情や近さで撮影してみてください。1〜2分ほどカメラを見ていると30枚分の顔画像が撮影され、プログラムが終了します。

なお、複数の人の画像を登録する場合は、もう一度プログラムを起動して、ユーザIDに2などを入力して同様に撮影して下さい。

⑥学習用のプログラムのダウンロード

次に、撮影した顔データを学習させるためのプログラム「02_face_training.py」をダウンロードします。

⑦02_face_training.pyの変更

オリジナルの「02_face_training.py」は、OpenCV「3.3.0」以上で動作するので、RaspberryPiにインストールされる「3.2.0」で実行するためには、以下の2点の修正を行う必要があります。

変更点1:21行目あたり「LBPHFaceRecognizer_create()」を以下のように変更。

変更点2:51行目あたり「recognizer.write()」を以下のように変更。

⑧学習済みデータ格納ディレクトリの作成

学習済みデータを格納する「trainer」ディレクトリを作成します。

⑨学習用のプログラムの実行

それでは「02_face_training.py」を実行して、撮影した顔データを学習させます。「trainer」フォルダに「trainer.yml」が作成されていればOKです。

以上で、認証用の顔データの学習は完了です。

Line通知機能の修正

ここからは、顔が認証された場合にLineへ通知する機能を作成していきます。

①functionノードの修正

Node-redの一つ目のfunctionノードに顔認証用の分岐条件を追加します。プログラムの内容は、ほぼ動体検知の場合と同じです。

②ノードのデプロイ

画面右上の「デプロイ」ボタンを押して、作成したフローをデプロイします。

顔検知・顔認証プログラムの作成

ここからは、Camera.pyに顔認証機能を追加していきます。なお、完全なソースコードはGitHubのnaka-kazz/RasPiCameraに置いたので、適宜参照してください。

①定数定義の追加

まずは、Camera.pyの定数定義の一番下に、定数定義を追加します。

namesは、ライブ配信映像やログに顔を検知した時に名前を表示させるものです。配列要素の1番目から、顔の撮影時に登録したユーザIDの順に名前を入力して下さい。

faceCascadeは、カメラ画像の中から顔を検知するためのものです。また、recognizerは顔認証のためのエンジンであり、上で学習させた顔データをロードしています。

②faceDetect関数の追加

今回のメインである、顔認証の機能であるfaceDetect関数を、moveDetect関数の下に追加します。

プログラムの特徴的な部分だけ説明していきます。まず、顔認証に色情報は不要なので、処理を軽くするために、カメラの画像をグレースケール画像に変換しています。

次に「faceCascade.detectMultiScale()」で、カメラで撮影した画像の中の人の顔を認識します。そして、次のforループの中で、認識されたそれぞれの顔について「recognizer.predict()」で顔認証を行っています。OpenCVを使うと、この一行だけで顔認証が行えます。

「recognizer.predict()」の戻り値は、顔を登録した時のユーザIDの番号と信頼度の2つです。信頼度が0以上で100以下だったら、顔認証OKとして判断し、ログ出力やサーバ通知を行っています。

また「#配信画像に枠と名前を付ける」の部分は、ライブ配信する画像に認識した顔の周りに枠をつけて、名前や信頼度を表示させるためのものです。

③faceDetect関数の呼出し部分の追加

上で定義したfaceDetect関数を呼び出す部分を、moveDetect関数内の「#ログ出力」の下に追加します。動体検知後に顔認証を行うことで、全体の処理を軽くできます。

④テスト

それでは、作成したプログラムを動かしてみましょう。プログラムが起動したら、カメラに顔を向けてみて下さい。以下のようにログが表示されて、Lineに通知が来れば完成です!!

チューニング

プログラムがちゃんと動くようになったら、顔認証の精度を高くできるように、顔データやパラメータを調整してみて下さい。

・顔データ:光の当たり方や顔の大きさなどで、認証できたりできなかったりします。認証の精度を高めるためには、実際に防犯カメラを設置する場所に置いて、学習用の顔データを撮影すると良い結果となりました。
・minSize:faceCascade.detectMultiScale()のminSizeパラメータは、顔検知を行う最小サイズを設定します。カメラから離れている状態で顔認証してしまうと、範囲が狭く範囲内のピクセル数が少ないので精度が落ちてしまいます。これも、実際の設置場所に合わせて大きな値とすると精度が高くなりました。
・confidence:ドアセキュリティに利用する場合など、高い信頼性が求められる場合には、confidenceの判定条件をキツくした方が良いと思います。

ちなみにチューニングを繰り返していると、我が家では80%ぐらいの精度でそれぞれの人の顔を認証できるようになりました。たまに、子供の顔をパパとして認証してしまいますが、これは親子の顔が似ているからなんですかねー?

CPU・メモリ使用率

ここまでの動画配信・記録、動体検知・line通知、顔検知・顔認証機能を含む防犯カメラをRaspberry Pi 3B+で実行した時のCPU使用率、メモリ使用率は以下のとおりでした。

・平常時(動画配信・記録時)

・繁忙時(動体検知・顔認証の動作時)

この結果からも、十分にRaspberry Pi 3B+で動作可能かと思います。あとはAlexaの動作に耐えられるかです。

おわりに

今回は防犯カメラに顔認証機能を追加し、Lineに通知することをやってみました。次回は、防犯カメラにAlexaを搭載したいと思います。

間違い・改善点や質問など、あったらコメント欄に書いていただければと思います。

連載記事

 1回目:カメラの設定と動画記録
 2回目:カメラ映像のライブ配信
 3回目:動体検知機能とLineへの通知
 4回目:顔認証機能とLineへの通知
 5回目:Raspberry PiへのAlexaの搭載 ←次はこれ
 6回目:顔認証後にAlexaで音声通知

関連記事

Alexaをしゃべらせる(Node-red編)
やりたいことNode-redでnode-red-contrib-amazon-echoやnode-red-contrib-alexa-home-skillのパレットを使うと、Alexaに音声で話しかけることをトリガーにNode-redの処理
自分のGoogleカレンダーにJWTを使って予定を追加してみる
今回は、JWT(JSON Web Token)を使って、ブラウザからのログイン操作なしで特定のGoogleカレンダーに予定を追加することをやってみます。
Alexaに通知を送る(Node-red編)
今回は、Alexaに「通知」を送ることをやってみたいと思います。ちなみに、この通知を送る機能は「プロアクティブイベントAPI」という物を利用しますが、少々実装が面倒なのが難点です。
Node-redでスマートハウス-LG製テレビを操作してみる(1/5)
はじめに我が家にも有機ELテレビがやってきました。国産メーカのテレビも、有機ELパネルはほとんどがLG製のパネルを利用しているらしく「同じパネルなら安い方がいいんじゃない?」という事でOLED 55C7Pを購入!このLG製のテレビ、内部はw
Node-redでスマートハウス-Gravioで子供用プリキュアボタン
今回は、Gravioのボタンセンサーを使って、2歳の子供でもテレビのアプリをyoutubeにして、プリキュアの動画を再生できる「プリキュアボタン」を作りたいと思います。
Gravioでミルク&オムツ交換記録をGoogleカレンダにつけてみる
子育てをしていると両手が塞がっていたり、手が汚かったりすることが本当多いんです。なので、スマホを手に取って、ロック解除して、記録アプリを開いて、時間・種類などをいちいち入力することはホント面倒です。今回は「赤ちゃんボタン」を作って、ボタンを押すだけでミルク&おむつ交換の記録がワンプッシュで記録することをやってみます。
Node-redだけで簡易Alexaアプリを作ってみる「アレクサ、雨雲きてる?」
今回はASKを使わずNode-redだけを使って、自分用の簡易Alexaアプリを作ることをやってみたいと思います。
HomeAssistantでスマートホームコントローラを作ってみる[1/6]
家の中にIoT機器が増えてくると、スマホのリモコンアプリやHEMSのパネルなど、情報や操作がバラバラになってきます。そこで、今回はHome Assistantを使って家の中のIoT機器を一元管理できるようにしてみたいと思います。
記事が参考になったら、ブログランキングに協力(クリック)して貰えると嬉しいです。
スポンサーリンク
naka-kazz

昼間はIT企業に勤めてますが、プライベートでは「育児×家事×IoT」をテーマに家のスマートホーム化に取り組んでいます。Androidアプリも作っているので使って下さい。質問・コメントは、↓のコメント蘭でもFacebookメッセンジャーでもどちらでも大丈夫です。
E-mail:naka.kazz.d@gmail.com

naka-kazzをフォローする
スマートホーム 開発者向け
naka-kazzをフォローする
育児×家事×IoT

コメント

  1. 平澤俊樹 より:

    初めまして、いつもブログを楽しみに拝見しています。
    私もRaspberry piを使用し画像認識で積層灯を認識し
    アクションをしたいと思っており試行錯誤しています、
    教えていただけませんでしょうか?

    • naka-kazz naka-kazz より:

      ブログをお読みいただき有ありがとうございます。
      私にできることでしたら、回答させていただきますので、メールでもFacebookのIMでも大丈夫ですので、
      ご連絡いただければと思います。

  2. Dorahopu より:

    ④のテストでプログラミングを実行すると、
    「base_camera.py, line 94, in _thread」
    「Camera.py, line211, in frames」
    という2つのエラーが出てしまうのですが、解決策を教えてください。
    何度も質問してしまいすみません。

    • naka-kazz naka-kazz より:

      こちらもエラーの全文を教えていただけば解決策がわかるかもしれません。Camera.pyの211行目が間違っているようですが、211行目には何が書いてありますでしょうか?

タイトルとURLをコピーしました