つるながの綴り方

ITインフラ系のネタやTips、趣味としているカーライフなどを中心に日頃メモしておきたいことをしたためています。

【SB-AI部 Advent Calendar 2019】物体検知して通知する見守りサーバーとしてJetson Nanoを活用する方法

この記事は SoftBank AI部 Advent Calendar 2019 の11日目の記事です。 SB-AI部とは、ソフトバンク株式会社公認のクラブ活動です。AI関連の話題の共有、イベント情報、質問、議論、企画、雑談、希望メンバー同士のシャッフルランチなどなどが行われています。詳細はこちら。 qiita.com

自己紹介

社内向け)
本務はTUのアプリケーション技術本部です。2018年からTechnical Meisterを拝命しており、サーバーインフラの企画/設計/開発に従事しています。SBグループのAIインキュベーション部門も兼務しており、社内外スタートアップ起業の技術支援をさせていただいています。

社外向け)
学⽣時代に⽴ち上げたスタートアップのM&Aによりソフトバンクに。同時に、地元愛知から東京へ居を移し、以来技術部⾨に従事。運⽤業務、インフラ構築業務、アプリ開発と多くの技術系業務を経験してきましたが、近頃はインキュベーション事業や、社内の勉強会、ハッカソンなどのイベント運用にも携わっています。
著書一覧

Jetson Nanoの本が出ます

Jetson Nanoについて書かせていただきました。「Linux何?」というレベルからでも読めるようになっていますが、本格的なAIアプリについても書いており、ある程度分かっている人にも、手応えのある一冊になっていると思いますので、この冬はぜひ!

www.hanmoto.com

物体検知して通知する見守りサーバーとしてJetson Nanoを活用する方法(Darknet+YOLOv3)

「Jetson Nano 超入門」では3章を担当しており、実はAIアプリについては書いていませんが、日経Linux 2019年9月号で、タイトルの内容の記事を書かせていただきました。そちらをベースに改めて書かせていただきたいと思います。


 Jetson Nanoを「見守りサーバー」として活用します。Jetson Nanoにカメラをつなぎ、ビデオ映像から物体を"検出"し"識別"できるようにします。次に特定の物体を検出したら、メールで通知を行うようにします。
 画像認識の応用例には、数多くのデモアプリがあります。最も利用されているのが、NVIDIA社がJetsonシリーズ向けに公開している「jetson-inference」です。C++で書かれたソースコードをダウンロードしてビルドするだけで動作しますが、ラズパイ用カメラモジュールが必要になり、USB接続型のWebカメラを使用するには、別途作業が発生します。また動作も安定しません。
 本パートでは、オープンソースニューラルネットワークフレームワークの「Darknet」と一般物体認識モデルの「YOLOv3」を使ってリアルタイムで高速に物体認識できるようにします。YOLOは「You Only Look Once」を略したもので、語源は「You Only Lovd Once(今を生きる)」のスラングとされています。物体検出数、精度、速さといった点で高く評価されています。
 次の3ステップで、見守りサーバーに仕立てます。

【ステップ1】一般的なUSB接続型Webカメラでリアルタイム物体認識
Jetson NanoにDarknetとYOLOv3をインストールして、一般的なUSB接続型Webカメラでリアルタイム物体認識を実現します。

【ステップ2】ネットワークカメラでリアルタイム物体認識
ネットワークカメラからインターネット経由で映像を受信し、リアルタイム物体認識を行います。Webカメラもラズパイカメラも調達できない場合に、身近なAndroidスマホをネットワークカメラとして利用できます。

【ステップ3】指定した物体を認識したらメール通知を行う
Darknet+YOLOv3による物体認識では識別した物体の名称がコンソールに出力されます。出力される文字列に対して、特定のパターンがあらわれた際にメール通知を行うよう設定します。たとえばコンソール出力に「person」といった文字列を見つけたら、人物を検知したと判断しメールを送信します。

【ステップ1】一般的なUSB接続型Webカメラでリアルタイム物体認識

 Darknetをインストールします。ソースコードGitHub上で公開されています。次のようにgitコマンドを使って、ソースコードをダウンロードします。なお本説明では、ホームディレクトリーにダウンロードします。ほかのディレクトリーを使用する場合は適宜読み替えてください。

$ git clone https://github.com/AlexeyAB/darknet darknet

 ダウンロードが完了すると、darknetディレクトリーが作成され、そこにソースコードが格納されます。カレントディレクトリーをdarknetに移動します。

$ cd darknet

 ソースコードをビルドする前に、環境変数を追加し、CUDA開発環境を使えるようにします。環境変数を追加するよう、ホームディレクトリーの「.bashrc」をエディターで開き、末尾に2行追加します。

$ nano ~/.bashrc
↓ 末尾に追加
export PATH=/usr/local/cuda/bin:${PATH}
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:${LD_LIBRARY_PATH}

 再ログイン後から、新しい環境変数が有効化されますが、即座に反映させるには、sourceコマンドを実行します。nvccコマンドが使えるかどうかで、有効化されたかどうか確認できます。

$ source ~/.bashrc
$ which nvcc
/usr/local/cuda/bin/nvcc <--確認

 ビルドする前に、Jetson NanoにあわせてMakefileファイルをエディターで開き、下図のように修正します。darknetはGPUがなくてもCPUによる計算が可能です。そのためデフォルトでCPUを使うよう設定されているため、必ず修正してください。

$ nano Makefile
(下図のように修正)

f:id:tsurunaga:20191210221945p:plain
Makefile修正

 makeコマンドでソースコードから実行ファイルにビルドします。パワーモードを変更したJetson Nanoでも、20分程度かかります。完了したら何も引数に付けずにdarknetを実行してみましょう。

$ make
$ ./darknet
usage: ./darknet <function> <--確認

 物体検知には、学習済みのモデルが必要になります。YOLOv3の学習済みモデルをダウンロードします。モデルとして3種類用意されていますが、最初にサイズが小さい「yolov3-tiny」を試してください。サイズが大きいモデルを使用することで、精度は向上しますが、処理が重くなります。ほかのモデルを使用する方法は、最後に解説します。

$ wget https://pjreddie.com/media/files/yolov3-tiny.weights

 試しにテスト用の画像ファイルを使って、物体認識できるかどうか確認します。次のようにdarknetを実行します。

$ ./darknet detector test cfg/coco.data cfg/yolov3-tiny.cfg yolov3-tiny.weights ./data/person.jpg

 一般物体認識とは、画像中の物体の位置を検出し、その物体の名前を予測する処理です。物体を検知すると、図のようにバウンディングボックスで囲まれ、認識された物体の名前がボックスの上に表示されます。同時にコンソールには、検知された物体の名前と確信度が表示されます。

dog: 89%
dog: 82%
person: 98%
sheep: 83%

f:id:tsurunaga:20191210222024p:plain

 darknetを終了するには、[Ctrl][C]を同時にタイプします。
 darknet実行時に「Gtk-Message: Failed to load module "canberra-gtk-module"」といったエラーが表示されます。動作に支障はありませんが、気になるようなら次のようにパッケージを追加インストールします。

$ sudo apt install libcanberra-gtk-module

 いよいよ、USBポートにWebカメラを接続して、リアルタイム物体認識を実行します。USB Video Class(UVC)に対応したWebカメラなら、ドライブーは不要です。
 接続したWebカメラが使用可能かどうか、Cheeseアプリで確認できます。Cheeseを起動したら、画面にビデオ映像が写っているか確認してください。

$ cheese

 Cheeseを起動させている場合は終了してから、次のようにdarknetを実行して、リアルタイム物体認識を行います。Webカメラのほかにもカメラを繋げている場合は、「-c 番号」で番号を0から1に変えるなどしてください。

$ ./darknet detector demo cfg/coco.data cfg/yolov3-tiny.cfg yolov3-tiny.weights -c 0

 最初に、カメラの映像が全画面表示されますが、それを閉じると、入力解像度と同じ大きさでウィンドウ表示されます。テスト画像で物体認識したときと同じように、コンソールに、認識されたものが即座に表示され、1秒間に何フレームを処理したかが、FPSとして表示されます。パワーモードを上げたJetson Nanoでは、解像度640×480の映像に対して、15〜20FPS程度の処理が可能でした。
 ここまでの手順が完了したら、[Ctrl][C]を同時にタイプして、いったんdarknetを終了します。

【ステップ2】ネットワークカメラでリアルタイム物体認識

 ステップ2として、ネットワークカメラの映像をリアルタイムで受信し、USB接続されたWebカメラと同じように、リアルタイム物体認識できるようにします。
 darknetが対応しているネットワークカメラは、「http://IPアドレス」といったURLでアクセスでき、映像をMotion JPEG形式でストリーミング受信できるものになります。専用のネットワークカメラを使わなくても、Androidスマホにアプリをインストールすることで、ネットワークカメラとして利用できます。たとえばAndroidアプリの「IP Webcam」が使用できます。
 IP Webcamは「4.Androidスマホ編」で取り上げられています。P.〇〇を参考にインストールし、配信を開始してください、LAM環境が劣悪だと、映像の転送に時間がかかります。ビデオの画質を落としたり、最大フレームレートを低くするなどして調整します。
 ネットワーク配信された映像をもとに、リアルタイム物体認識するには、darknetを次のように実行します。

$ ./darknet detector demo cfg/coco.data cfg/yolov3-tiny.cfg yolov3-tiny.weights http://スマホのIPアドレス:8080/video?dummy=param.mjpg -i 0

 LANの環境やスマホの性能にもよりますが、ネットワークカメラを使ったリアルタイム物体認識では、解像度640×480の映像に対して、処理能力が1〜2FPSに低下しました。

【ステップ3】指定した物体を認識したらメール通知を行う

 Darknet+YOLOv3による物体認識では、識別した物体の名称が文字列として出力されます。出力された文字列に対して、特定のパターンがあらわれた際にメールで通知するには、1.認識した物体の名称をログファイルに出力する、2.ログファイルをSwatchで監視して特定のパターンを検知したらメールを送信する、3.Jetson Nanから外部のメールサーバーにメールを中継する、といった手順で行います。
 darknetのコンソールに表示される内容を、ホームディレクトリ内のdarknet.logファイルに出力するよう、「> ~/darknet.log」を付けて、次のようにdarknetを実行します。そのほかのオプションや引数は、Webカメラを使った場合や、ネットワークカメラを使った場合と同じです。目的にあわせて変更してください。

$ ./darknet detector demo cfg/coco.data cfg/yolov3-tiny.cfg yolov3-tiny.weights -c 0 > ~/darknet.log

 ログファイルの監視に「Swatch」を使用します。次の手順でインストールし、動作確認用に設定ファイルの「swatch.conf」を用意します。

$ sudo apt install swatch
$ nano swatch.conf
(下図の内容で作成)

f:id:tsurunaga:20191210222109p:plain

 設定ファイルは、ログファイル中に「Failed password」といった文字列を検出すると、画面に出力(echo)すると同時に、「foo@example.jp」宛に、題名が「alert_from_swatch」といったメールを送付します。
 次のように「swatchdog」を実行すると、「/var/log/auth.log」に対して、ログ監視を始めます。

$ sudo swatchdog --config-file=swatch.conf --tail-file=/var/log/auth.log

 試しに、Jetson Nanoに対して間違ったユーザー名やパスワードでSSHログインを試みてください。swatchdogを実行している端末上に、パターンに一致したログが表示されるはずです。
 次に、メール通知できるようJetson Nanoをメールサーバーとして仕立てます。外部のメールサーバーに接続してメールを中継しますが、昨今の迷惑メール対策で、家庭内でメールサーバーを立てるのが難しくなっています。SMTP認証に対応した中継サーバーを利用できない場合、Gmailアカウントを新規に取得することで、簡単に中継サーバーを用意できます。それにはWebブラウザーで「https://accounts.google.com/SignUp」にアクセスし画面の指示通りに登録します。すでに取得済みのGmailアカウントでもメール中継可は可能です。ただし、2段階認証を設定すると、中継が制限されます。「https://myaccount.google.com/lesssecureapps」を参考に、安全性の低いアプリの許可を有効にして、中継できるようにしてください。
 以降、Gmailを中継サーバーとして使用することを前提に、メール通知を行う方法を解説します。ほかの中継サーバーを使用する場合は、メールサーバーアドレス、ユーザー名、パスワードを適宜置き換えてください。
 次のようにしてメールユーティリティーをまとめてインストールします。

$ sudo apt install mailutils

 インストール中に、下図のような、メールサーバーとしてのタイプを選択する画面が表示されたら、「ローカルのみ」を選択します。あとは[Enter]キーをタイプし画面を進めて設定を完了します。
f:id:tsurunaga:20191210222145p:plain  メールサーバーとして「Postfix」がインストールされるため、設定ファイルの「/etc/postfix/main.cf」をエディターで開き末尾に追加します。

$ sudo nano /etc/postfix/main.c
(下図の内容を末尾に追加)

f:id:tsurunaga:20191210222228p:plain

 中継サーバーへの接続に必要な、Gmailアカウントとパスワードを「/etc/postfix/sasl_passwd」ファイルに設定します。

$ sudo nano /etc/postfix/sasl_passwd
↓次の1行を追加
[smtp.gmail.com]:587    Gmailのアドレス:パスワード

 設定したパスワードをデータベース化して、最後に設定した内容を有効化するよう、メールサーバーを再起動します。

$ sudo chmod 600 /etc/postfix/sasl_passwd
$ sudo postmap hash:/etc/postfix/sasl_passwd
$ sudo systemctl restart postfix.service

 試しにメールを送信して、動作を確認します。

$ echo "mail test" | mail -s "TEST" メールアドレス

 あとは、Swatchを起動しdarknetが出力するログファイルの「~/darknet」に対して、監視するようにします。下図の内容で、「swatch.conf」を修正します。今回あらたに、「threshold」を設定しています。物体認識では、認識した結果を連続して出力するため、都度通知をおこなうと、大量のメールを送信することになります。そこで、3回連続して検知したら通知するようにし、1度検知してから5分間(300秒)は、通知しないように設定します。

f:id:tsurunaga:20191210222326p:plain

 設定ファイルが用意できたら、swatchdogを次のようにして起動します。

$ swatchdog --config-file=~/swatch.conf --tail-file=~/darknet.log

 これで、人物を検出するとメールが送られるようになります。検出する文字列を「dog」や「cat」に変更すれば、犬や猫がカメラに映った際に通知を行うようにできます。また車を検知したり、ハサミやカッターナイフのような刃物を検出したりして、危険物を知らせるといった使い方もできます。
 swatchdogに「--daemon」オプションを付けて実行すれば、バックグラウンドで処理されるようになります。また「gnome-session-properties」を使って、darknetを本体起動時に自動的に実行するようにもできます。ただし、冒頭の説明のようにJetson Nanoは開発用に作られているため、長期間の使用は発熱や安定性で問題があります。ここで解説した内容は、個人の楽しみの範囲で活用するようにしてください。

精度を向上する

 YOLOv3の学習済みモデルには、今回使用したTiny版のほかに、通常版と精度を向上させたSPP版(Spatial Pyramid Pooling Based YOLO)があります。Tiny版 < 通常版 < SPP版の順に精度が高く、その分処理が遅くなります。用途に応じて使い分けてください。それぞれ、以下のURLからダウンロードできます。

 darknetを実行する際に、ダウンロードしたweightsファイルとともにcfgファイルも、対応したものに変更してください。たとえばSPP版でdarknetを実行するときは、次のようにします。

$ ./darknet detector test cfg/coco.data cfg/yolov3-spp.cfg yolov3-spp.weights ./data/person.jpg