パラメトリックモデル(MANO)に基づくジェスチャ姿勢推定---包括的解析

現在、手の姿勢推定には、2017 年にマックス プランク研究所が提案した MANO パラメトリック モデルを使用し、これに基づいて 3 次元座標を返す技術ソリューションが主流ですが、これは MANO が非常に合理的な構造と明確に定義された順ダイナミクスを備えているためです。木から学びましょう。この記事の目的は、MANO に基づく手の姿勢推定のプロセスを紹介することです。データ処理MANO の推論プロセス (論文と一致)手の解剖学的および生物学的特性が含まれますが、これらに限定されません。

1. 手の姿勢推定とは何ですか?

私が手の姿勢推定として理解していることは、
人体の姿勢推定と同じで、手のクローズアップ画像が与えられると、その姿勢 (2D/3D キーポイント) の位置が推定されます (通常 21 )

以下の図は、最も古典的な実装の 1 つです (パラメーター化されたモデルはありません)。

Encoder-Decoder 構造に手のクローズアップ画像を入力し、Decoder が出力した特徴マップから応答が最も大きい位置を選択し、グラウンドトゥルースを含む 2D ランドマークのヒート マップを生成して損失を計算します。目的は、Decoder によって生成された特徴を使用することです。グラフには、手のさまざまな位置での対応する応答があります。つまり、関心のある( PoI ) から関心のある領域 ( RoI )の表現の構築に変化します。ネットワークが特定の点に焦点を当てることから範囲に焦点を当てるように変化することで、モデルの汎化能力と複雑な状況における推定のロバスト性が拡張されます。

この方法は、パラメトリック モデル MANO/SMPL が登場する前は姿勢推定の分野で主流でした。
ここに画像の説明を挿入します

この写真は、2018年にOlha CHERNYTSKAさん(ウクライナ・カトリック大学卒業)の修士論文からのものです[3]

3Dキーポイントの座標は相対座標系で表現されるのが一般的で、手の場合は手首(下図0)/人差し指と手のひらを繋ぐ関節(下図5)を原点として選択するのが一般的です。ローカル座標系 (0, 0, 0 ) 。このアプローチは、 root-relativeとも呼ばれます

ここに画像の説明を挿入します

次の図は、上図のノード 5 を原点として相対的な 3 次元座標で表現したものです。次の図を例として、ノード 5 の座標を (0, 0, 0) にしたいとします。一般的には非常に単純です (擬似コード):

img = cv2.imread("xxx.jpg")  # 1) 读取手部特写图片
img = normalize(img)         # 2) 对图片进行处理(规则化等)
pred_3d = Net(img)           # 3) 送入网络进行预测
pred_3d -= pred_3d[5]        # 4) 将预测结果变为root-relative的方式.

ここに画像の説明を挿入します

赤いボックスはノード 5 で、その座標は (0, 0, 0) です。

2.MANOとは何ですか?

近年、CVPR、ECCV、ICCV に関する手の姿勢推定に関する論文はすべて、多かれ少なかれモデルベース、つまりパラメトリック モデルに基づいたソリューションです。その中でも最も主流のパラメトリックモデルは、2017年にSiggraph AsiaでJavier Romero、Dimitrios Tzionas、Michael J. Blackによって出版された「 Embodied Hands: Modeling and Capturing Hands and Bodies Together」です[1]

この記事もマックス プランク研究所とインダストリアル ライト アンド マジックが共同で提案した「 SMPL: A Skinned Multi-person Linear Model (2015)」に基づいており[2]手のパラメトリック モデルを提案しています。

低解像度オクルージョンノイズに対処するために、
MANO (Hand Model with Articulated and Non-rigid defOrmations) と呼ばれる新しいモデルを
ここに画像の説明を挿入します開発しました[1]

私の個人的な感覚では、ジェスチャー推定の問題は次のとおりです。

  • 自己閉塞: たとえば、下の写真では、中指から小指までが手の甲で塞がれています。
    ここに画像の説明を挿入します

  • 手で物体を掴むことによって引き起こされるオクルージョン:
    ここに画像の説明を挿入します

  • 低解像度: 全体の構成において手が占めるピクセルの割合は非常に小さいため、ジェスチャーを正確に推定することが困難になります。

確かに、全身/半身で見た場合、ジェスチャーは全身に比べて占めるピクセル数が非常に小さいため、動きを区別すること
が困難ですが、MANOモデルは遷移表現​​を追加する(または遷移表現​​を追加する)ことに相当します。画像 -> 3D ポーズの間。経験に基づく強い優先順位により、オクルージョンと低解像度画像を予測できます。
ここに画像の説明を挿入します

Frankmocap リポジトリからの画像[4]

事前情報のない方法、つまりモデルフリーの方法を使用すると、通常、このような状況での姿勢推定効果は失敗します。パラメトリック モデル MANO が作成されて以来、MANO は、握手、不十分な照明、その他のシーンを含む、さまざまな手のポーズをとった 31 人の被験者の手の 1000 回の高解像度 3D スキャンから取得されました。

したがって、過去 18 年間にわたる数多くの手の姿勢分析作業によれば、MANO パラメータ化モデルの使用が合理的かつ正確な手の姿勢を推定する上で重要な役割を果たすことが示されています

なお、手はセグメント化された剛体(多関節物体)であるため、モデリングは依然として困難であり、マックス・プランク研究所は米国アトランタの3dMD社のスキャン装置を使用したが、これには多額の費用がかかると推定されている..., MANOの作り方については、ここでは詳しく説明しませんので、興味のある方は記事のすぐ下に聞いてください。

ここに画像の説明を挿入します

この写真は、中国科学技術大学の Liu Ligang 氏が教えた games102 コースからのものです[5]

では、3D パラメトリック モデルとしての MANO のパラメータは何でしょうか?

  • 778 の頂点と 1538 の面、および 16 のキー ポイント + 5 つの指先ポイントに基づいて
    頂点から取得され、完全なハンド チェーンを形成する、またはフォワードキネマティック ツリーと呼ばれます。
    下の写真はオックスフォード大学の CVPR2019 論文[7]「3D Hand Shape and 「イメージ・イン・ザ・ワイルド」のポーズ
    ここに画像の説明を挿入します

(つまり、図の 16、17、18、19、20 はすべて、所定のルール、コードに従って変形された頂点から取得されます。ノード 9 を例にとると、その 3D 座標は次のように変形されたメッシュ上にあります。頂点が存在する場所を抽出します。ここに画像の説明を挿入します

3. ジェスチャー3D姿勢推定のMANO部分の処理ロジック解析重点

下図に示すように、手のクロップ画像がニューラルネットワークに送信され、MANOが必要とするカメラパラメータ(最初の3つ)、θ(3)を含むMANOが必要とする61個のパラメータの値が予測されます。 -51)、β( 51:61)。 ここで、θ はMANO でポーズを制御するために使用されるパラメータでありβは MANO で形状を制御するために使用されるパラメータです
ここに画像の説明を挿入します

その中でも、ニューラル ネットワークの設計は、入力と出力の構造に従って設計されている限り比較的単純であり、最も古典的な実装ソリューションは、UCB と Max Planck が共同で作成した CVPR2018 論文: HMR です。予測を最適化するための自己回帰法[6]。MANO に必要な 61 個の係数。

  • 入力 (bs, 3, 224, 224) は
    画像処理後に取得されたテンソル (NCHW) です。画像の解像度は必要に応じて調整でき、bs はバッチ サイズです。

  • 出力は (bs, 61)
    で、MANO に必要なパラメータを取得します。これらのパラメータを MANO に入力すると、3 次元姿勢推定結果 (相対座標系における 21 個のキー点の xyz 位置) を取得できます。

3.1 MANOの計算ロジック

下の図は CVPR2020 の「Minimal-Hand」からのもので[8]、2 つの公式を使用して MANO プロセスを簡単に要約しています。
ここに画像の説明を挿入します

  • 1 T ( β , θ ) = T ‾ + B s ( β ) + B p ( θ ) T(\beta, \theta) = \overline{T} + B_s(\beta) + B_p(\theta)T ( b =T+Bs( b )+Bp( θ )
    この式は形状パラメータβ ∈ R 10 \beta \in R^{10}bR1 0とポーズのパラメータθ ∈ R 48 \theta \in R^{48}R4 8が変形され、その変形はB s / p B_{s/p}Bs / p成し遂げる。T ‾ \overline{T}T標準の 3D ハンド メッシュを表します。下の図は MANO のhand_mean T ‾ \overline{T}T:

ご覧のとおり、MANO のT ‾ \overline{T}T手のひらを平らに広げた姿勢で、アニメーションの分野では一般にTポーズと呼ばれています
ここに画像の説明を挿入します

ここに画像の説明を挿入します
ここに画像の説明を挿入します

  • 2 M ( β , θ ) = W ( T ( θ , β ) , θ , β , W , J ( θ ) ) M(\beta, \theta) = \mathbf{W}(T(\theta, \beta )、\シータ、\ベータ、W、J(\シータ))M ( b =W ( T ( θ ,b b J ( θ ) )ステップ①により、変形されたメッシュ
    が得られます:T ( θ , β ) T(\theta, \beta)T ( θ ,β )、ステップ 2 の目的は、スキニング操作 (線形ブレンド スキニング) を実行することです。WWW皮膚の重さJ ( θ ) J(\theta)J ( θ )はノードの位置です
    ここに画像の説明を挿入します

3.2 MANOの実際の計算過程

さて、MANO の基本的な処理を理解したところで本題に戻りますが、この記事の目的は、MANO がカム、形状、姿勢のパラメータをどのように処理して関節の回転 (軸と角度を表す) を取得するかを分析することです。

rot_pose_beta_to_meshここでは、次の関数を分析のコアとして使用します。このrot_pose_beta_to_mesh関数は 3 つの入力パラメーターを受け取り、これらを合わせると、ネットワークによって予測される正確に 61 個のパラメーターになります。

  • 腐る∈ R 3 \in R^{3}R3
    ルートノード (手首 CMC) の回転軸角度。
  • ポーズ∈ R 45 \in R^{45}R4 5
    各指の指先 (TIP 列を除く) と手首、すべてのキー ポイントの軸角度 (15*3=45) を除く、下の図は ECCV2020 BMC からのものです[9]
    ここに画像の説明を挿入します

手のボーンは、灰色の手首(CMC)、黄色のMCP(手のひらと各指の接合部)、緑色のPIP、青色のDIP 、および指先の位置を示すボーンTIPに分かれています。ボーンに「横」という名前が付いているのがわかります…。

  • ベータ∈ R 10 \in R^{10}R1 0
    mano に必要な形状パラメータ
3.2.1 MANO 計算に関係するいくつかの重要なパラメーター
  • kintree_table、parent などのダイナミクスおよび継承関係パラメータ。
    下の図に示すように、parent と kintree_table は一連のジェスチャを形成します。kintree_table には
    ここに画像の説明を挿入します
    指先が含まれていないことに注意してください。(関節数は 16 個、指関節 15 個 + 手首関節 1 個のみ)、これも MANO で定義された構造に準拠しています。つまり、上図には 5 つの点 (4,8,12,16,20) がありません。

  • hands_mean: ここでのhands_meanはmesh_muと同様に
    レストの手の軸角度である必要があり、ネットワークが予測したポーズ(軸角度)を加えて処理するという使い方になります。ここでのポーズには TIP スケルトンが含まれていないことに加えて、手首も含まれていないことに
    注意してください。
    ここに画像の説明を挿入します

  • mesh_mu:下図の[1]式 2 のT (MANO2017 ) ‾ \overline{T}T. それが平均的な形状です。
    ここに画像の説明を挿入します
    式 2 から計算されるT p T_pTpコードのvowned v_{posed}に対応します。vポーズとっ_:
    ここに画像の説明を挿入します

  • mesh_pca: 形状は pca に基づいて形状として最大の 10 次元パラメータを取るため、最大の形状固有値に対応する固有ベクトル ここでの Mesh_pca は、用途に応じて式 4 (MANO2017) の Sn です。
    ここに画像の説明を挿入します
    対応するコード:
    ここに画像の説明を挿入します

  • J_regressor: (SMPL2015) の式 10 に相当し、メッシュ上の頂点 (頂点) をノード (ジョイント) に変えることが目的です
    ここに画像の説明を挿入します

  • root_rot: ルートノードとは手首上の点、つまり下図の0点を指し、相対距離を計算するにはこの方法を使用する必要があると理解しています。
    ここに画像の説明を挿入します

  • posedirs: 以前の分析によると、posedirsポーズのブレンド形状パラメータを表す MANO (2017) の式 3 の Pn です。
    ここに画像の説明を挿入します

  • weights:weights第 3.1 章式 2 M ( β , θ ) = W ( T ( θ , β ) , θ , β , W , J ( θ ) ) M(\beta, \theta) = \mathbf{W}(T( \theta 、\beta)、\theta、\beta、W、J(\theta))M ( b =W ( T ( θ ,b b J ( θ ) )WWW

3.2.2 回転行列の計算 (Rodrigues)

ここでの主な分析はrodrigues関数です。この関数の目的は、軸角度 (axis-angle) を回転行列 (回転行列) に[10]変更することです。次のコードは、回転の単位ノルム軸w ‾ \overline
ここに画像の説明を挿入します
n等しくなります。下図 (SMPL2015) {w} w、R

R = I3 + torch.sin(theta).view(-1, 1, 1) * Sn \
    + (1. - torch.cos(theta).view(-1, 1, 1)) * torch.matmul(Sn, Sn)

SMPL2015の式(1)と同等であり、S(n_)関数は上記に相当しますSkew(V)
ここに画像の説明を挿入します

def rodrigues(r):
    theta = torch.sqrt(torch.sum(torch.pow(r, 2), 1))

    def S(n_):
        ns = torch.split(n_, 1, 1)
        Sn_ = torch.cat([torch.zeros_like(ns[0]), -ns[2], ns[1], ns[2], torch.zeros_like(ns[0]), -ns[0], -ns[1], ns[0],
                         torch.zeros_like(ns[0])], 1)
        Sn_ = Sn_.view(-1, 3, 3)
        return Sn_

    n = r / (theta.view(-1, 1))
    Sn = S(n)

    # R = torch.eye(3).unsqueeze(0) + torch.sin(theta).view(-1, 1, 1)*Sn\
    #        +(1.-torch.cos(theta).view(-1, 1, 1)) * torch.matmul(Sn,Sn)

    I3 = Variable(torch.eye(3).unsqueeze(0).cuda())
	
	# R等于 公式 (1)---SMPL
    R = I3 + torch.sin(theta).view(-1, 1, 1) * Sn \
        + (1. - torch.cos(theta).view(-1, 1, 1)) * torch.matmul(Sn, Sn)

    Sr = S(r)
    theta2 = theta ** 2
    R2 = I3 + (1. - theta2.view(-1, 1, 1) / 6.) * Sr \
         + (.5 - theta2.view(-1, 1, 1) / 24.) * torch.matmul(Sr, Sr)

    idx = np.argwhere((theta < 1e-30).data.cpu().numpy())

    if (idx.size):
        R[idx, :, :] = R2[idx, :, :]

    return R, Sn

3.2.3get_poseweights (poses, bszie)

この関数は、pose_weights形状が[bs, 135]135 = 45 ∗ 3 135 = 45 * 3のプロパティを計算するために使用されます。1 3 5=4 53. 2 つのステップに分かれています
ここに画像の説明を挿入します

  • poses3.2.2 で導入した Rodrigues 関数に最初のフィード ([bs, 16, 3]) を入力します。SMPL2015 によると、その目的は各関節の軸角度を回転行列に変換することです。pose_matrix
    は [15xbs, 3、3]
    ここに画像の説明を挿入します

  • ②pose_matrix から単位行列を引いたもの。 (MANO2017) の式 3の R n ( θ ) − R n ( θ ∗ ) R_n(θ)- R_n(θ^*)として理解されます。R()R(私は ):
    ここに画像の説明を挿入します

ここに画像の説明を挿入します

def get_poseweights(poses, bsize):
    # pose: batch x 24 x 3
    pose_matrix, _ = rodrigues(poses[:, 1:, :].contiguous().view(-1, 3))
    # pose_matrix, _ = rodrigues(poses.view(-1,3))
    pose_matrix = pose_matrix - Variable(torch.from_numpy(
        np.repeat(np.expand_dims(np.eye(3, dtype=np.float32), 0), bsize * (keypoints_num - 1), axis=0)).cuda())
    pose_matrix = pose_matrix.view(bsize, -1)
    return pose_matrix

3.3rot_pose_beta_to_meshコーミング

① 最初のステップは、ポーズv_shapeを計算することです。

⚫ ポーズ: ポーズはネットワークによって予測されますaxis angle+ hand_mean(静止ポーズ)、さらに root_rot (手首の位置。コードでは (0,0,0) として記述されます。これは相対位置であり、root-relative を構築した結果です) . [bs、16、3]

⚫ v_shape: SMPL2015 の式 10 の T に対応します‾ \overline{T}T+ パート B [bs、778、3]
ここに画像の説明を挿入します

対応するコード:
ここに画像の説明を挿入します

② ステップ 2 では、 pose_weightsv_used 、およびJ_ownedを計算します

⚫pose_weightsが渡されます

pose_weights = get_poseweights(poses, batch_size)

計算された。具体的な分析については、get_poseweights3.2.3の機能紹介を参照してください。

⚫ v_posed は <3D Hand Shape and Pose from Images in the wild, CVPR2019> の公式 2 のT ( β , θ ) T(β, θ)T ( b θ )、これは MANO2017 の式 2 でもあります。
ここに画像の説明を挿入します

⚫ J_posed は SMPL2015 の式 10 であり、その機能は頂点をジョイントに変えることです。([bs, 16, 3])
ここに画像の説明を挿入します

ここに画像の説明を挿入します
③ 3 番目のステップは、results_globalT, vを計算することです。
ここに画像の説明を挿入します

J_owned (bs, 16, 3)からJ_owned_split (16, bs, 3) に変更します。つまり、ここでの処理ロジックは、バッチ単位の次元ではなく、指のノードに従って処理されます。

⚫ 同様に、posesから取得したposses_splitposses_splitから取得したangle_matrixがあります。

results_globalはキネマティック ツリーに基づいて計算され、各カレント ノードの関節位置は、親ノードとカレント ノードの回転行列に基づく行列乗算によって取得されます。

results_global は 16 個のフィンガー ノードの 3D xyz でもあります。[(bs ,4, 4), (bs, 4, 4), … , (bs ,4, 4)]. 親ノードは単にその上のノードであることに注意してください。現在のノード
ここに画像の説明を挿入します
、ルートノードではありません~。以前にこの問題を説明した図があります。
ここに画像の説明を挿入します

T は、前の結果とウェイトを乗算して取得されます。ここでのウェイトは、スキンされたブレンド ウェイトWWです。W
ここに画像の説明を挿入します

Vはスキニング処理後の最終的な変形ノード、Jtrはハンドノードの最終的な 3D 位置セットであり、**指先 (TIP ボーン)** の 5 つの関節の位置は V に基づいて取得されることに注意してください。
さらに、最終的に正しい結果を出力するには、(ルート ノードの回転角度に従って)
VJtrを再度回転する必要があります。
ここに画像の説明を挿入します

④ 最後のステップは、標準 MANO モデルから TIP スケルトンの関節位置を見つけることです。
この方法では、手動で MANO モデルの頂点を確認する必要があります。例として親指をとり、頂点番号 745 を示し
ここに画像の説明を挿入します
ます頂点を配置します。 v とノード Jtr の両方が、ルート ノード (手首) の回転行列に従って回転されます。

最後に、ローカル座標系の 3D 座標 (ルート相対) を取得するために、ノード 5 を (0, 0, 0) として取得する処理を実行します。したがって、ノード 5 の位置を V から減算する必要がありますそしてJtr .. _

ここに画像の説明を挿入します

ここに画像の説明を挿入します

4. まとめ

上記の分析に基づいて、最終的に、各手の画像に対応する 21 のキーポイントと、ねじり後の 778 個の頂点すべての 3Dxyz (ルート相対) を取得しました (MANO の手モデルには 778 個の頂点があります)。

ご不明な点がございましたら、お問い合わせください〜

参考文献

[1] MANO2017
[2] SMPL2015
[3] OlgaChernytska/3D-Hand-Pose-Estimation
[4] Frankmocap Facebook
[5] 「幾何モデリングと処理 (GMP)」
[6] HMR CVPR2018
[8] Minimal Hand CVPR2020
[9] ] hand-biomechanical-constraints (ECCV2020)
[10]回転行列: 軸と角度

おすすめ

転載: blog.csdn.net/g11d111/article/details/115539407