この記事は 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アプリについても書いており、ある程度分かっている人にも、手応えのある一冊になっていると思いますので、この冬はぜひ!
物体検知して通知する見守りサーバーとして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 (下図のように修正)
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%
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 (下図の内容で作成)
設定ファイルは、ログファイル中に「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]キーをタイプし画面を進めて設定を完了します。
メールサーバーとして「Postfix」がインストールされるため、設定ファイルの「/etc/postfix/main.cf」をエディターで開き末尾に追加します。
$ sudo nano /etc/postfix/main.c (下図の内容を末尾に追加)
中継サーバーへの接続に必要な、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秒)は、通知しないように設定します。
設定ファイルが用意できたら、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