こんにちは。
最近、研究の方でmediapipeというgoogleのMachine Learning Platformを使用するために環境構築をしていました。私は環境構築との相性が抜群に悪いので、数日間ハマってしまいました。
本記事ではその環境構築について一貫した手順をまとめ、最終的に下画像のようなHandTrackingを行います。
mediapipeのインストール方法
windows環境
windows環境であれば、mediapipeはものすごく簡単にセットアップできます(Python環境に限る)(jetson nanoやraspiを除くLinuxやMac OSでも可能?)。Python周りの環境は事前に整っていると仮定しますが、次のコマンドをcommand promptで実行するだけで環境構築が完了します。
pip install mediapipe
サンプルコードは、Kazuhito00さんのサンプル集などが使えます。素晴らしいサンプルをありがとうございます。
楽勝ですね。
Jetson Nanoでの環境構築手順
さて、ここからは本題であるJetson Nanoにおける環境構築について紹介します。JetsonやRaspiのarchitectureは、AMDの中でもaarch64という特殊なものらしく、前述のようにpip install mediapipe
と1行で環境構築することができません。
そのため、1からビルドをしてあげる必要があります。
基本的には公式サイトやこのサイトに従って構築していきますが、色々とハマったので全部を通した手順を本記事にまとめます。
手順1:bazelのインストール
まず、bazelというbuildのためのツールを用意します。この際、バージョンは3.4.1以上である必要があり、aptによるインストールではバージョン指定が不可でした。
mkdir ~/bazel-3.4.1 cd ~/bazel-3.4.1 wget https://github.com/bazelbuild/bazel/releases/download/3.4.1/bazel-3.4.1-dist.zip sudo apt-get install build-essential openjdk-8-jdk python zip unzip unzip bazel-3.4.1-dist.zip env EXTRA_BAZEL_ARGS="--host_javabase=@local_jdk//:jdk" bash ./compile.sh sudo cp output/bazel /usr/local/bin/
手順2:mediapipeのcloneと各ライブラリのinstall
mediapipeの実行には、opencvとffmpegも必要となります。ffmpegはlibopencv-video-devでinstallされます。
この手順の最後には、ビルドの設定ファイルの内容を変更します(aarch64用)。
git clone https://github.com/google/mediapipe.git cd ~/mediapipe sudo apt-get install libopencv-core-dev libopencv-highgui-dev \ libopencv-calib3d-dev libopencv-features2d-dev \ libopencv-imgproc-dev libopencv-video-dev sed -i "s/x86_64-linux-gnu/aarch64-linux-gnu/g" third_party/opencv_linux.BUILD
手順3:OpenCVのセットアップ
シェルスクリプトを実行するだけです。このスクリプトの内容をざっと見てみた感じ、opencvとopencv-contribのソースコードを基にbuildをしていました。
bash ./setup_opencv.sh
手順4:gccとg++のバージョンの変更
後々、bazelによるbuildをするときに、gccとg++のバージョンが8以上でなければ変なエラーが出ます。(こんなやつ:mediapipe/calculators/tensor/image_to_tensor_converter_opencv.cc:106:12: error: could not convert 'tensor' from 'mediapipe::Tensor' to 'absl::lts_2020_09_23::StatusOr<mediapipe::Tensor>')
ということで、gcc --version
とg++ --version
でバージョン確認し、8未満だった場合はこのサイトに従って下記の様に更新していきます。
# インストールとコマンドの設定 sudo apt install gcc-8 g++-8 -y sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 8 sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-8 8 # 設定できているか確認 sudo update-alternatives --config gcc sudo update-alternatives --config g++
手順5:protobuf-compilerの設定
このサイトを参考に最新版のprotocをインストールします。
その際のwgetのURLには、このリポジトリから最新版のaarch64用のzipを引っ張ってきています。
sudo apt install -y protobuf-compiler wget https://github.com/protocolbuffers/protobuf/releases/download/v3.15.6/protoc-3.15.6-linux-aarch_64.zip unzip protoc-3.15.6-linux-aarch_64.zip -d protoc3 sudo mv protoc3/bin/* /usr/local/bin/ sudo mv protoc3/include/* /usr/local/include/ sudo chown [user] /usr/local/bin/protoc sudo chown -R [user] /usr/local/include/google
※ 最初にprotobuf-compilerをapt installしているが、古いバージョンなので実行しなくていいかも。
手順6:build用にコードを編集
aarch64のarchitectureに合わせて、実行不可能な内容をdisableにするなど、build時に使用されるコードを編集していきます。
・~/mediapipe/setup.pyについて、208行目あたりを編集
︙ sys.stderr.write('cannot find required file: %s\n' % source) sys.exit(-1) # protoc_command = [self._protoc, '-I.', '--python_out=.', source] protoc_command = [self._protoc, '-I.', '-I/usr/local/include', '--python_out=.', source] ︙
・OpenCVについて不必要なモジュールとリンカを取り除くらしい(sed~~/BUILD までが1つのコマンド)
cd ~/mediapipe sed -i -e "/\"imgcodecs\"/d;/\"calib3d\"/d;/\"features2d\"/d;/\"highgui\"/d;/\"video\"/d;/\"videoio\"/d" third_party/BUILD sed -i -e "/-ljpeg/d;/-lpng/d;/-ltiff/d;/-lImath/d;/-lIlmImf/d;/-lHalf/d;/-lIex/d;/-lIlmThread/d;/-lrt/d;/-ldc1394/d;/-lavcodec/d;/-lavformat/d;/-lavutil/d;/-lswscale/d;/-lavresample/d" third_party/BUILD
・~/mediapipe/requirements.txtからopencv-pythonなどを削除し、下記の状態にする(numpyのバージョン指定も無し)
absl-py dataclasses numpy protobuf>=3.11.4 six wheel
・~/mediapipe/mediapipe/python/solutions/__init__.pyの14行目あたりから drawing_utilsを削除(aarch64 Linuxではopencv-pythonが使用できないため)
︙ # import mediapipe.python.solutions.drawing_utils import mediapipe.python.solutions.face_mesh import mediapipe.python.solutions.hands import mediapipe.python.solutions.holistic ︙
・~/mediapipe/third_party/BUILDの110行目あたりからcarotene_o4tを無効化(下の2行を追加している)
︙ "WITH_ITT": "OFF", "WITH_JASPER": "OFF", "WITH_WEBP": "OFF", "ENABLE_NEON": "OFF", "WITH_TENGINE": "OFF", ︙
手順6.5:bazelのキャッシュを削除
gccのバージョンを上げる前にこのコードを実行してしまい、本記事を参考にbuildをやり直している場合のみ、この手順を実行してください。
gccのバージョンを変えてから再度setupに挑戦する場合は、こういうエラーが発生します。そのため、一度bazelのキャッシュを削除する必要があると考えられます。その際は下記のようなPATHを探してrm -rf
してあげてください。
# 私の場合、下記の場所にあるキャッシュを削除 ~/.cache/bazel/_bazel_username/hfgdsahgklsdahgfkujasdhfalskd(長い名前のディレクトリ)
bazelのcacheを削除した後に、もう一度python3 setup.py gen_protos && python3 setup.py bdist_wheel
をしたときに、401 authorization的なエラーが出力されました。
これは、githubの自動ログイン用ファイルが邪魔して生じる現象のようです。githubの設定で~/.netrc
ファイルを設定している場合、bdist_wheelのsetupが上手くできませんでした。この場合は、1次的に~/.netrc
をbkpファイルにリネームして、rebootしてからsetup.pyを実行すると正常に動きました。
手順7:mediapipeのsetup.pyを実行
ここまで来たら、ついにmediapipeのbuildします。buildには結構時間がかかります。上手く終了することを願うばかりです。。。
cd ~/mediapipe/ python3 setup.py gen_protos && python3 setup.py bdist_wheel
※うまくいくと下記のファイルができているはず。
~/mediapipe/dist/mediapipe-0.8-cp36-cp36-linux_aarch64.whl
手順8:mediapipeを実行するためのinstallを施行
buildして生成されたwheelファイルを用いてpip installします。私の場合、installした内容は~/.local/lib/python3.6/site-packages/mediapipe
に出力されました。
python3 -m pip install cython python3 -m pip install numpy python3 -m pip install pillow python3 -m pip install ~/mediapipe/dist/mediapipe-0.8-cp36-cp36-linux_aarch64.whl
手順9:mediapipeのPATHを設定する
Python実行時にmediapipeを認識できるようにPYTHONPATHを追加設定します。
そのために、~/.bashrc
の末尾に下記の行を追加します。
export PYTHONPATH=$PYTHONPATH:/home/username/.local/lib/python3.6/site-packages/mediapipe/python
コード編集後はsource ~/.bashrc
で設定を更新しましょう。
手順10:試す!
ここまで来れたら、ちょっとしたバグが発生しても諦めないでください。ゴールは目の前です!
実行するサンプルコードには、Kazuhito00さんのを用いたいと思います。偉大。
cd ~/ git clone https://github.com/Kazuhito00/mediapipe-python-sample cd mediapipe-python-sample
このサンプル集から"sample_hand.py”を用いて、webCameraから画像取得してHandTrackingします。その際webcameraからストリーミングがうまくいかない問題があったので、私はコードの280行目あたりを下記のように書き換える必要がありました。
cap = cv.VideoCapture(cap_device, cv.CAP_V4L2) # 引数にcv.CAP_V4L2を追加
最後に実行して勝利をつかみ取りましょう。
python3 sample_hand.py
実行結果
これはwindows側で撮影した動画です。Jetson Nano側で撮影したのはまだ記録していないのです。。。そのうちすり替えます。
おわりに苦労話
本記事ではpython3 setup.py gen_protos && python3 setup.py bdist_wheel
を用いてbuildをしましたが、他の方法も色々試していました。
例えばbazelによるソースコードからの自力buildを試してみたり、dockerによる環境構築を試したりしたのですが、どれも失敗に終わりました。
bazelの方に関しては、ビルド時にandroid-sdkのbuild-toolsが必要となるのですが、その導入のためにはandroidのemulatorが先に入っている必要があります。それらはcmdline-toolsのsdkmanagerによって導入するのですが、aarch64の特性なのかemulatorが導入可能な項目のリストに無いのです。つまり、bazelを動かす為に必要なbuild-toolsを得るために必要なemulatorが得られないという、連鎖的詰み状態に陥っていました。 aarch64の情報が少なくて呪う。
dockerの方に関しては、build途中で32GBの容量を超過しそうになってフリーズし、最終的にjetsonが起動しなくなりました。。。結果、研究用途で書いていたソースコードにアクセスできなくなり、ちゃんとバックアップを取っていなかった自分を呪う羽目に。。。
これを機にDockerを自分でも使いこなせるよう、勉強しようと決意したのでした。
参考文献
手順毎に参考にしたURLは張っていますが、ここにすべてまとめて置きます。
- mediapipeのgithubレポジトリ:https://github.com/google/mediapipe.git
- 環境構築大参考①:https://google.github.io/mediapipe/getting_started/install#installing-on-debian-and-ubuntu
- 環境構築大参考②:https://github.com/jiuqiant/mediapipe_python_aarch64
- 素晴らしいサンプル集:https://github.com/Kazuhito00/mediapipe-python-sample
- gccとg++のupgrade法:https://0h-n0.github.io/blog/2020/05/07/ubuntu-gcc.html
- protocの最新版のinstall法:https://qiita.com/Sylba2050/items/8ee3228fae50d35ce38d
- protocの最新版の保存元:https://github.com/protocolbuffers/protobuf/releases
- githubの自動ログインファイル:https://qiita.com/azusanakano/items/8dc1d7e384b00239d4d9
issue
- CPU build failed in Linux - Mediapipe docker(Tensorの型変換に関するエラー):https://github.com/homuler/MediaPipeUnityPlugin/issues/89
- Error running hello_world example on Ubuntu 20.04(gccとg++更新時のキャッシュによるエラー):https://github.com/google/mediapipe/issues/1204
- GET returned 401 Unauthorized for rules_python(setup.py時の401 authorization):https://github.com/bazelbuild/bazel/issues/10998
- GStreamer features do not work(sample_hand.py実行時のエラー対処):https://github.com/opencv/opencv/issues/16029