以前こんな記事を書きましたが、OpenCVの透視投影変換行列を分解するdecomposeProjectionMatrix
には他にもいろいろと罠があったので完全版の使い方をまとめていきます。
まずは単純に分解
され、まずは単純にdecomposeProjectionMatrix
で透視投影変換行列を分解していきます。
ただ、decomposeProjectionMatrix
は内部的にはQR分解を使用して行列分解しているだけなので、これだけではいろいろと問題が残ります。
内部パラメータをスケーリング
さて、単純に分解しただけでは、正確な内部パラメータは得られるとは限りません。なぜなら、QR分解で得られるのは、”上三角行列”と”正規直行行列”で、上三角行列の右下要素が1になるという制約は入っていないからです。
そのため、入力し使用した透視投影変換行列は定数倍されていたものの場合、上三角行列の右下要素が1ではない値になります。
なので、decomposeProjectionMatrix
で得られた内部パラメータの右下の要素で内部パラメータ全体を割ってやる必要があります。そうすることで右下要素が1の内部パラメータを得ることができます。
内部パラメータの焦点距離が負の数になった場合
前述のとおり、QR分解で得られるのは”上三角行列”と”正規直行行列”でした。すなわち、
で得られた内部パラメータの焦点距離の要素が、正の数になるとは限りません。
decomposeProjectionMatrix
ですので、焦点距離が正の数になるよう補正する必要があります。
先ほどまでに求めた内部パラメータを\(\boldsymbol{K}\)、回転行列を\(\boldsymbol{R}\)とおきます。さらに透視投影変換行列の1~3列目の部分を\(\boldsymbol{P}_{3\times3}\)とおきます。すると、これらの関係は下のように表すことができます。
焦点距離が負の数になる場合は、下のように焦点距離が正になるようにできるように、内部パラメータと回転行列を補正します。このようにすると、回転行列を正規直行行列の状態に保ったまま、焦点距離の符号を変えることができます。
この\(\boldsymbol{K}’\)を最終的な内部パラメータ、\(\boldsymbol{R}’\)を最終的な回転行列とします。
なお、\(\boldsymbol{K}\)の1行1列目、2行2列目それぞれの焦点距離の符号が別の場合、そもそも透視投影変換行列の導出が何かおかしい可能性が高いので、そちらを見直した方がいいです。
並進ベクトルの導出
最後に、\(\boldsymbol{R}’\)を使って下記方法で外部パラメータの並進ベクトルを導出すれば、内部パラメータ、外部パラメータの導出完了です。
OpenCVは大変便利に使わせてもらっていますが、正直公式のドキュメントの充実度がいまいちな感じなので、この辺の情報も充実してくれたら嬉しいですね。
参考:
コメント