【MediaPipe】Raspberry Pi 4で環境構築し、CPU/GPUで動かしてみた(v0.7.5)

2020.07.11

カフェチームの山本です。

今までMediaPipeを動かしてきましたが、使用していた環境はデスクトップPC・クラウドでした。

【MediaPipe】Windowsで環境構築し、Multi Hand Trackingを動かしてみた

【MediaPipe】Amazon EC2のGPUインスタンスでMediaPipeを動かしてみた

今回は、エッジ側でコスト安く処理するために、MediaPipeをシングルボードで動かすことを目的として、MediaPipeをRaspberry Pi 4にインストールする方法を調べました。Hello Worldで動作確認し、Multi Hand Tracking CPU/GPU版をビルドし、動作することを確認しました。

基本的にMediaPipeの公式ガイド通りに進めれば良いのですが、一部プログラムを修正する必要がありました。結果として、CPUを用いた場合は0.3[fps]程度、GPUを用いた場合は1[fps]程度で、Multi Hand Trackingが動作しました。

利用したバージョンはv0.7.5です。

(MediaPipeに関連する記事はこちらにまとめてあります。)

【MediaPipe】投稿記事まとめ

留意事項

本記事はMediaPipe v0.7.5を利用していますが、ちょうど本記事を執筆中(2020/7/9)にMediaPipe v0.7.6が公開されました(https://github.com/google/mediapipe/releases/tag/v0.7.6)。インストールガイドにRasPiでの実行方法が追加されたため、公式の方が良いという方はそちらをご覧ください。

Installation - mediapipe

なお、公式のインストールガイドでは、bazelをRasPi上でビルドしていますが、本記事では別の方が公開されている、ビルド済みのbazelを利用しています。長いビルド時間を短縮できるという点では、本記事の方が良いと思います。しかし、本記事ではエラー箇所を自分で修正していますが、v0.7.6を利用して公式ガイド通りインストールしたらエラーが出ずに実行できると思われるので、公式ガイドの方が良いかもしません。

インストール手順

ステップ0:用意するもの

Raspberry Piで動かすのに必要なものです。今回は以下のものを使用しました。ほとんど秋月電子通商で購入できます(専用の棚がありました)。

  • micro SDカード:32GBのものを利用しました。
  • SDカードライター
  • Raspberry Pi 4本体:メモリ8GBのモデルを利用しました。(http://akizukidenshi.com/catalog/g/gM-15359/
  • 電源:USB Type C 5V 3.8A(http://akizukidenshi.com/catalog/g/gM-14935/
  • USBキーボード・マウス
  • モニタ用ケーブル:micro HDMI - HDMI(http://akizukidenshi.com/catalog/g/gC-15002/
  • モニタ:HDMI入力
  • ネットワーク環境:無線 or 有線。どちらでも問題ありません。
  • カメラ:RasPiカメラモジュール or USBカメラ。どちらでも問題ありません。 (カメラがなくても、動画ファイルの処理は可能です。)

また、以下のものがあると良いと思います。

  • ヒートシンク・ファン:MediaPipeを動かすとかなり熱くなるので、あると安心して作業できます。(なくても、動かすのが短時間であれば問題ないと思います。)
  • アクリルケース:金属部分が他に接触しないので、安心できます。また、ケーブルを挿し込む際など、取り扱いがしやすいので、あると嬉しいです。ヒートシンク・ファンのセットで売ってるものが多いです。

ステップ1:RasPiをセットアップする

ステップ1-1 :Raspberry Pi Imagerをダウンロードする

SDカードにイメージを書き込むには、Raspberry Pi Imagerを利用すると簡単で便利です。以下のリンクから、ダウンロードできます。(他のSDカードライタソフトウェアでも構いません。その場合はRaspberry Piの公式ページから、OSイメージを自分でダウンロードして書き込んでください。)

Raspberry Pi Imager

ステップ1-2:SDカードにイメージを書き込む

Raspberry Pi Imagerを立ち上げると、下のような画面が表示されます

「CHOOSE OS」では「Rasberry Pi OS (32-bit)」(旧Raspbian)を選びます。未確認ですが「Rasberry Pi OS (other)」から選択しても問題ないと思います。

「CHOOSE SD CARD」で書き込みたいSDカードのドライブを選択します。中身が上書きされて消えてしまうので、間違ったドライブを選択していないようご注意ください。

ステップ1-3:Rasberry Pi OSをセットアップする

SDカードをRasPiに挿し、ディスプレイ・キーボード・マウスを接続します。立ち上がったら、指示にしたがって、Raspberry Pi OS(Raspbian)をセットアップしてください。

セットアップが終わったら、ターミナルを開き、以下のコマンドで更新しておきます。

sudo apt update
sudo apt upgrade -y
sudo reboot

ステップ2:MediaPipe をインストールする

公式ガイドにしたがってインストールしていきます。

Installation

ステップ2-1:MediaPipeのリポジトリをクローンする

ターミナルを開いて、以下のコマンドを実行します。

cd ~
git clone https://github.com/google/mediapipe.git

ステップ2-2:OpenCVとFFmpegをインストールする

今回は、インストールガイドのOption 2を利用しました。(下のコマンドはcloneしたMediaPipeのフォルダで実行してください)

cd ~/mediapipe
chmod +x setup_opencv.sh
./setup_opencv.sh

数十分かかるので、次のステップを並行して進めます。

ステップ2-3:bazelをインストールする

今回は、本記事の冒頭で述べたように、こちらで公開されている、すでにビルド済みのバイナリファイルを利用させていただきました。バージョンは2.0.0を利用しました(0.26.0だと、Hello Worldをビルドするときにエラーで止まりました)。必要なjdk8をインストールし、cloneしたリポジトリに含まれるbazelインストール用のスクリプトを実行します。

sudo apt-get install -y openjdk-8-jdk

cd ~
git clone https://github.com/PINTO0309/Bazel_bin.git
cd Bazel_bin/2.0.0/Raspbian_Debian_Buster_armhf/openjdk-8-jdk/
./install.sh
# output to /usr/local/bin/bazel

/usr/local/binにbazelというファイルが追加されます。以下のコマンドを実行して、bazelのメニューが表示されればOKです。

/usr/local/bin/bazel

注:公式ガイドでは、bazelをRasPi上でビルドするように書かれています。未確認ですが、こちらの方法でも問題ないと思います。ただし、RasPiでビルドするので時間がかかります(別の作業でビルドしたとき数時間かかりました)。

ステップ2-4:GPU用のEGLドライバをインストールする

以下のコマンドを実行してインストールします。GPUでMediaPipeを動かすために必要です。

sudo apt-get install mesa-common-dev libegl1-mesa-dev libgles2-mesa-dev -y

Hello Worldで動作確認

そのままビルドしようとすると以下のようなエラーが発生します。

undefined reference to '__atomic_store_8'

こちらの記事で書かれているように、mediapipe/example/desktop/hello_world/BUILDのcc_binaryに以下を追加します。

linkopts = [
    "-latomic"
]

修正したら、MediaPipeのHello Worldを動かします。

# cd ~/mediapipe
export GLOG_logtostderr=1

bazel run --copt -DMESA_EGL_NO_X11_HEADERS --copt -DEGL_NO_X11 \
    mediapipe/examples/desktop/hello_world:hello_world

bazelのビルド後(数十分かかります)、以下のように「Hello World!」が10回表示がされればOKです。

I20200629 11:55:45.702250 28131 hello_world.cc:56] Hello World!
I20200629 11:55:45.702352 28131 hello_world.cc:56] Hello World!
I20200629 11:55:45.702378 28131 hello_world.cc:56] Hello World!
I20200629 11:55:45.702397 28131 hello_world.cc:56] Hello World!
I20200629 11:55:45.702419 28131 hello_world.cc:56] Hello World!
I20200629 11:55:45.702440 28131 hello_world.cc:56] Hello World!
I20200629 11:55:45.702461 28131 hello_world.cc:56] Hello World!
I20200629 11:55:45.702484 28131 hello_world.cc:56] Hello World!
I20200629 11:55:45.702507 28131 hello_world.cc:56] Hello World!
I20200629 11:55:45.702527 28131 hello_world.cc:56] Hello World!

Multi Hand Trackingを動かす

Multi Hand Trackingを実行する(エラーver)

先程と同じように、mediapipe/examples/desktop/multi_hand_tracking/BUILDのcc_binaryに以下を追加します。

linkopts = [
    "-latomic",
    "-lopencv_core",
    "-lopencv_highgui",
    "-lopencv_imgproc",
    "-lopencv_videoio"
],

カメラを接続して実行します。カメラがない場合は、以下のように実行オプションを追加してください。

bazel-bin/mediapipe/examples/desktop/multi_hand_tracking/multi_hand_tracking_gpu \
  --calculator_graph_config_file=mediapipe/graphs/hand_tracking/multi_hand_tracking_desktop_live.pbtxt \
  --input_video_path="video.mp4" \
  --output_video_path="video_gpu.mp4"

CPU版は以下のコマンドでビルドできます。

# cd ~/mediapipe

bazel build -c opt --define MEDIAPIPE_DISABLE_GPU=1 \
  mediapipe/examples/desktop/multi_hand_tracking:multi_hand_tracking_gpu

export GLOG_logtostderr=1
bazel-bin/mediapipe/examples/desktop/multi_hand_tracking/multi_hand_tracking_gpu \
  --calculator_graph_config_file=mediapipe/graphs/hand_tracking/multi_hand_tracking_desktop_live.pbtxt

GPU版は以下のコマンドでビルドできます。

# cd ~/mediapipe

bazel build -c opt --copt -DMESA_EGL_NO_X11_HEADERS --copt -DEGL_NO_X11 \
  mediapipe/examples/desktop/multi_hand_tracking:multi_hand_tracking_gpu

export GLOG_logtostderr=1
bazel-bin/mediapipe/examples/desktop/multi_hand_tracking/multi_hand_tracking_gpu \
  --calculator_graph_config_file=mediapipe/graphs/hand_tracking/multi_hand_tracking_desktop_live.pbtxt

どちらもビルドは通りますが、どちらも以下のエラーになってしまいます。

Packet timestamp mismatch on a calculator receiving from stream "input_video". Current minimum expected timestamp is 4294967296 but received 4294967295. Are you using a custom InputStreamHandeler? Note that some InputStreamhandle allow timestamps that are not strictly monotonically increasing. See for example the ImmediateInputStreamHandler class comment.
*4
corrupted size vs. prev_size

プログラムを修正する

調べてみると、こちらの記事で修正方法を解説されていました。mediapipe/examples/pi/demo_run_graph_main.ccを、以下のリンクのものに置き換えます。

https://github.com/NobuoTsukamoto/mediapipe/blob/master/mediapipe/examples/pi/demo_run_graph_main.cc

もし、バージョンの違いなどで動かなかった場合は、以下のリンクの差分を参考に、mediapipe/examples/pi/demo_run_graph_main.ccを修正します。

https://github.com/NobuoTsukamoto/mediapipe/commits/master/mediapipe/examples/pi/demo_run_graph_main.cc

Multi Hand Trackingを実行する(成功ver)

上のビルドコマンドを再度実行し、バイナリを実行します。

CPUで実行している様子は以下の通りでした。処理速度は0.3[fps]程度のようです。

GPUは以下の通りでした。処理速度は1[fps]程度のようです。

まとめ

今回は、MediaPipe v0.7.5をRasPiにインストールし、Multi Hand Trackingを動かしました。処理速度はGPUを利用して1[fps]程度でした。そのままカフェなどで利用するには、少しパワー不足の印象です。別のFace Detectionなどの軽いモデルであれば、もう少し早く動くはずなので、実環境でも利用できるかもしれません。

参考にさせていただいたページ

PINTO0309/Bazel_bin

Raspberry pi4 で mediapipe の hand_tracking を動かす (cpuなら動いた) - Qiita

MediaPipeでEdge TPU

補足

処理速度を上げるには、以下の方法が利用できそうです。参考となるリンクを貼っておきます。

モデルを量子化したものに変更する

利用するモデルを量子化によって軽量化したものに変更することで処理速度を上げられるかもしれません。ただし、Calculatorも変更する必要があるような気がします。

Raspberry Pi4 単体で TensorFlow Lite はどれくらいの速度で動く? - Qiita

RasPi4 + EdgeTPU USB Acceleratorで動かす

MediaPipeでEdge TPU

NobuoTsukamoto/mediapipe

デバイスを変える