Python入門トップページ


目次

  1. 仮想環境の構築
  2. OpenPose のダウンロード
  3. 写真と動画データの準備
  4. 学習済みモデルのダウンロード
  5. 写真に対する骨格検出
  6. 動画に対する骨格検出

OpenPose で骨格検出をしてみよう

写真に対する骨格検出

OpenPose に含まれる OpenPose_Notebook.ipynb を Juypter Notebook で実行すると,簡単に骨格検出ができるはずです.具体的にはファイル名の部分を書き換えるだけで目的のファイルを解析できます.また COCO または MPI のモデルを指定している箇所があるので,この部分を書き換えるだけで利用する学習モデルを変更できます.

OpenPose のフォルダに移動して Jupyter Notebook を起動します.

(py39openpose) C:\Users\lecture>cd Documents ⏎

(py39openpose) C:\Users\lecture\Documents>cd python ⏎

(py39openpose) C:\Users\lecture\Documents\python>cd OpenPose ⏎

(py39openpose) C:\Users\lecture>jupyter notebook ⏎

OpenPose_Notebook.ipynb を Jupyter Notebook で開いて実行すると,画面上に解析結果が表示されるはずです.しかしながら,ここでは golf フォルダにある golf.png を解析してみます.また,解析結果をファイルに書き出すことも行います.さらに,フォルダの指定は OS の環境によって異なるので,Windows でも macOS でも動作するように若干書き換えてみます.詳細はここを参照してください.

まず必要なパッケージをインポートします.

import os
import cv2
import time
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

次にモデルの指定を行います.このまま実行すると警告が表示されることになります.特に問題にはならないはずですが,警告が表示されないようにするためには 3行目と9行目を if MODE == "COCO":elif MODE == "MPI": のように書き換えます.

MODE = "MPI"

if MODE is "COCO":
    protoFile = "pose/coco/pose_deploy_linevec.prototxt"
    weightsFile = "pose/coco/pose_iter_440000.caffemodel"
    nPoints = 18
    POSE_PAIRS = [ [1,0],[1,2],[1,5],[2,3],[3,4],[5,6],[6,7],[1,8],[8,9],[9,10],[1,11],[11,12],[12,13],[0,14],[0,15],[14,16],[15,17]]

elif MODE is "MPI":
    protoFile = "pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt"
    weightsFile = "pose/mpi/pose_iter_160000.caffemodel"
    nPoints = 15
    POSE_PAIRS = [[0,1], [1,2], [2,3], [3,4], [1,5], [5,6], [6,7], [1,14], [14,8], [8,9], [9,10], [14,11], [11,12], [12,13] ]

解析したい画像ファイルのパスを定義します.具体的には golf フォルダの中にある golf.png ファイルの解析を試みます.

file_path = os.path.sep.join(['golf', 'golf.png'])
frame = cv2.imread(file_path)
frameCopy = np.copy(frame)
frameWidth = frame.shape[1]
frameHeight = frame.shape[0]
threshold = 0.1

モデルをロードして,画像ファイルの解析を行います.

net = cv2.dnn.readNetFromCaffe(protoFile, weightsFile)

inWidth = 368
inHeight = 368
inpBlob = cv2.dnn.blobFromImage(frame, 1.0 / 255, (inWidth, inHeight),
                          (0, 0, 0), swapRB=False, crop=False)

net.setInput(inpBlob)
output = net.forward()
H = output.shape[2]
W = output.shape[3]
print(output.shape)
(1, 44, 46, 46)

解析結果からキーポイントと骨格を画像に重ね合わせて画面に表示するとともに,画像ファイルとして書き出します.なお,35行目と38行目では PNG ファイルを書き出しています.このとき,出力された画像の余白を小さくするために,33行目と36行目で constrained_layout=True という引数を指定していることに注意してください.

# Empty list to store the detected keypoints
points = []

for i in range(nPoints):
    # confidence map of corresponding body's part.
    probMap = output[0, i, :, :]

    # Find global maxima of the probMap.
    minVal, prob, minLoc, point = cv2.minMaxLoc(probMap)

    # Scale the point to fit on the original image
    x = (frameWidth * point[0]) / W
    y = (frameHeight * point[1]) / H

    if prob > threshold :
        cv2.circle(frameCopy, (int(x), int(y)), 8, (0, 255, 255), thickness=-1, lineType=cv2.FILLED)
        cv2.putText(frameCopy, "{}".format(i), (int(x), int(y)), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, lineType=cv2.LINE_AA)
        cv2.circle(frame, (int(x), int(y)), 8, (0, 0, 255), thickness=-1, lineType=cv2.FILLED)

        # Add the point to the list if the probability is greater than the threshold
        points.append((int(x), int(y)))
    else :
        points.append(None)

# Draw Skeleton
for pair in POSE_PAIRS:
    partA = pair[0]
    partB = pair[1]

    if points[partA] and points[partB]:
        cv2.line(frame, points[partA], points[partB], (0, 255, 255), 3)

plt.figure(figsize=[10,10], constrained_layout=True)
plt.imshow(cv2.cvtColor(frameCopy, cv2.COLOR_BGR2RGB))
plt.savefig("golf-keypoints.png", dpi=150, facecolor="white")
plt.figure(figsize=[10,10], constrained_layout=True)
plt.imshow(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
plt.savefig("golf-skelton.png", dpi=150, facecolor="white")
golf.png
openpose
golf-keypoints.png
openpose_keypoints
golf-skelton.png
openpose_skelton

目次に戻る