透視投影変換行列を内部パラメータと外部パラメータに分解するため、OpenCVのdecomposeProjectionMatrix
を使用したのですが、ちょっと使い方にはまったので使い方メモです。
公式ドキュメントを見てみる
decomposeProjectionMatrix
の使い方はここに書いてます。
この関数の引数や返り値は以下の通りです。
void decomposeProjectionMatrix(InputArray projMatrix, OutputArray cameraMatrix, OutputArray rotMatrix, OutputArray transVect, OutputArray rotMatrixX=noArray(), OutputArray rotMatrixY=noArray(), OutputArray rotMatrixZ=noArray(), OutputArray eulerAngles=noArray() )
各パラメータの役割はこんな感じです。(rotMatrixX
とかは今回触れないので省略してます。)
引数 | 役割 | |
入力 | projMatrix | 透視投影変換行列 |
出力 | cameraMatrix | 内部パラメータ |
rotMatrix | 外部パラメータの回転行列 | |
transVect | カメラ位置の示したベクトル |
はまったところ
この関数の出力であるtransVect
、すなわちカメラ位置を示したベクトルがどの座標系で表現されているのかを確認せずに使ったので、見事にバグを生み出してしまいました。
カメラ位置は世界座標系で求まる
はい、結論から言うと、transVect
は世界座標系でのカメラ位置です。なので、外部パラメータで使用するような並進ベクトル\(\boldsymbol{t}\)を求めるにはtransVect
から導出してやる必要があります。
なお、この変換には外部パラメータへの理解が必要となりますので、わからない人はこの記事をご覧ください。
変換するにはまず、transVect
は4次元ベクトルとして返ってきて扱いづらいため、3次元ベクトルにしてやります。これは、1~3番目の要素を4番目の要素で割ればいいです。
この3次元ベクトルを\(\boldsymbol{X}_w=[X_w, Y_w, Z_w]^T\)と置きます。
ついでに求まった回転行列rotMatrix
を\(\boldsymbol{R}\)と置いておきます。
さらに、この世界座標系で表現されたカメラ位置\(\boldsymbol{X}_w\)は外部パラメータによって変換されるとカメラ座標系の原点の座標\(\boldsymbol{X}_c=[0, 0, 0]\)になるはずです。
すなわちこうなります。
つまり、並進ベクトル\(\boldsymbol{t}\)はこのように求めることができます。
なお、decomposeProjectionMatrix
には他にもハマりどころが何箇所かあるので、それはこちらにまとめています。
コメント