【OpenCV】decomposeProjectionMatrixを使った外部パラメータの導出

透視投影変換行列を内部パラメータと外部パラメータに分解するため、OpenCVのdecomposeProjectionMatrixを使用したのですが、ちょっと使い方にはまったので使い方メモです。

公式ドキュメントを見てみる

decomposeProjectionMatrixの使い方はここに書いてます。

https://docs.opencv.org/3.0-last-rst/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#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には他にもハマりどころが何箇所かあるので、それはこちらにまとめています。

コメント