United Statesからアクセスのようです。言語設定をEnglishに切り替えますか?
Switch to English site
Skip to main content

AIによる人追跡ショッピングカートの開発 ~パート1: さぁ、はじめよう~

Nvidia Jetson Nanoをセットアップし、人の後ろをついて回るロボットカートを製作するための準備として、機械学習の実験を行います。

Nvidia Jetson Nano

はじめに

昨今、機械学習とAIは、テクノロジー業界でのトレンドとなっています。ただ、初めてAI の世界に足を踏み入れる際、ハードルが高いと感じる人は多いでしょう。実のところ、全くもって難しいことはなく、むしろ真逆といって良いような時もあるんです。

このプロジェクトでは、人を追尾できるカートを作成することを目指しています。庭で物を運ぶ際の台車のようなもので、電動で、コンピュータビジョン装置を備えており、人を特定して追尾できるようになっていると考えてもらえるとわかりやすいかと思います。今回は、組み込みシステムでのコンピュータビジョンや、機械学習に最適で、Nvidia Maxwell GPUやクアッドコアARMプロセッサを搭載したプラットフォームである、Jetson Nanoを使用します。

最初の一歩

Out of the box - Nvidia Jetson Nano

まず始めに、Jetson Nano開発者キット (199-9831) を開封します。このキットには、M.2スロットや、カメラ用MIPI-CSIヘッダ x 2、4Kに対応したHDMIとDisplayPortソケット、4つのUSB3.0ポート、Raspberry Pi互換のGPIOヘッダ、イーサネット、2つの電源ポートなど、十分なI/Oを備えたキャリアボードの上にJetson Nanoモジュールが固定された、シングルボードコンピュータが入っています。

ボードが安定して動作するためには5V電源が必要なため、電源には5V-4A (144-0968) のものを選択し、十分な余裕を確保しました。加えて、Raspberry Piカメラv2やUSBウェブカメラも、リアルタイムでのビデオストリーミングのために必要になります。

プロジェクトを始めるにあたり、Nvidia社から明確なガイドが提供されており、使用する前の準備手順が説明されています。ここでは、ガイドから少し離れて、電源をバレルジャック入力に切り替えました。詳細はJetson開発者キットユーザーガイドに載っていますが、バレルジャックのすぐ隣にあるジャンパ「J48」を移動させ、2つのピンを接続する必要があります。

電源の入力を変更し、SDカードにNvidiaから提供されているOSイメージを書き込みます。これは6GBもある、非常に大きなZIPアーカイブで、展開すると16GBの容量を必要とします。そのため、十分なディスクスペースがあることを先に確認してください。その後、Balena EtcherやWin32DiskImagerの様なツールを使い、ファイルをSDカードに書き込みます。この手順は、Raspberry Piや、他のシングルボードコンピュータを使用したことがある人であれば、馴染みのあるものでしょう。

あとのセットアップは、いくつかのオプションを選択することでした。ここではすべてデフォルトを選択するのが良いでしょう。次に、システムをsudo apt update && sudo apt upgradeで最新の状態にします。

サンプルを動かしてみる

Nvidia社から、Jetson Nanoで実行するためのサンプルが様々提供されており、その中に「2日間でできるデモンストレーション」という短いコースがあります。これは、環境設定から、簡単なサンプルの実行、そして、より複雑なサンプルを実行することで、簡単なサンプルから得られた知識をさらに拡張する、といったコースです。

また、Jetsonコミュニティープロジェクトもあり、単純なプロジェクトから、三角コーンのリアルタイム検出といったハイレベルなものまで、幅広いプロジェクトがあります。

セットアップが正常にできているか確認するために「Hello AI World」のサンプルを使用しました。これは、 ディープラーニングを用いた物体検出のデモになります。GitHubリポジトリの「Building the Project from Source」に従って、必要な依存関係をすべてクローンし、その後、全体をビルドします。

ここでは、モデルをダウンロードし、大量のコードをコンパイルする必要があるため、時間がかかります。デフォルトでは、一部の画像認識用モデルしか選択されていませんが、後で気が変わったらdownload-models.shスクリプトを再度実行し、モデルの変更が可能です。

Running an example, with Pi Camera connected to the development board

すべてコンパイルされ、インストールが終わったら、開発キットに接続したPi カメラを使ってサンプルを実行できます。使用したことのないモデルを用いてアプリケーションを実行する際は、モデルネットワークファイルの最適化のためにいくらか時間がかかりますが、今後の読み込み時間を短くするために、ディスクにキャッシュされます。

このデモンストレーションは上手くいったので、次は、顔認識を一切使用しない人の追跡を実現する方法について考えることにしました。

人の追跡

物体追跡・認識は十分に発達していて、生産ラインで品物を運ぶ必要があるロボットや、ベルトコンベアから流れてくる品の合否を決めるロボットなど、マシンビジョン応用において産業界ですでに幅広く使用されています。特に、ひとつの品目に対して動作の追跡を行う場合など、タグをつけることで解決できますが、今回私たちが取り組んでいる問題は、ユーザーがタグを身につける必要がなく、何を着ているのかといったことだけでユーザーを特定できるようにすることです。

顔認識は、人物を特定し、追跡する際に有効です。ただ、今回のような、ショッピングカートが人の後ろについて回るといった状況では、顔が見えず、有効的な方法ではありません。こういったことから、今回のプロジェクトを成功させるために活用できる方法の選択肢がいくらか制限されました。

いろいろと調べてみると、「person re-identification(人物再同定)」という言葉がヒットしました。ScienceDirectによるとこれは、「異なる複数のカメラ映像から、様々な時間や場所において個人を識別する問題」です。これは、私たちが行いたい人物特定に近いものですが、今回は1つのカメラ映像しか取得できないため、使えません。

Yolo v4 + DeepSORT

Object tracking(物体追跡)が、解決策として最適です。さらに検索してみると、こちらの「DeepSORT」を用いた物体追跡の記事が見つかりました。方向性としては合っているように思えるので、さらに検索を続けてみると、このGitHubリポジトリが見つかりました。READMEにある動画では、人を識別し、追跡している様子が示されており、今回のプロジェクトに適していると考えました。

また、この例では、人の周りにボックスが描かれていますが、このボックスによって、ロボットの視覚の中央に特定の人物を移動させることが可能であると期待できます。

リポジトリのドキュメントも非常に充実していたので、これを試してみることにしました。ただし残念なことに、一部のプログラムは正常に動作しないことが予想されました。Jetson Nanoでは、サイズの大きな「YOLOv4」モデルに対応できなかったのですが、なんとか「YOLOv4-tiny」モデルを処理し、その後、実際の物体追跡スクリプトの実行を試みましたが、動作しませんでした。この問題は、よりパワフルなJetson SoM(System on Module)や、PCIe接続のNvidia GPU搭載PCには、関係のないものでしょう。

FastMOT

次に、別のGitHubリポジトリのプログラムで、「YOLOv4」モデルを使うものを試してみました。また、ここでも先ほどと同様に、ドキュメントが明確で、簡単に使用することができるスクリプトが提供されていました。

Githubリポジトリをクローンし、scripts/install_jetson.shにあるセットアップスクリプトを使って、インストールを開始することができました。ただ、PyCudaをインストールまではうまくいっていたものの、ヘッダファイルが見当たらずに失敗しました。いろいろと調べていると、このNvidiaフォーラムのスレッドが見つかり、別のGithubリポジトリにある、PyCudaを正しくインストールするためのスクリプトが示されていました。

ようやくPyCudaのインストールが完了したので、元のインストールスクリプトを再度実行しました。先ほどよりも進んだものの、また別の依存関係をインストールする際に落ちてしまいました。原因は、ヘッダファイルxlocale.hが抜けていたことでしたが、このStackoverflowでの投稿のaccepted answerによって解決しました。コマンドln -s /usr/include/locale.h /usr/include/xlocale.hを実行することで、新たなlocale.hヘッダへのシンボリックリンクを作成するというものでした。

シンボリックリンクができたので、install_jetson.shスクリプトを実行し、今度はすべての依存関係がインストールできました。Jetson Nanoでは、LLVMのコンパイルに数時間かかるので、放置して、別の作業をして待ちましょう。

全てのインストールが終わったので、必要なモデルをダウンロードしました。これは、./scripts/download_models.shを実行するだけといった具合に簡単でした…と、その時は思いました。このスクリプトはPythonライブラリの gdown をインストールします。これにより、大きなファイルがGoogle Driveからダウンロードする処理が走りますが、シェル内で実行可能ファイルとして表示されるはずが、見つかりませんでした。試行錯誤したのちに、pipから、ダウンロードした実行可能ファイルが保存されているパスまで辿ったところ、/home/jetson/.local/bin/にありました。

スクリプト内の、任意の実行可能ファイルとして扱われているgdown のインスタンスを、/home/jetson/.local/bin/gdownと置き換えることで、すべてのモデルをダウンロードすることができました。さらに、TensorRTプラグインをビルドするためのコンパイルも、リポジトリのドキュメントに沿って行い、プログラムを実行する準備が整いました。

デスクトップ環境からpython3 app.py --input_uri csi://0 --mot --guiとコマンドを入力し、プログラムを実行しました。ここでは、700MB程度のモデルがすべてコンパイルされたので、しばらく時間がかかります。最初は作動しませんでしたが、修正点がすでにプロジェクトのイシュートラッカーで示されており、2つのファイル、yolo.pyreid.pyの1行を1 << 30から1 << 28に変更することで、問題が修正できました。

最初のコマンドを再度実行してプログラムを立ち上げるには、前回コンパイルが中断されたため、しばらく時間がかかりましたが、最終的にはウィンドウが現れました!カメラフィードが表示されており、良い調子です。次に、カメラの映像を見てみると、ボックスと番号が表示されていました!ネットワークが、動き回る人々を検出して追跡する能力があることを示しており、実験は成功です。性能に関しては、ずば抜けて素晴らしいものではありませんが、ドキュメントで指定されているのはJetson TX2/Xavier/Xavier NXであり、Jetson Nanoにそれほどの処理能力が無いことを踏まえると、十分な結果です。

Running FastMOT tracking program

機能する追跡ソリューションの実現を達成した今、コードを変更して座標を出力できるようにし、その後、それを使って、ロボットの電気系統に命令を出すことが可能になります。サンプルのコードですでに追跡対象の周辺にボックスを描いているので、そこまで難しい話ではないはずです。

結論

この投稿では、Nvidia Jetson Nanoの始め方から、フレーム内の人物を追跡する様々方法を調べ、FastMOTベースの人物追尾システムの稼働まで成功させました。パート2では、ロボットのフレームを作成していきたいと思います。

Engineer of mechanical and electronic things by day, and a designer of rather amusing, rather terrible electric "vehicles" by night.