OpenPose と 3D再構成 – Part 3: 3D再構成

OpenPose で人の動きを取得し3D再構成するシリーズの第3回です。Part 1 で OpenPose を導入して2Dキーポイントを取得し、Part 2 でカメラを校正して投影行列を求めました。今回はいよいよ、複数カメラの2Dキーポイントを3Dに復元します。Part 1・2 を視聴済みである前提で進めます。

扱うのは次の3点です。

  1. DLT(Direct Linear Transform/三角測量)による3D再構成
  2. 再構成データのフィルタリング
  3. 再投影誤差の最小化による最適化

1. DLT(Direct Linear Transform)による三角測量

基本は、複数の投影線(ray)が交わる点を求めることです。1台のカメラでは、2Dキーポイントとそのカメラの投影行列から3D空間へ伸びる直線は引けますが、その線上のどこに実点があるかは分かりません。別角度のカメラをもう1台加えると、2本の直線が交わる点が3D点です。これが三角測量です。

2台のカメラの像面と投影線が3D点で交わる図
2視点で3D点を三角測量。図の出典: O. H. Maghsoudi (2019)(動画内の表示に準拠)。

実際には2本の線はぴったり交わらず、わずかな隙間ができるので、その中点を推定します。数式では 2D = 内部パラメータ × 外部パラメータ × 3D投影行列 = 内部 × 外部)。これを DLT の式に整形し、各カメラについてx・yの2行を全視点ぶん積み上げて大きな行列にし、特異値分解(SVD)で解きます。得られる解が3D点です。

2. OpenPose の信頼度で重み付け

OpenPose は2D座標だけでなく、各キーポイントの信頼度(confidence)も出力します。これをDLTに取り込み、各カメラの式に信頼度を掛けます。すると、推定される中点が信頼度の高いカメラの線側に寄り、不確かな線から離れるため、精度が上がります。以降(SVD)の処理は同じです。

信頼度で重み付けしたDLT: 投影行列L、信頼度を掛けた式、kneeU・kneeV・kneeConfの表
DLTの各行にキーポイントの信頼度を掛ける。表の一部は信頼度0(未検出)。

Python は簡潔です。各カメラの投影行列パラメータと歪み補正済みの (u, v) から行列を組み、SVD を取り、Vh の最終行を最後の要素で正規化すると3D座標が得られます。

PythonのDLT再構成: 投影パラメータと2D点から行列Mを構築し、np.linalg.svd、xyz = Vh[-1,0:-1] / Vh[-1,-1]
DLT再構成: カメラごとの行を積み上げ、SVDし、最後の特異ベクトルから3D点を読む。

OpenPoseのJSONからデータを取り出し、人物を追跡する

OpenPose はフレームごとに JSON を書き出します。MATLAB ではファイルを読み、jsondecode で構造体(struct)にして、ドット記法でキーポイントを取り出せます(自動化も容易)。ただし OpenPose は複数人を検出しますがフレーム間で追跡しないため、人物のIDが入れ替わったり消えたりします。

正しい人物を追うために、簡易トラッカーを使います。最初のフレームで対象を選び、以降の各フレームでは前フレームの姿勢と検出された各人物を比較し、誤差が最小の人物を採用します。最良一致でも誤差が約100 pxを超えたら停止し、対象を選び直します。半自動ですが精度重視です。抽出後は、信頼度とx/y座標を分離し、欠損(0)のキーポイントを補間(線形で十分)し、平滑化します。

3. フィルタリング: 残差分析でカットオフを決める

平滑化には Butterworth フィルタが定番ですが、常に難しいのがカットオフ周波数をいくつにするかです。残差分析(residual analysis)で客観的に決められます。カットオフを範囲でスイープし(例: 1〜10 Hz、0.1刻み)、各点で残差(元信号とフィルタ後のRMS誤差)を計算し、残差 vs カットオフをプロットします。

残差分析のプロット: 残差 vs カットオフ周波数。低カットオフで信号歪み、高カットオフでノイズ通過、最適カットオフ fci
残差分析: 平坦な(ノイズの)尾部をy軸まで延長し、水平線を引いてカーブとの交点から最適カットオフを求める。図の出典: G. M. Moreira (2019)(動画内の表示に準拠)。

カットオフが低すぎると本来の信号まで削り(残差大・「信号の歪み」)、高すぎるとノイズを通します(残差はノイズ床へ平坦化)。平坦な尾部の傾きをy軸まで延長し、そこから水平線を引いてカーブと交わる点が最適カットオフ周波数です。ノイズを除きつつ信号を残す妥協点で、これで実際にフィルタをかけます。

なお動画では、どの段階でフィルタをかけるべきか(OpenPose直後、3D再構成後、など)はまだ検討の余地がある、と率直に述べられています。

4. 最適化: 再投影誤差の最小化

最後は任意の精密化です。最小二乗最適化(SciPy の least_squares)で、再投影誤差を最小化して再構成3Dを精密化します。再構成した3D点を各カメラの投影行列で2Dに再投影し、元のOpenPose 2D点と比較します。その差が誤差で、全カメラで最小化します。ここでも各カメラの誤差を信頼度で重み付けできます。

最適化スライド: least_squares の呼び出しと、観測点と再投影点の再投影誤差の図
SciPy least_squares で再投影誤差を最小化し3Dを精密化。再投影の図の出典: Michele Adduci (2014)(動画内の表示に準拠)。

動画での率直な補足: これは OpenPose の2D点を「正解」として最小化する前提ですが、その2D点自体も推定値です。基準が不完全なら、それに対して誤差を最小化して意味があるのかは一概に言えません。著者の経験でも、うまくいく場合と、かえって崩れる場合があるとのこと。原理的な答えをご存じの方は、ぜひコメントで教えてください、とのことです。

次回

3Dの動きを再構成できたら、シリーズ終盤はバイオメカニクスへ: キネマティクス/キネティクスのシミュレーションです。見逃さないよう、YouTube のチャンネル登録をぜひ。


著者について

Takashi Fukushima — スポーツ・運動科学 × Human Pose Estimation × Computer Vision × XR を横断して研究・開発しています。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール