![]() |
OpenCV 5.0.0
Open Source Computer Vision
|
姿勢計算問題 [189] は、3D-2D点対応からの再投影誤差を最小化する回転と並進を求めることにある。
solvePnP および関連関数は、一連のオブジェクト点とそれらに対応する画像投影、ならびにカメラの内部行列と歪み係数が与えられたときにオブジェクトの姿勢を推定する。下図を参照のこと(より正確には、コンピュータビジョン分野の慣例では、カメラフレームのX軸を右向き、Y軸を下向き、Z軸を前向きとする)。
ワールドフレーム \( \bf{X}_w \) で表された点は、透視投影モデル \( \Pi \) とカメラ内部パラメータ行列 \( \bf{A} \)(文献では \( \bf{K} \) とも表記される)を用いて、画像平面 \( \left[ u, v \right] \) に投影される:
\[ \begin{align*} \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} &= \bf{A} \hspace{0.1em} \Pi \hspace{0.2em} ^{c}\bf{T}_w \begin{bmatrix} X_{w} \\ Y_{w} \\ Z_{w} \\ 1 \end{bmatrix} \\ \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} &= \begin{bmatrix} f_x & 0 & c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix} \begin{bmatrix} r_{11} & r_{12} & r_{13} & t_x \\ r_{21} & r_{22} & r_{23} & t_y \\ r_{31} & r_{32} & r_{33} & t_z \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} X_{w} \\ Y_{w} \\ Z_{w} \\ 1 \end{bmatrix} \end{align*} \]
したがって推定される姿勢は、ワールドフレームで表された3D点をカメラフレームに変換できる回転 (rvec) と並進 (tvec) のベクトルである:
\[ \begin{align*} \begin{bmatrix} X_c \\ Y_c \\ Z_c \\ 1 \end{bmatrix} &= \hspace{0.2em} ^{c}\bf{T}_w \begin{bmatrix} X_{w} \\ Y_{w} \\ Z_{w} \\ 1 \end{bmatrix} \\ \begin{bmatrix} X_c \\ Y_c \\ Z_c \\ 1 \end{bmatrix} &= \begin{bmatrix} r_{11} & r_{12} & r_{13} & t_x \\ r_{21} & r_{22} & r_{23} & t_y \\ r_{31} & r_{32} & r_{33} & t_z \\ 0 & 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} X_{w} \\ Y_{w} \\ Z_{w} \\ 1 \end{bmatrix} \end{align*} \]
取りうる値の一覧については、 cv::SolvePnPMethod enumのドキュメントを参照すること。各手法の詳細を以下に説明する:
cv::solveP3P() はちょうど3組の3D-2D点対応から物体の姿勢を計算する。P3P問題は最大で4個の解を持つ。
cv::solvePnP() は、物体座標系で表された3D点をカメラ座標系へ変換する回転ベクトルと並進ベクトルを、さまざまな手法を用いて返す。
cv::solvePnPGeneric() はあり得るすべての解を取得できる。
現在のところ、複数の解を返せるのは cv::SOLVEPNP_P3P, cv::SOLVEPNP_AP3P, cv::SOLVEPNP_IPPE, cv::SOLVEPNP_IPPE_SQUARE, cv::SOLVEPNP_SQPNP のみである。
cv::solvePnPRansac() は、外れ値に対処するためにRANSAC手法を用いてカメラ座標系に対する物体の姿勢を計算する。
詳しくは [336] を参照のこと。
姿勢の精緻化とは、解の初期推定値から開始し、非線形最小化法を用いて再投影誤差を最小化する回転と並進を推定することである。OpenCVはこの問題に対して cv::solvePnPRefineLM() と cv::solvePnPRefineVVS() を提供している。
cv::solvePnPRefineLM() は非線形のLevenberg-Marquardt最小化法 [185] [81] を用いており、現在の実装では回転の更新を摂動として計算し、SO(3)上では計算しない。
cv::solvePnPRefineVVS() はGauss-Newton非線形最小化法 [189] を用いており、回転部分の更新は指数写像を使って計算する。