1. ホーム

Python+OpenCV+OpenPoseによる人体姿勢推定(人体キーポイント検出)

2022-02-11 10:13:02

内容紹介

1. 人体姿勢推定入門

2、人体姿勢推定データセット

3. OpenPoseライブラリ

4、実装原理

5、ニューラルネットワークの実装

6. コードの実装


1. 人体姿勢推定入門

人体姿勢推定とは、画像から検出された人体のキーポイントを正しく関連付けることで、人体の姿勢を推定することである。

人間のキーポイントは、通常、以下のように、首、肩、肘、手首、腰、膝、足首など、ある程度の自由度を持つ人体の関節に対応しています。

3次元空間における人体の主要点の相対位置を計算することで、現在の人体の姿勢を推定する。

さらに、人間のキーポイントの位置の時間的な変化を見るための時系列を加えることで、より正確な姿勢検出、ターゲットの将来の瞬間姿勢の推定、電話をしているかどうかの判断など、より抽象的な人間の行動分析が可能となります。

人間の姿勢検出の課題。

  1. 各画像に含まれる人数が不明である。
  2. 人間の相互作用は接触、咬合など非常に複雑であり、個々の手足を一体化すること、すなわち人物のどの部分が存在しているかを判断することは困難である。
  3. 画像中の人数が多いほど計算量が多くなり(計算量は人数と正の相関がある)、リアルタイムでの検出が困難になる。

2. 人物ポーズ推定データセット

人間の姿勢推定は、高品質なデータセットがないため、進歩が遅れています。ここ数年、いくつかの挑戦的なデータセットが公開され、研究者はR&Dの努力を行うようになりました。人間の姿勢推定によく使われるデータセット

3. OpenPoseライブラリ

 OpenPose人体姿勢認識プロジェクトは、カーネギーメロン大学(CMU)で開発された、畳み込みニューラルネットワークと教師あり学習をベースに、Caffeをフレームワークとして用いたオープンソースライブラリです。人間の動きや表情、指の動きなどのポーズ推定を実装することができます。一人用、複数人用に適しており、ロバスト性に優れている。ディープラーニングを用いた世界初のリアルタイムマルチプレイヤー2Dポーズ推定アプリケーションであり、これを用いた事例が続々と登場しています。

その理論的基盤は、CMUのPerceptual Computing LabのZhe CaoによるCVPR 2017論文「Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields 」にあります( http://people.eecs.berkeley.edu/~zhecao/#top ), トーマス・シモン , 魏志琥 , Yaser Sheikh  .

人体姿勢推定技術は、スポーツ・フィットネス、モーションキャプチャ、3Dフィッティング、世論調査など幅広い分野で応用が期待されている。より身近な応用例としては、ぎこちないダンスマシン「Jitterbug」がある。

OpenPoseプロジェクトのGithubリンクです。 https://github.com/CMU-Perceptual-Computing-Lab/openpose

4. 実装の原則

  1. 入力画像に対して畳み込みネットワークによる特徴抽出を行い、特徴マップの集合を得る。その後、2つの分岐に分け、それぞれCNNネットワークによりPart Confidence MapsとPart Affinity Fieldsを抽出する。
  2. これら2つの情報を得た後、グラフ理論におけるBipartite Matchingを用いて、同一人物の関節を繋ぐPart Associationを求め、PAF自体のベクトル的性質により、生成された偶数マッチを正しくし、最終的に人物の全体骨格に統合します
  3. 最後にPAFに基づくMulti-person Parsingを見つける-> Multi-person parsing problemをグラフの問題に変換する-> ハンガリー・アルゴリズム(Hungarian Algorithm)

(ハンガリーアルゴリズムは、部分グラフマッチングの最も一般的なアルゴリズムで、その中核はオーグメントパスを見つけることであり、オーグメントパスを用いて2部グラフの最大一致を求めるアルゴリズムである)。

5. ニューラルネットワークの実装

ステージ1:VGGNetの最初の10層は、入力画像の特徴マップを作成するために使用されます。

ステージ2:2分岐の多段CNNを使用し、最初の分岐で身体の部位(肘、膝など)の位置に対する2次元信頼度マップのセットを予測する。キーポイントである左肩の信頼度マップと親和性マップは下図の通りである。

2番目の枝は、部分親和性の集合に対して、部分親和性の2次元ベクトル場(L)を予測し、部品間の関連性の度合いを符号化するものである。下図は、首と左肩の部分的親和性を示している。

ステージ3:信頼度マップと親和性マップを貪欲推論で解析し、画像内の全員の2次元キーポイントを生成する。

6. 実装コード

import cv2 as cv
import numpy as np
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--input', help='Path to image or video. Skip to capture frames from camera')
parser.add_argument('--thr', default=0.2, type=float, help='Threshold value for pose parts heat map')
parser.add_argument('--width', default=368, type=int, help='Resize input to specific width.')
parser.add_argument('--height', default=368, type=int, help='Resize input to specific height.')

args = parser.parse_args()

BODY_PARTS = { "Nose": 0, "Neck": 1, "RShoulder": 2, "RElbow": 3, "RWrist": 4,
               "LShoulder": 5, "LElbow": 6, "LWrist": 7, "RHip": 8, "RKnee": 9,
               "RAnkle": 10, "LHip": 11, "LKnee": 12, "LAnkle": 13, "REye": 14,
               "LEye": 15, "REar": 16, "LEar": 17, "Background": 18 }

POSE_PAIRS = [ ["Neck", "RShoulder"], ["Neck", "LShoulder"], ["RShoulder", "RElbow& quot;],
               ["RElbow", "RWrist"], ["LShoulder", "LElbow"], ["LElbow", "LWrist"],
               ["Neck", "RHip"], ["RHip", "RKnee"], ["RKnee", "RAnkle"], ["Neck", "LHip"],
               ["LHip", "LKnee"], ["LKnee", "LAnkle"], ["Neck", "Nose"], ["Nose", "REye"],
               ["REye", "REar"], ["Nose", "LEye"], ["LEye", "LEar"]]

inWidth = args.width
inHeight = args.height

net = cv.dnn.readNetFromTensorflow("graph_opt.pb")

cap = cv.VideoCapture(args.input if args.input else 0)

while cv.waitKey(1) < 0:
    hasFrame, frame = cap.read()
    if not hasFrame:
        cv.waitKey()
        break

    frameWidth = frame.shape[1]
    frameHeight = frame.shape[0]
    
    net.setInput(cv.dnn.blobFromImage(frame, 1.0, (inWidth, inHeight), (127.5, 127.5, 127.5), swapRB=True, crop=False))
    out = net.forward()
    out = out[:, :19, :, :] # MobileNet output [1, 57, -1, -1], we only need the first 19 elements

    assert(len(BODY_PARTS) == out.shape[1])

    points = []
    for i in range(len(BODY_PARTS)):
        # Slice heatmap of corresponging body's part.
        heatMap = out[0, i, :, :]

        # Originally, we try to find all the local maximums. to simpli

このプロジェクトの実装のためのコードとモデルは、以下のサイトで公開されています。 https://download.csdn.net/download/m0_38106923/11265524

 キーワードで公開ページをフォローする。 キーポイント検出 をリソースとして使用します。