昨日は、ナチョがウェストブロム戦で見せた奇跡のクリアをopenposeで関節推定してみました。openposeは、関節位置をファイル出力するオプションを用意しているので、jsonで出力して黒背景に関節位置を描画しましたが、その時の解析手順を簡単にまとめておきます。
jsonファイル出力
openpose実行時にwrite_keypoint_jsonを指定します。
$ ./build/examples/openpose/openpose.bin --image_dir ~/data/nacho --write_keypoint_json ~/data/results
ファイルの中身はこんな感じ。pose_keypointsが関節位置で、people以下に検出した人数分が出力されます。
{ "version":1.0, "people":[ { "pose_keypoints":[ 247.668,514.465,0.89905,247.702,527.27,0.87725,236.549,527.306,0.878132,233.307,541.693,0.918291,236.415,544.831,0.709778,258.863,527.235,0.795694,263.66,540.037,0.772329,269.998,554.436,0.744358,246.054,556.101,0.807442,246.055,575.247,0.484067,0,0,0,258.864,556.007,0.797664,260.464,573.657,0.435004,266.807,583.267,0.163514,246.067,511.293,0.856283,249.24,509.715,0.886759,241.254,514.496,0.671889,250.916,514.453,0.700287 ], "face_keypoints":[ ], "hand_left_keypoints":[ ], "hand_right_keypoints":[ ] } ] }
pose_keypointsは(x座標, y座標, 信頼度) x 関節数18で、54個の値が含まれています。それから、関節位置の順番ですが、 openpose/poseParameters.hpp at master · CMU-Perceptual-Computing-Lab/openpose · GitHubに定義された通り(POSE_COCO_BODY_PARTS)になっていて、backgroundは関節位置には含まれませんので注意。さらに、関節位置の結合順序は、POSE_COCO_PAIRSに定義されてます。親切。
pythonでjsonをパース
pythonは3.6.1です。シンプルにやると、
- jsonをload
- 検出された人数分のループ
- 関節の全ペアのループ
- ペアをcv2.lineで描画
たまに関節位置が求められなくて信頼度0.0になっているところだけ注意する必要があります。
import json import numpy as np import cv2 # jsonのロード with open('nacho_0_keypoints.json', 'r') as f: data = json.load(f) # 黒背景画像の用意 img_ = cv2.imread('original.jpg') img = np.zeros_like(img_) # 関節毎の描画色 colors = [(255., 0., 85.), (255., 0., 0.), (255., 85., 0.), (255., 170., 0.), (255., 255., 0.), (170., 255., 0.), (85., 255., 0.), (0., 255., 0.), (0., 255., 85.), (0., 255., 170.), (0., 255., 255.), (0., 170., 255.), (0., 85., 255.), (0., 0., 255.), (255., 0., 170.), (170., 0., 255.), (255., 0., 255.), (85., 0., 255.)] # 検出された全員について for d in data['people']: kpt = np.array(d['pose_keypoints']).reshape((18, 3)) # 関節位置の全ペアについて for p in pairs: pt1 = tuple(list(map(int, kpt[p[0], 0:2]))) c1 = kpt[p[0], 2] pt2 = tuple(list(map(int, kpt[p[1], 0:2]))) c2 = kpt[p[1], 2] # 信頼度0.0の関節は無視 if c1 == 0.0 or c2 == 0.0: continue # 関節の描画 color = tuple(list(map(int, colors[p[0]]))) img = cv2.line(img, pt1, pt2, color, 7) cv2.imshow('nacho', img)
参照
以上のことは、下記を参照しています。