【内容】
ここ数日、かなり活性化している「Coral - Github」ですが、その中の一つでPoseNetが利用できるようになっていました。
今回は、これを動かしてみました。
【姿勢検出とは】
姿勢推定は、肘、肩、足が画像のどこにあるのか検出できるように、画像中の人物を検出するコンピュータビジョン(技術です。
PoseNetは身体の主要な関節がどこにあるかを推定します。
目、鼻、耳、肩、肘、手首、腰、膝、足首を左右それぞれ検出してくれるようです。
【インストール】
下記コマンドを実行し、リポジトリのクローンを行い、インストールスクリプトを実行します。
EdgeTPUが動く環境であれば、特に新たにインストールされるものはないと思います。
cd ~/
git clone https://github.com/google-coral/project-posenet
cd project-posenet
sudo sh install_requirements.sh
【サンプルプログラムの実行】
とにかく動かしてみます。
python3 simple_pose.py
「couple.jpg」(下記画像)がダウンロードされ、姿勢検出が行われます。
Inference time: 102ms
Pose Score: 0.61855656
right shoulder x=160 y=173 score=1.0
right eye x=199 y=137 score=1.0
left hip x=324 y=179 score=0.2
left ear x=244 y=135 score=1.0
left eye x=224 y=138 score=1.0
left ankle x=316 y=175 score=0.1
left knee x=344 y=86 score=0.8
right ankle x=166 y=307 score=0.0
left elbow x=282 y=255 score=0.6
right knee x=170 y=294 score=0.0
right elbow x=154 y=256 score=0.9
left shoulder x=268 y=168 score=0.8
right wrist x=162 y=299 score=0.6
nose x=210 y=152 score=1.0
right ear x=182 y=129 score=0.8
left wrist x=236 y=333 score=0.8
right hip x=203 y=233 score=0.0
Pose Score: 0.5867945
right shoulder x=362 y=151 score=0.8
right eye x=382 y=127 score=1.0
left hip x=525 y=106 score=0.0
left ear x=457 y=110 score=0.9
left eye x=416 y=128 score=1.0
left ankle x=504 y=178 score=0.0
left knee x=501 y=90 score=0.6
right ankle x=306 y=176 score=0.1
left elbow x=465 y=290 score=0.9
right knee x=350 y=167 score=0.1
right elbow x=328 y=246 score=0.8
left shoulder x=491 y=169 score=0.9
right wrist x=233 y=331 score=0.5
nose x=398 y=145 score=1.0
right ear x=370 y=120 score=0.2
left wrist x=340 y=303 score=0.9
right hip x=361 y=161 score=0.3
102msで推論が完了し、推論した各関節位置が表示されます。
ただ、これだけだとよくわかりませんね…
【カメラキャプチャのサンプル実行】
Webカメラで動画をキャプチャしながら姿勢検出を行います。
python3 pose_camera.py
Loading model: models/posenet_mobilenet_v1_075_481_641_quant_decoder_edgetpu.tflite
INFO: Initialized TensorFlow Lite runtime.
Gstreamer pipeline: v4l2src device=/dev/video0 ! video/x-raw,width=640,height=480,framerate=30/1 ! queue max-size-buffers=1 leaky=downstream ! videoconvert ! videoscale ! video/x-raw,format=RGB,width=640,height=480 ! tee name=t
t. ! queue max-size-buffers=1 leaky=downstream ! appsink name=appsink sync=false emit-signals=true max-buffers=1 drop=true
t. ! queue max-size-buffers=1 leaky=downstream ! videoflip video-direction=horiz ! videoconvert
! rsvgoverlay name=overlay ! videoconvert ! autovideosink
PoseNet: 163.9ms Frame IO: 31.66ms TrueFPS: 0.05 Nposes 0
PoseNet: 136.0ms Frame IO: 22.88ms TrueFPS: 3.82 Nposes 0
PoseNet: 123.3ms Frame IO: 19.96ms TrueFPS: 5.31 Nposes 0
PoseNet: 116.0ms Frame IO: 24.42ms TrueFPS: 5.74 Nposes 0
Warning: gst-core-error-quark: A lot of buffers are being dropped. (13): gstbasesink.c(2834): gst_base_sink_is_too_late (): /GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstGLImageSinkBin:autovideosink0-actual-sink-glimage/GstGLImageSink:sink:
There may be a timestamping problem, or this computer is too slow.
Warning: gst-core-error-quark: A lot of buffers are being dropped. (13): gstbasesink.c(2834): gst_base_sink_is_too_late (): /GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstGLImageSinkBin:autovideosink0-actual-sink-glimage/GstGLImageSink:sink:
There may be a timestamping problem, or this computer is too slow.
PoseNet: 111.8ms Frame IO: 23.93ms TrueFPS: 6.19 Nposes 0
PoseNet: 109.2ms Frame IO: 22.59ms TrueFPS: 6.51 Nposes 0
PoseNet: 109.3ms Frame IO: 21.05ms TrueFPS: 6.62 Nposes 0
PoseNet: 108.1ms Frame IO: 22.61ms TrueFPS: 6.66 Nposes 0
PoseNet: 106.7ms Frame IO: 23.68ms TrueFPS: 6.73 Nposes 0
PoseNet: 105.8ms Frame IO: 22.47ms TrueFPS: 6.81 Nposes 0
Warning: gst-core-error-quark: A lot of buffers are being dropped. (13): gstbasesink.c(2834): gst_base_sink_is_too_late (): /GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstGLImageSinkBin:autovideosink0-actual-sink-glimage/GstGLImageSink:sink:
There may be a timestamping problem, or this computer is too slow.
Warning: gst-core-error-quark: A lot of buffers are being dropped. (13): gstbasesink.c(2834): gst_base_sink_is_too_late (): /GstPipeline:pipeline0/GstAutoVideoSink:autovideosink0/GstGLImageSinkBin:autovideosink0-actual-sink-glimage/GstGLImageSink:sink:
There may be a timestamping problem, or this computer is too slow.
PoseNet: 105.8ms Frame IO: 22.39ms TrueFPS: 6.86 Nposes 0
PoseNet: 106.8ms Frame IO: 21.54ms TrueFPS: 6.89 Nposes 0
PoseNet: 109.0ms Frame IO: 21.84ms TrueFPS: 6.81 Nposes 0
PoseNet: 109.2ms Frame IO: 21.14ms TrueFPS: 6.80 Nposes 0
PoseNet: 110.1ms Frame IO: 21.50ms TrueFPS: 6.73 Nposes 0
PoseNet: 109.5ms Frame IO: 20.89ms TrueFPS: 6.78 Nposes 0
PoseNet: 108.7ms Frame IO: 20.96ms TrueFPS: 6.81 Nposes 0
PoseNet: 109.3ms Frame IO: 20.64ms TrueFPS: 6.80 Nposes 0
100ms強で推論して、7FPS弱出ているようです。
ただし、表示されているワーニングのせいなのか、1秒ごとにしか画面が更新されないのでカクカクして微妙です。
python3 pose_camera.py --mirror
python3 pose_camera.py --mirror --res 480x360
【anonymizer.py】
プライバシーを保護を目的とし、対象者の映像は残さず姿勢のみを推定します。
やってることは背景画像を固定して表示しているだけです。
python3 anonymizer.py
【トラブルシュート】
私の環境ではプログラム実行時に以下のエラーが表示されました。
Traceback (most recent call last):
File "simple_pose.py", line 18, in <module>
from pose_engine import PoseEngine
File "/home/pi/project-posenet/pose_engine.py", line 22, in <module>
'This demo requires Edge TPU version >= 2.11.1'
AssertionError: This demo requires Edge TPU version >= 2.11.1
どうやらEdgeTPUのライブラリが古かったようです。
下記コマンドを実行し、最新バージョンをインストールし直しました。
cd ~/
wget https://dl.google.com/coral/edgetpu_api/edgetpu_api_latest.tar.gz -O edgetpu_api.tar.gz --trust-server-names
rm -Rf edgetpu_api
tar xzf edgetpu_api.tar.gz
cd edgetpu_api
sudo bash ./install.sh
これで動くようになりました。
【最後に】
EdgeTPU + PoseNetでとても簡単に姿勢検出ができるようになりました。
何に使うかはアイデア次第ですが、非常に面白いものが作れそうです。
今回は動かしませんでしたが、付属のプログラム「synthesizer.py」では3人の体で音楽を奏でることができるようです。
これは夢が広がります。
ただし、今回実行したサンプルプログラムのパフォーマンスが悪くてイマイチでした。
さらに、温度警告が表示されるほどCPUを酷使しています。
せっかくEdgeTPUを使っているのに勘弁してほしいところです。
改善の余地はありそうでしたので時間があったら修正してみたいと思います。
それから、同じプログラムをJetson Nanoで動かそうと試みましたがエラーで動きませんでした。
修正するときにはJetson Nanoでも動くようにして、パフォーマンスの比較をしてみようと思います。