Pythonの外部ライブラリultralyticsを用いれば、YOLOを使ってバウンディングボックスの描画だけでなく、高度な姿勢推定も実現可能です。この記事では、動画ファイルに対してposeモデルを利用した姿勢推定コードの作成と利用方法を分かりやすく紹介します。
こんにちは。wat(@watlablog)です。ここではYOLOv8を使って姿勢推定を行う方法を紹介します!
YOLOによる姿勢推定とは?
YOLO(You Only Look Once)とは、コンピュータを使った物体検出手法です。この手法は従来よりも短時間で何の物体が画像内のどこにあるかを推定できます。YOLOを使った物体検出は以下の記事でPythonによるコードを紹介していますので、是非参考にしてください。
・Python/ultralyticsでYOLOv8をただ使ってみた
YOLOを使うとこんな感じで物体検出ができます。この時、物体を囲っている四角形はバウンディングボックスと呼ばれます。
そして姿勢推定とは、検出した人間の姿勢(ポーズ)を推定する技術です。例えば以下の図はYOLOによる物体検出で人物が検出されていますが、そのバウンディングボックスの中にカラフルな線が入っています。この線は手足、頭等の骨格を示しており姿勢推定結果を意味します。
今回はこのような写真による姿勢推定の他に、動画ファイルに対する姿勢推定を行うPythonコードを紹介します。
Pythonで姿勢推定するコード
動作環境
この記事のコードは以下の環境で動作確認をしました。
Mac | OS | macOS Ventura 13.2.1 |
---|---|---|
CPU | 1.4[GHz] | |
メモリ | 8[GB] |
Python | Python 3.9.6 |
---|---|
PyCharm (IDE) | PyCharm CE 2020.1 |
opencv-python | 4.2.0.76 |
ultralytics | 8.0.154 |
写真から姿勢推定するコード
動画ファイルを扱う前に、単一の写真を使って基本的な使い方を習得しましょう。
サンプルの写真素材
姿勢推定コードを検証するにあたり、人物の写った、しかも色々な姿勢になっている写真を用意するのがなかなか面倒かも知れません。今回はphotoAC(https://www.photo-ac.com/)さんのフリー素材を使います。
全コード
画像関係はOpenCV(cv2)を使い、姿勢推定はultraliticsのYOLOからモデルを呼び出します。.pyファイルと同じ場所にsample.jpgを置いてコードを実行することで姿勢推定の結果がオーバーレイされた画像pose-out.jpgが保存されるプログラムになっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
from ultralytics import YOLO import cv2 def pose_estimation(filename_in, filename_out, model): """ 画像ファイルから人間を検出して姿勢推定する関数 """ # 画像をオープン img = cv2.imread(filename_in, 1) # 画像を表示 cv2.imshow('img', img) cv2.waitKey() cv2.destroyAllWindows() # 物体検出 results = model(img) # バウンディングボックスをオーバーレイ img_annotated = results[0].plot(boxes=False) # 物体検出結果画像を表示 cv2.imshow("pose-estimated", img_annotated) cv2.waitKey() # 画像を保存 cv2.imwrite(filename_out, img_annotated) return if __name__ == '__main__': """ Main """ filename_in = 'sample.jpg' filename_out = 'pose-out.jpg' # モデルを設定 model = YOLO('yolov8s-pose.pt') # 物体検出関数を実行 pose_estimation(filename_in, filename_out, model) |
実行結果
こちらが実行結果です。.plot(boxes=False)とすることでバウンディングボックスを非表示にしています。今回はyolov8s-pose.ptを使いましたが、sの部分を変更することでモデルの精度を変更できます(n→s→m→l→xの順で精度が上がる)。
動画ファイルから姿勢推定するコード
サンプルの動画素材
写真と同様に、フリーの動画素材をvideoAC(https://video-ac.com/)さんからダウンロードして使いました。
全コード
写真に対する姿勢推定と同じ書き方で動画ファイルを使った姿勢推定コードを以下に示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
from ultralytics import YOLO import cv2 def pose_estimation_movie(filename_in, filename_out, model): """ 動画ファイルからリアルタイム物体検出する関数 """ # 動画撮影を開始 cap = cv2.VideoCapture(filename_in) # 動画ファイル保存用の設定 fps = int(cap.get(cv2.CAP_PROP_FPS)) w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') video = cv2.VideoWriter(filename_out, fourcc, fps, (w, h)) while cap.isOpened(): # フレームを抽出する success, frame = cap.read() if success: # 物体検出 results = model(frame, max_det=100) # 推定結果をオーバーレイ img_annotated = results[0].plot(boxes=False) # 物体検出結果画像を表示 cv2.imshow("Movie", img_annotated) # 保存 video.write(img_annotated) # qキーが押されたらウィンドウを閉じる if cv2.waitKey(1) & 0xFF == ord("q"): break else: break # リリース cap.release() cv2.destroyAllWindows() return if __name__ == '__main__': """ Main """ # 動画ファイル filename_in = 'sample.mp4' filename_out = 'pose-movie-out.mp4' # モデルを設定 model = YOLO('yolov8n-pose.pt') # 物体検出関数を実行 pose_estimation_movie(filename_in, filename_out, model) |
実行結果
実行結果はこちら。姿勢推定といったらスポーツだと思いゴルフの動画をダウンロードして使ってみました。物陰に隠れると精度が悪化する様子等も確認できました。
ダンス動画も姿勢推定してみましたが、人が重なると難しいようですね。
カメラからリアルタイムに姿勢推定するコード
こちらはおまけです。以下のコードはカメラからリアルタイムに姿勢推定を行うコードです。qキーを押すまで推定を続け、姿勢推定結果がオーバーレイされた動画を保存します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
from ultralytics import YOLO import cv2 def pose_estimation_camera(model, filename_out): """ カメラからリアルタイム姿勢推定する関数 """ # 動画撮影を開始 cap = cv2.VideoCapture(0) # 動画ファイル保存用の設定 fps = int(cap.get(cv2.CAP_PROP_FPS)) w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') video = cv2.VideoWriter(filename_out, fourcc, fps, (w, h)) while cap.isOpened(): # フレームを抽出する success, frame = cap.read() if success: # 物体検出 results = model(frame) # 推定結果をオーバーレイ img_annotated = results[0].plot(boxes=False) # 物体検出結果画像を表示 cv2.imshow("Movie", img_annotated) # 保存 video.write(img_annotated) # qキーが押されたらウィンドウを閉じる if cv2.waitKey(1) & 0xFF == ord("q"): break else: break # リリース cap.release() cv2.destroyAllWindows() return if __name__ == '__main__': """ Main """ filename_out = 'pose-camera.mp4' # モデルを設定 model = YOLO('yolov8n-pose.pt') # 物体検出関数を実行 pose_estimation_camera(model, filename_out) |
まとめ
この記事ではultraliticsのyolo-poseを使ったPythonによる姿勢推定方法を紹介しました。
写真、動画、カメラ…の場合の姿勢推定コードを紹介しましたが、どれも同じように書くことができました。
今回は使い方のみを取り扱いましたが、次回は姿勢情報を使って何かできないか試してみたいと思います。
既に学習済みのモデルを使うことで誰でも簡単に最先端の技術が使えるのはすごいですね!
Xでも関連情報をつぶやいているので、wat(@watlablog)のフォローをYOLOしくお願いします!