282.ラズパイ無双[21 MediaPipe Pose]
初回:2022/10/26
Raspberry Pi (ラズベリーパイ、通称"ラズパイ")で何か作ってみようという新シリーズです。前回『MediaPipe』のHands をご紹介しましたが、今回は、姿勢推定(Pose)をご紹介したいと思います。
P子「自分で作らないの?」※1
無理です。
しかし、本当にすごい世の中になってきたと思います。『何ができるか』という事ではなく『何をするか』が重要な気がします。しかもこれだけ短期間に低価格で色んなことができるなら、現場のお困りごとを聞いて、翌週にとりあえずの試作品を動かしてみてよければ納品する...なんて事が現実に可能かもしれません。
1.Pose
≪参考1≫
https://google.github.io/mediapipe/solutions/pose
MediaPipe Pose
『ビデオからの人間の姿勢推定は、身体運動の定量化、手話認識、全身ジェスチャー制御など、さまざまなアプリケーションで重要な役割を果たします。 たとえば、ヨガ、ダンス、フィットネス アプリケーションの基礎を形成できます。 また、拡張現実の現実世界の上にデジタル コンテンツと情報を重ねることもできます。』とのことです。
P子「Google翻訳 丸コピーじゃないの?」
『Human pose estimation from video plays a critical role in various applications such as quantifying physical exercises, sign language recognition, and full-body gesture control. For example, it can form the basis for yoga, dance, and fitness applications. It can also enable the overlay of digital content and information on top of the physical world in augmented reality.』が原本です。
これはこれで、ちゃんとした日本語になっているのがすごいです。一昔前の詐欺メールの日本語は、読めば大抵おかしな言葉遣いなので判別できましたが、今ではほとんど見分けがつきません。
P子「Google翻訳のせいじゃないわよ」
まずは、Python のサンプルソースをコピーしてきます。前回の Hands と同様に、静止画やカメラからの動画などのサンプルが混在しているので、単純化してみます。
https://google.github.io/mediapipe/solutions/pose.html#python-solution-api
mp_drawing = mp.solutions.drawing_utils
mp_pose = mp.solutions.pose
# For webcam input:
cap = cv2.VideoCapture(0)
with mp_pose.Pose() as pose:
while True:
_, image = cap.read()
imgRGB = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
results = pose.process(imgRGB)
image = cv2.cvtColor(imgRGB, cv2.COLOR_RGB2BGR)
# height, width, channel = image.shape
if results.pose_landmarks:
# for i, lm in enumerate(results.pose_landmarks.landmark):
# cx, cy = int(lm.x * width), int(lm.y * height)
# cv2.putText(image,str(i),(cx+10,cy+10),
# cv2.FONT_HERSHEY_PLAIN,1,
(255,255,255),1,cv2.LINE_AA)
mp_drawing.draw_landmarks(image,
results.pose_landmarks,
mp_pose.POSE_CONNECTIONS)
cv2.imshow('MediaPipe Pose', image)
k = cv2.waitKey(10)
if k == ord('q') or k == 27: # q または、ESC で終了
break
cap.release()
コメントしている個所は、ランドマークの場所と番号を表示する処理です。
全身のランドマークと番号は、以下のように定義されています。
Fig 4. 33 pose landmarks.
mp.solutions.drawing_styles などを削除しているので、単色で味気ないかもしれませんが、最少サンプルから学習するのが判りやすいのではないかと思っています。
2.plot_landmarks
先ほどの results で、results.pose_world_landmarks の値を mp_drawing.plot_landmarks に渡すことで、3D 領域での表示ができます。内部的には、matplotlib.pyplot を使用しています。
mp_drawing.plot_landmarks(results.pose_world_landmarks,
mp_pose.POSE_CONNECTIONS)
# 静止画になってしまう。
mp_drawing.draw_landmarks(image,results.pose_landmarks,
mp_pose.POSE_CONNECTIONS)
残念な事に、このままでは 3D 表示した所で停止してしまいます。plot_landmarks メソッドの最後に、plt.show() という記述があり、ここで停止します。例えばソースを、plt.pause(0.01) に書き換えれば、停止する事はなくなりますが、ラズパイで動かすには遅すぎました。
ソースは、~/.local/lib/python3.9/site-packages/mediapipe/python/solutions/drawing_utils.py
のを修正しました。
3.segmentation_mask
セグメンテーションマスクは、人物を特定して切り出すことができます。
下記の例では、背景(BG_COLOR)をgray にして人物だけ切り出しています。
if results.segmentation_mask is not None :
condition = np.stack(
(results.segmentation_mask,) * 3, axis=-1) > 0.1
bg_image = np.zeros(image.shape, dtype=np.uint8)
bg_image[:] = BG_COLOR
annotated_image = np.where(condition,
annotated_image, bg_image)
cv2.imshow('MediaPipe Pose', annotated_image)
イメージサイズが一定であれば、背景はループの外に出して定義しておいてもよいでしょう。
4.YouTube からの動画読取
折角なので、何か姿勢推定してみたいと思います。
私は趣味でテニスをしていますので、やはりテニスのフォームを何らかの方法で解析できればうれしいと思っています。そこで、YouTube の動画を姿勢推定してみましょう。
≪参考2≫
https://www.youtube.com/watch?v=AORG9W-41z4
Learn how to hit your backhand like Novak Djokovic... DRILLS Included!
『ノバク・ジョコビッチのようにバックハンドを打つ方法を学びましょう... ドリルが含まれています!』
以前のラズパイ無双で、YouTubeからの読取方法をピックアップしましたので、それを適用してみましょう。
≪参考3≫
https://el.jibun.atmarkit.co.jp/pythonlove/2022/06/2618_videocapture.html#c7
261.ラズパイ無双[8_VideoCapture]
7.YouTubeからの読取
まずは、準備として、pafy と、youtube_dl のインストールを行います。
$ pip3 install pafy youtube_dl
そして、最初のサンプルの、cap = cv2.VideoCapture(0) の箇所を以下のように書き換えてみます。
url = "https://www.youtube.com/watch?v=AORG9W-41z4"
video = pafy.new(url)
best = video.getbest(preftype="mp4")
cap = cv2.VideoCapture(best.url)
実行してみましょう。
261.ラズパイ無双でも述べたように、KeyError: 'dislike_count' が発生するようでしたら、対象箇所のソース(backend_youtube_dl.pyの54行目)をコメントアウトしてから、再実行してみましょう・
File "/home/≪user≫/.local/lib/python3.9/site-packages/pafy/backend_youtube_dl.py", line 54, in _fetch_basic
$ nano ~/.local/lib/python3.9/site-packages/pafy/backend_youtube_dl.py
ちなみに、nano で行番号を表示するには、CTTRL+# を押してから SHIFT + # で行番号を表示できます。
ジョコビッチのフォームが姿勢推定データとともに表示されます。素晴らしいですね。
5.まとめ
今回もご紹介レベルですが、色々とすごいです。HandsやPoseなどの情報から、熟練工の作業手順などをデジタル化してノウハウを共有出来たり、通常の作業を解析して効率的な作業を導き出すなどもできるかもしれません。
個人的には、テニスのフォーム改善などに使えないかと思っています。もちろん学術研究的な取り組みは行われているかもしれませんが、もっと手軽に一般的な環境でも利用できるようになれば良いと思っています。
ほな、さいなら
======= <<注釈>>=======
※1 P子「自分で作らないの?」
P子とは、私があこがれているツンデレPythonの仮想女性の心の声です。