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

## 結論

CPU でなら動いた。速度は 1-0.5fps くらい。最大 10秒くらい遅延する。![mediapipe.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/fbcbbdcd-a326-c3b3-7e29-3abbbc223d5a.jpeg)


Andriod では結構さくさく動くのに比べて、raspberry pi でこの速度なのはちょっと納得いかない。GPU でも何とかしてみたい、

## 機材

raspberry pi4 + 2019-09-26-raspbian-buster-lite.img ベースで開始。カメラは v2 モジュールを使用。

## mediapipe の instrall の説明

インストール方法についての公式ドキュメント
https://github.com/google/mediapipe/blob/master/mediapipe/docs/install.md#installing-on-debian-and-ubuntu

まず bazel がないので、bazel を自力で入れる必要あり。

## bazel を入れる

bazel の説明
https://knowledge.sakura.ad.jp/6174/

bazel のインストールについては以下に説明がある。
https://docs.bazel.build/versions/master/install.html

しかし raspbian ではいずれの方法でもうまくいかない。自力で comple.sh でビルドするしかないようだ。

準備については以下を参考に。
http://www.neko.ne.jp/~freewing/raspberry_pi/raspberry_pi_build_bazel_development_tool/

    $ sudo apt -y install build-essential python zip unzip
    $ sudo apt -y autoremove openjdk-8-jre-headless
    $ sudo apt -y install openjdk-8-jre-headless
    $ sudo apt -y install openjdk-8-jre
    $ sudo apt -y install openjdk-8-jdk

java や javac などのコマンドが実行できるかを確認しておく。

    $ cd
    $ mkdir bazel
    $ cd bazel
    $ wget https://github.com/bazelbuild/bazel/releases/download/1.2.1/bazel-1.2.1-dist.zip
    $ unzip bazel-1.2.1-dist.zip

下記を参考に zram を設定して compile.sh を書き換える。
https://qiita.com/PINTO/items/ecdab78dda6868221aee

これで comple.sh を実行する。

    $ sudo ./compile.sh

これで "Building Bazel from scratch." と表示された状態でしばらく何も進まなくなるが、エラー表示が出なければ正常にビルドが進んでいる(多分)。git clone でソースを持ってきて compile しようとすると、zip を持ってきて compile しろといわれる。また javac にパスが通ってない場合もエラーでとまる。JDK を 11 にしたらビルド中に Please increase MarkStackSizeMax (current value: 2097152) and restart というエラーが出て止まる。つまり、zip をとってきて jdk8 を使って、zram の設定をして、compile.sh を書き変えるなどする必要あり。

MicroSD 上でビルドすると1時間以上かかる。SSD を USB でつないで、その上でビルドしたら早くなるかも?

正常に終われば下記のメッセージがでる。

    Build successful! Binary is here: /home/kani/bazel/output/bazel

bazel をコピーして実行する。

    $ sudo cp output/bazel /usr/bin
    $ bazel

# opencv をインストールする

    $ sudo apt-get install libopencv-core-dev libopencv-highgui-dev \
                       libopencv-calib3d-dev libopencv-features2d-dev \
                       libopencv-imgproc-dev libopencv-video-dev

# mediapipe の hello world をビルドする

ビルドすると tensorflow を取ってくる模様 (インストールされていない場合)。

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

このまま bazel でビルドするとリンカで 

    undefined reference to '__atomic_store_8'

というようなエラーがずらずら出てしまう (pi4 で opencv を使うコードをコンパイルしたときだけ?)。 よくわからないけど、mediapipe/example/desctop/hello_world/BUILD の cc_binary 内に以下を追加したらなおった。

    linkopts = [
        "-latomic"
    ]

これで bazel run する。

    $ cd mediapipe
    $ bazel run --define MEDIAPIPE_DISABLE_GPU=1 mediapipe/examples/desktop/hello_world:hello_world

ビルドに軽く 10 分くらいかかる。正常にビルドと実行ができたら console に Hello World! と 10 回表示される。

# GPU 付きで hello world をビルドする

GPU を使う場合は EGL driver をインストールして、GPU 使用オプション付きでビルドする。

    $ sudo apt-get install mesa-common-dev libegl1-mesa-dev libgles2-mesa-dev
    $ bazel run --sandbox_debug --copt -DMESA_EGL_NO_X11_HEADERS mediapipe/examples/desktop/hello_world:hello_world

特に問題なく run できるようだ。

# Hand Tracking をビルドする

いよいよ Hand Tracking を build してみる。hello world と同様に BUILD を書き換える必要あり。fetch 中に fetch 回りの WARNING が出るようなら、ビルドを中止して clean しないと多分ビルドが成功しない。

Hello World のビルドのときに GPU 用の egl ライブラリをインストールしていないなら、インストールしておく。

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

そのままビルドすると EGL や opencv のライブラリのエラーが出る気がするので、BUILD の cc_binary に下記を追加しておく。

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

build と run については以下(公式)を参考に
https://github.com/google/mediapipe/blob/master/mediapipe/docs/hand_tracking_desktop.md#tensorflow-lite-hand-tracking-demo-with-webcam-cpu

    $ bazel clean --expunge
    $ bazel build -c opt --copt -DMESA_EGL_NO_X11_HEADERS     mediapipe/examples/desktop/hand_tracking:hand_tracking_gpu

これでビルドは通った。hello world を run したあとに hand_tracking を run しょうとすると、エラーが出ることがあるようだ。先に bazel clean しておくと防げるぽい。

というわけで build はできた。実行してみる。

    $ GLOG_logtostderr=1 sudo ./bazel-bin/mediapipe/examples/desktop/hand_tracking/hand_tracking_gpu \
    --calculator_graph_config_file=mediapipe/graphs/hand_tracking/hand_tracking_mobile.pbtxt

エラーが出て実行できない。gpu driver 回りがダメと言われる。ちょっと見ただけでは分からなかったので、とりあえず GPU 版はペンディング。

# Hand Tracking を CPU でビルドする

BUILD の書き換えは多分必要。

    bazel build -c opt --define MEDIAPIPE_DISABLE_GPU=1 \
    mediapipe/examples/desktop/hand_tracking:hand_tracking_cpu

問題なく通った。ビルド時間は 10 分くらい。

    GLOG_logtostderr=1 sudo ./bazel-bin/mediapipe/examples/desktop/hand_tracking/hand_tracking_cpu \
    --calculator_graph_config_file=mediapipe/graphs/hand_tracking/hand_tracking_desktop_live.pbtxt

これで実行できた。カメラにアクセスするために sudo 必要。

![mediapipe2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/4e5bdac1-6e71-b058-6930-4b3d207254d0.jpeg)

固定する位置が悪くて、カメラが上下逆なのはご愛敬。逆さなのが認識に影響しているかも。カメラ v1 と v2 の両方で試したみたところ、v2 のほうが少し速い気がする。手が近い場所にあるより、1-2m くらい離れた場所にあるほうが早く認識されるぽい。手の形が変化することに対しては早く処理できるようだけど、手の位置や角度が変わると、手を探しなおすせいか遅くなる。