907 文字
5 分
【OpenCV】decomposeProjectionMatrixを使って透視投影変換行列を分解する~完全版~

以前こんな記事を書きましたが、OpenCVの透視投影変換行列を分解するdecomposeProjectionMatrixには他にもいろいろと罠があったので、decomposeProjectionMatrixを利用して透視投影変換行列を内部パラメータと外部パラメータに分解するための完全版の使い方をまとめていきます。

まずは単純に分解#

さて、まずは単純にdecomposeProjectionMatrixで透視投影変換行列を分解していきます。

ただ、decomposeProjectionMatrixは内部的にはQR分解を使用して行列分解しているだけなので、これだけではいろいろと問題が残ります。

内部パラメータをスケーリング#

単純に分解しただけでは、正確な内部パラメータは得られるとは限りません。なぜなら、QR分解で得られるのは、”上三角行列”と”正規直行行列”で、上三角行列の右下要素が1になるという制約は入っていないからです。

そのため、入力に使用した透視投影変換行列は定数倍されていたものの場合、上三角行列の右下要素が1ではない値になります。

なので、decomposeProjectionMatrixで得られた内部パラメータの右下の要素で内部パラメータ全体を割ってやる必要があります。そうすることで右下要素が1の内部パラメータを得ることができます。

内部パラメータの焦点距離が負の数になった場合#

前述のとおり、QR分解で得られるのは”上三角行列”と”正規直行行列”でした。すなわち、decomposeProjectionMatrixで得られた内部パラメータの焦点距離の要素が、正の数になるとは限りません。
ですので、焦点距離が正の数になるよう補正する必要があります。

先ほどまでに求めた内部パラメータをK\boldsymbol{K}、回転行列をR\boldsymbol{R}とおきます。さらに透視投影変換行列の1~3列目の部分をP3×3\boldsymbol{P}_{3\times3}とおきます。すると、これらの関係は下のように表すことができます。

P_33=KR

焦点距離が負の数になる場合は、下のように焦点距離が正になるようにできるように、内部パラメータと回転行列を補正します。このようにすると、回転行列を正規直行行列の状態に保ったまま、焦点距離の符号を変えることができます。

このK\boldsymbol{K}'を最終的な内部パラメータ、R\boldsymbol{R}'を最終的な回転行列とします。

なお、K\boldsymbol{K}の1行1列目、2行2列目それぞれの焦点距離の符号が別の場合、そもそも透視投影変換行列の導出が何かおかしい可能性が高いので、そちらを見直した方がいいです。

並進ベクトルの導出#

最後に、R\boldsymbol{R}'を使って下記で説明している方法で外部パラメータの並進ベクトルを導出すれば、内部パラメータ、外部パラメータの導出完了です。

OpenCVは大変便利に使わせてもらっていますが、正直公式のドキュメントの充実度がいまいちな感じなので、この辺の情報も充実してくれたら嬉しいですね。

参考: openMVS/libs/MVS/Camera.cpp at 063e5cd7f1139aceaf882f9f6ae3f0de26c59138 · cdcseacave/openMVS · GitHub