ラベル object detection の投稿を表示しています。 すべての投稿を表示
ラベル object detection の投稿を表示しています。 すべての投稿を表示

2020年1月4日土曜日

Raspberry Pi + Coral USB Accelerator + TensorFlow Lite で物体検出と姿勢推定を試してみよう

以下は、古くなったのでサポートを停止した情報です。代替ページとして「Raspberry Pi 5 でリアルタイムな姿勢推定と物体検出」をお勧めします。

1. はじめに

注:本ページの演習は Coral USB Accelerator をお持ちでなくても実行できます

Raspberry Pi で YOLO v3-Tiny / YOLO v3 による物体検出を試してみよう」 では、物体検出の手法である YOLO を Raspberry Pi で試しました。
上記ページの演習を実行すると本書で学んだ CNN が物体検出で使われていることを体験頂けますが、計算量が多いため、カメラからの映像に対して物体検出を行うと映像の遅れが大きいことも分かりました。

一方、ディープラーニングの計算を高速化するために、グラフィックを描画するためのハードウェアである GPU が用いられるということを聞いたことがある方もいると思います。 GPU による高速化はRaspberry Pi でも行われており、例えば Idein 社の取り組みなどがあります。

本ページでは、ディープラーニングの推論部(学習後のネットワークによる認識部)の高速化のために Coral USB Accelerator を用いる手法を紹介します。 Coral USB Accelerator は内部に Google が開発した Edge TPU と呼ばれる AI 用ハードウェアを搭載しており、Raspberry Pi に USB ケーブルで接続することで、Raspberry Pi の代わりに高速に推論の計算を実行してくれるデバイスです。


上図は Raspberry Pi 4 に Coral USB Accelerator を接続し、カメラからの映像に対して物体検出を行っている様子です。以下の物体が検出されていることがわかります。
  • chair : 椅子
  • dining table : ダイニングテーブル
  • laptop : 実際にはラップトップPCではなく小型ディスプレイ
  • cup : カップ
  • keyboard : キーボード
  • mouse : マウス
また、少し見にくいですが左上に「19.9ms」と書かれており、これは物体検出の計算に 19.9ミリ秒の時間がかかったことを示しています。これは1秒間に50回物体検出の計算を行えることを意味します。実際には他にも様々な処理が行われるため1秒ごとの計算回数はもう少し少なくなります。
この計算を Coral USB Accelerator なしで行うと約 300ms の時間がかかりますので、約 15 倍程度の高速化になっています。

本ページではこの演習を行う方法を解説します。Coral USB Accelerator を Raspberry Pi 4 に接続した様子が下図になります。

Coral USB Accelerator は例えば下記で購入できます。
1万円以上するため、気軽に購入して試してみるというわけにはいかないかもしれません。
上述したように、本ページでは「Coral USB Accelerator を使った場合」と「使わなかった場合」とで計算時間を比較しますので、Coral USB Accelerator がなくても演習を体験できます。

Raspberry Pi で YOLO v3-Tiny / YOLO v3 による物体検出を試してみよう」で用いた YOLO とは異なる物体検出の方法を用いますので、性能の違いを体験してみるのもよいでしょう。

また、本ページの末尾では Coral USB Accelerator を用いた人物の姿勢推定のプログラムの実行方法も紹介します。こちらも Coral USB Accelerator がなくても動作しますので是非試してみてください。

2. 準備とTensorFlow Liteのインストール

それでは、本ページに演習を行うための準備を解説していきます。 必要なのは下記のものです。
  • Raspbian Busterをインストールした Rasberry Pi ( Pi 3 B+ と Pi 4 B でのみ試しました)
  • Raspberry Pi 公式カメラモジュールまたはウェブカメラ(ウェブカメラは Logicool 社製のみ試しました)
  • Pytrhon3 用の OpenCV 3 がインストールされていること
  • TensorFlow 1 系がインストールされていないこと
さらに、本書を全て終えた状態の Raspberry Pi を仮定します。その状態を簡単に実現するには、まず下記のページに従い Python3 用のツールをインストールします(ただし、kerasの設定は不要です)。
そうすると、TensorFlowがインストールされた状態になります。上記ページで、TensorFlow 1 系をインストールした方は、ターミナルを起動して下記のコマンドで TensorFlow のみを削除します。 TensorFlow 1 系がインストールされている環境では本ページで用いる TensorFlow Lite のプログラムの実行ができなくなるためです。 本ページの演習が終わり、また TensorFlow が必要だと感じた時に改めて再インストールしてください。
sudo pip3 uninstall tensorflow
途中で「Proceed (y/n)?」などと(場合によっては複数回)聞かれますので、キーボードで「y」をタイプしてEnterキーを押し、処理を進めて下さい。

次に、TensorFlow Liteをインストールします。 TensorFlow Lite とは、PCなどとは異なり計算パワーが小さいコンピュータでディープラーニングの計算を行わせるためのライブラリです。例えば、Android や iPhone などのスマートフォンでディープラーニングの計算を行いたい場合にも用いられます。

上で触れたように、Raspberry Pi ではフルセットの TensorFlow が動くのですが、Coral USB Accelerator のプログラムを実行するには TensorFlow Lite が必要になるのです。

下記の2つのコマンドを一つずつ順に実行すれば TensorFlow Lite のインストールは完了です。このコマンドを含め、本ページのコマンドは長いものが多いので、コピー&貼り付けにより確実に実行してください。
wget https://github.com/google-coral/pycoral/releases/download/release-frogfish/tflite_runtime-2.5.0-cp37-cp37m-linux_armv7l.whl

sudo pip3 install tflite_runtime-2.5.0-cp37-cp37m-linux_armv7l.whl
次に、Coral USB Accelerator を使うためのライブラリのインストールを行います。下記の4つのコマンドを一つずつ順に実行すれば完了です。なお、このコマンドは「Get started with the USB Accelerator」ページで解説されているものです。
echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list

curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -

sudo apt update

sudo apt install libedgetpu1-std
ここまでが終わったら Raspberry Pi を再起動してください。

3. カメラから得られた画像に対する物体認識

それでは、Coral USB Accelerator で物体検出を試してみましょう。

まず、Coral USB Accelerator を持っている場合は、それを Raspberry Pi に接続しておきましょう。このとき、Raspberry Pi 4 をお使いの方は USB3 ポートに接続するようにしましょう。コネクタの色が青いのが USB3 ポートです。コネクタの色が黒い USB2 ポートに接続するよりも Coral USB Accelerator が高速に動作します。

また、Raspberry Pi 公式カメラモジュールまたはウェブカメラを Raspberry Pi に接続しましょう。Raspberry Pi 公式カメラモジュールをお使いの方は、設定アプリケーションでカメラを有効にすることを忘れないでください。これは本書でも行ったことですね。

それでは、まずサンプルアプリケーションをダウンロードし、さらに 学習済のデータファイルのダウンロードを行います。ターミナルを起動し、下記のコマンドを一つずつ順に実行して下さい。
git clone https://github.com/neuralassembly/CoralOpenCV.git

cd CoralOpenCV/object_detection

bash install_requirements.sh
一つ目のコマンドでサンプルファイル全体のダウンロードを行っており、二つ目のコマンドでプログラムの存在するディレクトリへ移動し、三つ目のコマンドで学習済のデータファイルをダウンロードしています。なお、このサンプルファイルは Coral USB Accelerator 公式のサンプルファイルに、筆者が OpenCV によるカメラ対応を追加したものです。

さて、上のコマンドを実行したターミナルでそのまま下記を実行すれば物体検出が行われます。
python3 detect_opencv.py --model models/ssd_mobilenet_v2_coco_quant_postprocess_edgetpu.tflite --labels models/coco_labels.txt 
Coral USB Accelerator をお持ちではない場合、下記のコマンドを実行してください。
python3 detect_opencv.py --model models/ssd_mobilenet_v2_coco_quant_postprocess.tflite --labels models/coco_labels.txt 
なお、上記コマンドを実行する前にターミナルを一度閉じている場合、先に「cd CoralOpenCV/object_detection」コマンドによりディレクトリの移動を行ってから上記コマンドを実行してください。

なお、上記どちらかのコマンドでエラーが出る場合、一旦下記のコマンドで古いフォルダを削除し…
rm -rf ~/CoralOpenCV/
そして上の「git clone https://github.com/neuralassembly/CoralOpenCV.git」から始まる3コマンドを実行しなしてください。 それで問題が解消する場合があります。

プログラムが正しく動作すれば冒頭に示した図のように、検出された物体の位置に青い枠と名称が表示されます。


一枚の画像に対して物体検出を実行するのにかかる時間が映像の左上に表示されています。筆者が試したところ、おおよそ下記のような数値が得られました。Coral USB Accelerator を Raspberry Pi 4 の USB3 ポートに接続するのが最速ですが、USB2 ポートに接続した場合でも十分に恩恵を受けられることがわかります。

Pi 4 B + Coral USB Accelerator (USB3)20 ms
Pi 4 B + Coral USB Accelerator (USB2)45 ms
Pi 4 B + Coral なし300 ms
Pi 3 B+ + Coral USB Accelerator (USB2)60 ms
Pi 3 B+ + Coral なし590 ms

Raspberry Pi で YOLO v3-Tiny / YOLO v3 による物体検出を試してみよう」 で用いた YOLO と比較すると、Coral USB Accelerator を用いない場合であっても YOLO よりも高速に動作しているように感じます。

それは、この学習済ネットワークには Google により開発された MobileNetV2 + SSDLite という、高速化を意識したネットワークが用いられているからです。 ただし、学習用のデータセットはYOLOと同じCOCOが用いられているため、検出される物体は共通です。検出される物体のリストはこちらにあります。番号が 89 まで振られていますが、数字に抜けがあるので実際には 80 種類の物体を検出できます。

これくらいの速度で動作すると、周囲の物体検出をしながら動作するロボットの作成も現実的ではないでしょうか。

なお、プログラムを終了したい場合は、本書のプログラムと同様、認識の画面上でキーボードの「q」をタイプしてください。

4. (おまけ1)カメラから得られた画像に対する分類

以上で本ページの本題は終わりですが、ダウンロードしたサンプルプログラムには、「映像中に映っている物体の名称を表示する」という分類のプログラムもあるのでその解説もしておきます。 先ほどの物体検出との違いは、こちらのプログラムでは「映像に映っている物体は一つ」であることが前提されていることです。

下記のコマンドにより、分類用の学習データのダウンロードを行います。
cd ~/CoralOpenCV/classification

bash install_requirements.sh
そして、そのまま下記を実行します。
python3 classify_opencv.py --model models/mobilenet_v1_1.0_224_quant_edgetpu.tflite --labels models/labels_mobilenet_quant_v1_224.txt
Coral USB Accelerator をお持ちではない場合、下記のコマンドを実行してください。
python3 classify_opencv.py --model models/mobilenet_v1_1.0_224_quant.tflite --labels models/labels_mobilenet_quant_v1_224.txt
プログラムが動作すると、以下のように映像中に映っている物体(一つ)の名称が画面上部に表示されます。


こちらでは Google により開発された MobileNet V1 というネットワークが用いられています。 認識できる物体はホームディレクトリの「 CoralOpenCV/classification/models/labels_mobilenet_quant_v1_224.txt 」というテキストファイルに 1001 の英語の名称のリストが列挙されていますので、興味のある方は開いて確認してみてください。

4. (おまけ2)カメラに映っている人物の姿勢を推定する

もう一つ、カメラに映っている人物の姿勢を推定するプログラムの実行方法を紹介します。 人物の姿勢推定は、Microsoft の Kinect というデバイスを用いる方法が有名ですが、この例ではそれをディープラーニングにより通常のカメラで実現します。

こちらはサンプルプログラムをダウンロードして実行することにより、PoseNetというモデルを実行します。

まず、ターミナルを起動して下記の2つのコマンドを一つずつ順に実行し、必要なライブラリをインストールします。
sudo apt update

sudo apt install python3-edgetpu
なお、python3-edgetpu をインストールすると、互換性の問題で上でインストールした libedgetpu1-std が削除され、上の物体検出と分類の演習が行えなくなります。もう一度上の物体検出と分類の演習を実行したい場合、下記コマンドで libedgetpu1-std を再インストールしてください。ただしそうすると、たった今インストールした python3-edgetpu が削除され、今度は姿勢推定の演習が行えなくなります。面倒ですね。
sudo apt install libedgetpu1-std
さて、python3-edgetpu がインストールされた状態で、下記の4つのコマンドを一つずつ順に実行し、サンプルプログラムをダウンロードして実行環境を準備します。なお、このサンプルファイルは Coral USB Accelerator 公式のサンプルファイルに、Coral USB Accelerator がない場合のサポートを筆者が加えたものです。
cd ~/

git clone https://github.com/neuralassembly/project-posenet.git

cd project-posenet

bash install_requirements.sh
以上が終わったら、2つのコマンドを一つずつ順に実行してプログラムを実行します。
cd ~/project-posenet

python3 pose_camera.py 
Coral USB Accelerator をお持ちでない方は、以下のコマンドを実行してください。
cd ~/project-posenet

python3 pose_camera_cpu.py 
すると、下記のようにカメラの前の人物の姿勢(および目、鼻、耳)が線で表示されます。


なお、このプログラムはカメラの前に人が立つことを想定したものですが、プライバシーに配慮してフィギュアを用いた例になっておりますことをご了承ください。

また、このプログラムは、キーボードの「Ctrl-c」によりプログラムを終了します。
初回の実行時はプログラムの動作が遅いですが、コンソール上でキーボードで「Ctrl-c」を押して一旦プログラムを終了し、再びプログラムを起動するとそれ以降は快適に動作する印象があります。

また、カメラの前に人が立って動く際、映像の左右を反転させると鏡のようになって直感的に理解しやすい映像となります。コマンドライン引数「--mirror」を付けた以下のコマンドにより実行すると、この動作を実現できます。
python3 pose_camera.py --mirror 
Coral USB Accelerator をお持ちでない方は、以下のコマンドです。
python3 pose_camera_cpu.py --mirror 
なお、PoseNet では人間までの距離を知ることはできません。RealSense というセンサを用いて、人間までの距離も求める方法を 「Raspberry Pi + RealSense + Coral USB Accelerator + PoseNet で深度情報と姿勢情報を表示する」に記しました。RealSense をお持ちでない方も読み物としてお楽しみください。

また、PoseNet の動作原理を知りたいという方は、別サイト内の 「姿勢推定を行うPoseNetをWindowsなどのPCで実行する」というページの末尾にに解説を記しましたので興味のある方はご覧ください。

6. おわりに

Raspberry Pi + Coral USB Accelerator + TensorFlow Lite で物体検出を試してみました。Google により提案された MobileNet という高速なネットワークが、Coral USB Accelerator によりさらに高速に実行できることを体験できました。

ディープラーニングがより普及するには、このように計算能力が高くないデバイスにも計算が高速に実行ができる仕組みが重要になると思われます。

2019年12月3日火曜日

Raspberry Pi で YOLO v3-Tiny / YOLO v3 による物体検出を試してみよう

以下は、古くなったのでサポートを停止した情報です。代替ページとして「Raspberry Pi 5 でリアルタイムな姿勢推定と物体検出」をお勧めします。

1. 物体検出とは何か

本ページでは、Rapsberry Pi で「物体検出」を行う方法を紹介します。「物体検出」とは何かを知るには、下図の画像を見るのがわかりやすくて良いでしょう。


机の上にキーボード、カッター、カップ、マウスが置かれており、その写真に物体検出を適用した結果、物体の位置、大きさ、種類が表示されています。 図ではわかりにくいですが、検出された物体にそれぞれキーボード、ナイフ、カップ、マウスという名称が英語で記されています。

なお、「カッター」が「ナイフ」と検出されている理由は後に解説しますが、一言で言えば「学習データにカッターが含まれていないから」です。

物体検出には様々な方法がありますが、本ページで用いる物体検出は、本書で紹介した CNN (畳み込みニューラルネットワーク) の技術が使われたものです。
しかし、下図に示したように通常のCNNと物体検出では大きく異なる点があります。


通常のCNNでは、上図(A)のように画像中に一つの対象が記されており、その画像が属するクラス(「2」や「カップ」と言った分類先)が出力されます。

一方、物体検出では上図(B)のように、一枚の画像中に複数の物体が存在することがあり得ます。そして、それぞれの物体のクラスだけではなく位置や大きさも出力されねばなりません。

2. YOLOとは何か

この物体検出に CNN (畳み込みニューラルネットワーク) の考え方を応用した手法がいくつか提案されており、本ページで紹介するのはそのうちの一つである YOLO です。
YOLO(You Only Look Once、一度だけ見る)は 2016 年に J. Redmon らにより提案された手法です。 オリジナルの論文はこちらから入手できます。

You only look once とは、英語表現 You only live once(一度だけの人生)をもじったものと考えられます。「一度だけ見る」とは、YOLO では一枚の画像に対する認識に CNN の計算を一度だけ実行すれば良いことを示しています。
物体検出に CNN を用いる他の手法では、一枚の画像に対する認識時に何度も CNN の計算を行わねばならなかったことと対比しているのだと思われます。

通常の CNN の出力層ではソフトマックス関数により入力が属するクラスを出力します。詳細は省略しますが、YOLO では出力層に機械学習の回帰の考え方を適用し、物体の位置や大きさに関わる量も出力できるようにします。それにより、物体検出を可能にしているのです。

なお、執筆時点で YOLO にはバージョン 1 からバージョン 3 が存在します。本ページでは YOLO バージョン 3 を実行する方法を紹介します。

バージョンごとに性能が向上されている他に、学習時に用いられたデータが異なるという特徴があります。それにより、認識される物体の種類が異なるのです。
YOLO バージョン 1 ではクラス数 20 の Pascal VOC 2007 といううデータセットが用いられています。20 種類の物体を検出できるということです。その性能を向上させた YOLO バージョン 2 ではImageNet と COCO という 2 つのデータセットを組み合わせてクラス数 9000 の認識が可能な YOLO9000 というネットワークを実装しています。

そして、本ページで用いる用いた YOLO バージョン 3 では COCO というデータセットを用いてクラス数 80 の認識が可能です。80 種類のクラスをこちらでみることができます。

上で見た図で、カッターを「ナイフ」と認識しているのは「カッター」のデータがデータセットに含まれていなかったであると既に述べましたが、それは上のリンクにあるクラス一覧で確認することができます。

なお、これらの「学習済ネットワーク」から出発して新たなデータを学習させる「転移学習」という方法もありますが、本ページでは取り扱いません。

また、通常 YOLO で用いる CNN は、何十個もの畳み込み層と 2 個の全結合層を持ちます。これをそのまま Raspberry Pi の計算能力で実行するのはやや荷が重いといえます。そのため、本ページでは畳み込み層の数を十個程度に減らした YOLO の簡易版である Tiny YOLO の実行方法も紹介します。

Raspberry Pi 3までをお使いの方はこの Tiny YOLO を利用すると良いでしょう。 高速な Raspberry Pi 4 をお使いの方は通常の YOLO もあわせてチャレンジしてみましょう。

また、本ページの続編的なページとして、物体検出の高速化に関連する「Raspberry Pi + Coral USB Accelerator + TensorFlow Lite で物体検出と姿勢推定を試してみよう」もありますので合わせてご覧ください。Coral USB Acceleratorをお持ちでない場合も演習を実行できます。

3. Python3 用の TensorFlow と OpenCV のインストール

さて、YOLO および Tiny YOLO を実行するためには、Python3 用の TensorFlow および OpenCV のインストールが必要です。本書の補足ページの下記ページに従い、Python3 用の TensorFlow および OpenCV をインストールして下さい。 なお、本ページの内容を Anaconda で実行したい方は「本書の演習を Anaconda の Spyder で実行する方法」を参考にしてください。

さて、ここからは以下の流れで解説が進みます。 TensorFlow 1 系に比べて TensorFlow 2 系の解説は簡易的となっておりますのでご了承ください。

1. [TensorFlow 2 系] プログラムのダウンロードから実行まで

TensorFlow 2 系で行うための方法を記します。簡易的な解説となっていますのでご了承ください。

まず、プログラムをダウンロードするには下記のコマンドを実行して下さい。cedrickchee氏のプログラムに筆者が手を加えたファイルがダウンロードされます。TensorFlow 1 系とは別のプログラムを用いていることにもご注意ください。
git clone https://github.com/neuralassembly/tensorflow2-yolo-v3
プログラムのダウンロードが終わったら、下記コマンドを実行し、tensorflow2-yolo-v3 ディレクトリ(フォルダ)内に移動します。
cd tensorflow2-yolo-v3
そして、下記の4つのコマンドを実行し、YOLOv3用の重みをダウンロ―ドし、さらにそれを TensorFlow 用に変換します。前半 2 つが通常の YOLO 用のコマンド、後半 2 つが tiny YOLO 用のコマンドです。
wget https://pjreddie.com/media/files/yolov3.weights -O data/yolov3.weights
python3 convert.py

wget https://pjreddie.com/media/files/yolov3-tiny.weights -O data/yolov3-tiny.weights
python3 convert.py --weights ./data/yolov3-tiny.weights --output ./checkpoints/yolov3-tiny.tf --tiny
Raspberry Pi 4 登場以前の Raspberry Pi 3 などで、コマンド「python3 convert.py」実行時にエラーが出る場合、 「2. [TensorFlow 1 系] プログラムのダウンロードと準備」で解説されているスワップ領域の増加を試してみると良いかもしれません。

次に、静止画に対して物体検出を行うコマンドが下記の 2 つです。1 つ目のコマンドは、通常の YOLO を画像「./data/meme.jpg」に対して適用します。 「./data/meme.jpg」は、「現在のディレクトリ(./)にある data ディレクトリ(data/)にある画像 meme.jpg」という意味です。 同様に、2 つ目のコマンドは、tiny YOLO を画像「./data/street.jpg」に対して適用します。
どちらの場合も、検出結果が描かれた output.jpg というファイルが保存されます。
python3 detect.py --image ./data/meme.jpg

python3 detect.py --weights ./checkpoints/yolov3-tiny.tf --tiny --image ./data/street.jpg
最後に、ウェブカメラから取得した映像への物体検出は以下で行います。1 つ目が通常のYOLO、2 つ目が tiny YOLO 用のコマンドです。どちらも、終了するにはウインドウ上でキーボードの「q」をタイプしてください。
なお、Bullseye 64-bit で、Legacy Camera 有効 + カメラモジュールで使っている場合、カメラモジュールでの認識が可能です。 Bookworm 64-bit の場合カメラモジュールでの認識はできません。USBで接続するウェブカメラが必要です。その場合、detect.py の 57行目の「cap = cv2.VideoCapture(0)」のカッコ内の数字を 0 から 1 に変更する必要があるかもしれません。
python3 detect.py --webcam

python3 detect.py --weights ./checkpoints/yolov3-tiny.tf --tiny --webcam


2. [TensorFlow 1 系] プログラムのダウンロードと準備

ここからは、TensorFlow 1 系用の YOLO バージョン 3 (YOLOv3) のダウンロードと準備を行いましょう。
公式の YOLO は、darknet というライブラリでネットワークを実現しています。 それを別のディープラーニング用ライブラリで実行するためのプログラムを様々な方が公開しています。

ここでは、kcosta42 氏が公開しているプロクラムを用います。 kcosta42 氏のプログラムに、カメラ映像に対する物体検出機能を筆者が追加したプログラムをダウンロードします。 ターミナルを開き、下記のコマンドでプログラムをダウンロードしましょう。
git clone https://github.com/neuralassembly/Tensorflow-YOLOv3
次に、学習済のパラメーター(結合係数)ファイルをダウンロードして TensorFlow 用のファイルに変換します。下記の3つのコマンドを順に一つずつ実行します。
cd Tensorflow-YOLOv3

curl https://pjreddie.com/media/files/yolov3-tiny.weights > ./weights/yolov3-tiny.weights

python3 convert_weights.py --tiny
一つ目のコマンドはディレクトリの移動を、二つ目のコマンドははTiny YOLO用のパラメーターファイル (35MB程度) のダウンロードを表します。
三つ目のコマンドはファイル変換を行います。Pi 3 B+で 1 分 30 秒程度、Pi 4 B で40秒程度の時間がかかります。このときコンソールに大量の WARNING が出ますが、変換は適切に行われますので気にする必要はありません。

Raspberry Pi 4 をお使いの方で Tiny ではない通常の YOLO の実行もしたい方は、引き続き下記の2コマンドを実行してください。
curl https://pjreddie.com/media/files/yolov3.weights > ./weights/yolov3.weights

python3 convert_weights.py
それぞれ YOLO 用のパラメーターファイルのダウンロードと変換を行っています。Pi 4 B で 2 分程度の時間がかかります。
なお、パラメータファイルは250MB程度ありますので、SDカードの容量に注意してください。
なお、ファイルの変換には多くのメモリが必要とされるため、 Pi 3 B+までのRaspberry Piでは途中で強制終了してしまいます。

なお、2019.12末に試したところ、2つめのコマンドで Raspberry Pi 4 でもメモリに関するエラーが出て終了してしまいました(std::bad_alloc)。
これは、この時期にインストールされた tensorflow-1.14.0 に問題があるからのようです。
sudo pip3 install tensorflow==1.13.1
上記のコマンドにより tensorflow 1.13.1 にバージョンを落とすと上の変換コマンド「python3 convert_weights.py」はRaspberry Pi 4 メモリ 8GB 版と 4GB 版とでは問題なく実行でき、「Model Saved at "./weights/model.ckpt" 」と表示されて正常終了します。その場合、「3. プログラムの実行 (静止画の場合)」に進んでください。

なお、Raspberry Pi 4 メモリ 2GB 版ではメモリが足りず tensorflow-1.13.1 にバージョンを落としても「python3 convert_weights.py」コマンドに失敗することがあります。 その場合、SDカードの領域をメモリの一部として使う「スワップ」という領域のサイズを増やす必要があります。スワップ領域のデフォルトのサイズは 100MB であるので、これを 600MB に増やしてみましょう。 下記コマンドにより、スワップ領域のサイズを決めるファイル /etc/dphys-swapfile を管理者権限のテキストエディタで開きます。
sudo mousepad /etc/dphys-swapfile
下記の行がありますので、
CONF_SWAPSIZE=100
この数値 100 を下記のように 600 に変更します。
CONF_SWAPSIZE=600
変更したらテキストエディタでファイルを上書き保存してから、Raspberry Pi を再起動します。すると、スワップ領域の量が 600MB に増えており、変換コマンド「python3 convert_weights.py」が「Model Saved at "./weights/model.ckpt" 」と表示されて正常終了するようになります。
正常終了を確認したら、再び /etc/dphys-swapfile を管理者権限で開き、CONF_SWAPSIZE の値を 100 に戻して構いません。

以上が終わったら物体検出を実行してみましょう。

3. [TensorFlow 1 系] プログラムの実行 (静止画の場合)

まず、静止画に対する物体検出を試してみましょう。プログラムをダウンロードすることでユーザー pi のホームディレクトリに Tensorflow-YOLOv3 というディレクトリ(フォルダ)が出来ていますが、
その中の data ディレクトリ→ imagesディレクトリとたどった中にある person.jpg というファイルに対して物体検出をおこないます。あらかじめ、Raspberry Pi上のファイルマネージャで画像をダブルクリックしてどのような画像か確認しておきましょう。

そして、 Tensorflow-YOLOv3 というディレクトリに移動してからプログラムを実行します。 結合係数の変換からターミナルを閉じていなければそのまま実行してよいのですが、新たにターミナルを起動した場合はあらかじめ
cd Tensorflow-YOLOv3
というコマンドを実行し、ディレクトリを移動してからプログラムを実行します。

Tiny YOLO (YOLOv3-tiny) によりperson.jpgに対して物体検出を行うには下記のコマンドを実行します。
python3 detect.py --tiny image 0.5 0.5 ./data/images/person.jpg
Pi 3 B+で 45秒程度(パラメータファイルからのモデルの構築に36秒、入力から検出結果を得るのに9秒)、Pi 4 B で 24 秒程度(パラメータファイルからのモデルの構築に20秒、入力から検出結果を得るのに4秒)の時間待つと、結果が保存されます。
結果は、Tensorflow-YOLOv3 ディレクトリ内の detections ディレクトリにある image_output.png というファイルに保存されています(ファイル名は毎回固定です)。 下記のようなファイルが保存されているはずです。


犬に対する枠が2重に表示されていたり、馬が sheep と判定されているなど若干問題はありますが、Tinyではない通常の YOLO を用いるとこの問題はどちらも解決されます(その方法は後述します)。
なお、犬に対する枠が2重に表示されている問題は Tiny の範囲で解決できます。実行コマンド中の「0.5 0.5」のうち、一つ目の数字は「同じクラスの物体を示す枠が複数あって重なっているとき、重なりが大きい枠を除去する」という処理に使われます。 この数字を 0 から 1 の範囲で小さくすると(例えば 0.3)、犬の枠は一つになります。すなわち「python3 detect.py --tiny image 0.3 0.5 ./data/images/person.jpg」ですので興味のある方は試してみてください。

ここで、実行コマンドの中の「./data/images/person.jpg」について解説しておきましょう。これは物体検出を行う対象となる画像の位置を指定しています。このとき、下記の記号を覚えておくと便利です。

   .   ユーザーが現在いるディレクトリ
   /   ディレクトリの区切り

この表によると、「./data/images/person.jpg」は「ユーザーが現在いるディレクトリ内にあるdataディレクトリ→imagesディレクトリにあるperson.jpgという画像」という意味になります。 それ以外には下記の記号を覚えておくと良いでしょう。

   ..   ユーザーが現在いるディレクトリの一つ上のディレクトリ

この記号を用いると、例えば「../image.jpg」と書くことで「ユーザーが現在いるディレクトリの一つ上のディレクトリにあるimage.jpgという画像」という意味になります。

ここで学んだ知識を確認するため、別の画像に対しても Tiny YOLO で物体検出を行ってみましょう。本ページの冒頭に示した机の上にキーボード、カッター、カップ、マウスを置いた画像を試してみましょう。下記のコマンドで画像をダウンロードします。
wget https://raw.githubusercontent.com/neuralassembly/raspi/master/desk-image.jpg
ファイルマネージャで Tensorflow-YOLOv3 ディレクトリにダウンロードされた desk-image.jpg の存在を確認し、どんな画像か確認しておきましょう。 そして、下記のコマンドにより物体検出を実行します。
python3 detect.py --tiny image 0.5 0.5 ./desk-image.jpg
先ほど学んだように「./desk-image.jpg」は「現在のディレクトリにある desk-image.jpg という画像ファイル」という意味になるのでしたね。

実行結果は先程と同じく detections ディレクトリの image_output.png として保存されます。以下のような図になっているはずです。


本ページ冒頭の図と異なり、カッターが検出されていません。これは、物体かどうかを判定する基準が厳しいからです。実行コマンド中の「0.5 0.5」のうち二つ目の数字を0.2にすると、基準が緩くなり、カッターがナイフと判定されるようになります (基準は0から1の範囲の数値で定めます)。すなわち「python3 detect.py --tiny image 0.5 0.2 ./desk-image.jpg」です。このコマンドで本ページ冒頭の図と同じものが detections ディレクトリの image_output.png として保存されます。

さて、ここまで Tiny YOLO での物体検出を解説してきました。通常の YOLO で物体検出を行いたい場合は、コマンドから「--tiny」を除いて下記を実行します。Pi 3 B+までではパラメータファイルの変換に失敗するので、実行可能なのは Raspberry Pi 4 以降のみでしたね(メモリ 4GB 版と 2GB版とで動作を確認)。
python3 detect.py image 0.5 0.5 ./data/images/person.jpg
Pi 4 B で 1 分弱(パラメータファイルからのモデルの構築に45秒、入力から検出結果を得るのに8秒)待つと、これまで通り detections ディレクトリの image_output.png として保存されます。
認識率はこちらの通常の YOLO を用いることで格段に上がりますが、そのぶん認識結果を得るまでの時間がかかるようになっています。

4. [TensorFlow 1 系] プログラムの実行 (カメラの映像の場合)

最後に、Raspberry Pi に接続したカメラから得られた映像に対して物体検出を行う方法を紹介します。

カメラは、Raspberry Pi 公式のカメラモジュールおよび USB 接続のウェブカメラのどちらでも構いません。USB 接続のウェブカメラとしてこちらで動作確認したのは ロジクール社の C270 および C920 です。

本ページでは「××社の○○と言うカメラで動くか」という質問や「××社の○○と言うカメラで動くようにして欲しい」という要望には応えることができませんのでご了承ください。

実行方法は、静止画の場合と同様に Tensorflow-YOLOv3 ディレクトリに「cd Tensorflow-YOLOv3」コマンドで移動してから下記を実行します。

Tiny YOLOの場合はこちらです。
python3 detect.py --tiny webcam 0.5 0.5 
利用状況は下図のようになります。Pi 3 B+ では、約1秒に一回くらい映像が更新されましたが、5秒くらいの映像遅れがあるので実用は厳しいところです。
Pi 4 B では、1秒に複数回映像が更新され、2秒くらいの映像遅れがあります。



通常の YOLO の場合はコマンドから「--tiny」を除いた下記のコマンドを実行します。こちらは Raspberry Pi 4 でのみ実行できます(メモリ 4GB 版と 2GB 版とで動作を確認)。 こちらは Tiny YOLO よりも認識率は良いのですが、映像の遅れが25秒程度あるので使いどころは難しいところです。
python3 detect.py webcam 0.5 0.5 


8. まとめ

Raspberry Pi で YOLO v3-Tiny / YOLO v3 による物体検出を試してみました。カメラ映像に対する例を試してみたところ、実用するためには Raspberry Pi 4 + YOLO v3-Tiny くらいの動作速度は最低限欲しいところです。

また、YOLO v3-Tiny は認識精度が低いので、実用するにはなんらかの工夫が必要と思われます。

この物体検出の高速化に関して、「Raspberry Pi + Coral USB Accelerator + TensorFlow Lite で物体検出と姿勢推定を試してみよう」ページを作成しましたので、引き続きご覧ください。Coral USB Acceleratorをお持ちでない場合も演習を実行できます。