QR分解ではありません、RQ分解です。QR分解について書かれているサイトはたくさんありますがRQ分解については少ないようです。しかしこの分野(3Dビジョン)では必要です。
カメラ行列(透視投影行列)Pというのがありました。過去記事にあります。
www.omoshiro-suugaku.com
Pは P=A[R T] のようにできあがっています。このブログではまだ解説していませんが、Aはカメラの内部パラメータ行列と呼ばれ、成分が焦点距離などカメラの内部パラメータからなる上3角行列です。R、Tは上の過去記事(『写真から立体を再現(4)』)にも書いた、座標軸の回転と平行移動に関わる行列(3次元の回転を表すので直交行列)、ベクトルです。P=A[R T] =[AR AT] で AT は列ベクトルなので、行列 P の左側3×3の部分をかけ算の形に分解すればA、Rを求められます。行列を(上3角行列)×(直交行列)の形に分解するのです。手作業で(いや、計算はプログラムで……)これを実行することもできますが結構大変です。何かライブラリはないかな、と探したら scipy にありました! numpy にはないようです(見つからなかった。間違えていたらすみません)。A、Rはどちらも3次の正則な正方行列ですから、ARは正則のはずです。なので、今回の実験では2次、3次の正則行列をRQ分解してみます。
import sys from scipy import linalg import numpy as np A = np.array([[1,2], [4,5]]) print('rank = ', np.linalg.matrix_rank(A), '\n') R, Q = linalg.rq(A) print(R, '\n') print(Q, '\n') print(np.dot(R, Q)) print('\n') A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 0]]) print('rank = ', np.linalg.matrix_rank(A), '\n') R, Q = linalg.rq(A) print(R, '\n') print(Q, '\n') print(np.dot(R, Q)) sys.exit()
実行結果は以下の通り。
rank = 2
[[-0.46852129 -2.18643267]
[ 0. -6.40312424]]
[[ 0.78086881 -0.62469505]
[-0.62469505 -0.78086881]]
[[1. 2.]
[4. 5.]]
rank = 3
[[ -0.42285689 3.02320627 -2.163658 ]
[ 0. 6.0066335 -6.39690191]
[ 0. 0. -10.63014581]]
[[ 0.75174558 -0.65777738 0.0469841 ]
[-0.03535914 0.03093925 0.99889564]
[-0.65850461 -0.75257669 0. ]]
[[1. 2. 3.]
[4. 5. 6.]
[7. 8. 0.]]
ランクも確認。正則なのだから2次ならランク2で、3次ならランク3です。結果を見るとちゃんと(上3角行列)×(直交行列)と分解していることが分かります。分解後、積がもとに戻るかも確認しました。
サイトが少ないということは、RQ分解を使う人は少ないということでしょうか……。OpenCVにも関数(RQDecomp3×3)がありましたが、これを Python から使えるのか分かりませんでした。