ホモグラフィ行列を求める
出典: Wikimura
ホモグラフィについて書かれた資料参照。ホモグラフィ(平面射影)は、空間内の平面と、画像(平面)の投影を調べるということ。
4つ以上の対応点が分かれば求められるらしい。
目次 |
計算方法
「How to compute a homography」および「Computing the plane to plane homography」参照。 2次元の点対応が与えられると、ホモグラフィが定義できる。ホモグラフィは3x3の行列。スケールが関係するので、PとP'は数値的には等しくないが、同じものを表している。
ここで鍵となるのは...9個の未知数を持つ行列についての式を、3つの3次元ベクトルについての式にする方法。 行列を行ベクトルで表示すると、行ベクトルを3つ重ねた9次元のベクトルと、3行9列の行列との積の形になる。
与えられた対応点からホモグラフィ行列を求めるには、行列をベクトルの形にする。
既知なのは二次元の同次座標だけ。大文字で表したものは、小文字のものと同じ点を指す同次座標であるが、スケールは未知。
ここで、スケールが次数を1つ減らす性質を利用すると、同次方程式からスケールについて解くことができる。
Wをh3とpで表すことができる。
最終的に次式で表すことができる。
1つの点対応で同次方程式が2つが立てられるので、8自由度全てを決定するには4つの点対応が必要となる。
もちろん5つ以上の点対応があっても良いが、その場合は固有値分解や特異値分解を使うらしい。
同次方程式の解
ホモグラフィを求める式は同次方程式となった。 同次方程式(Ax = 0)の解は行列Aの性質で変わってくる。 行列が特異値(singular value)を持たなければ、自明な解(x=0)しか持たない。 特異値を持つなら、そうでない解が(どれくらいの自由度かはものによるが)得られるらしい。 「コンピュータビジョン3章:同時系と固有値問題」参照。
「同次連立1次方程式の理論」によると、方程式と未知数の数が一致するとき方程式が解をもつ条件は、係数行列の行列式が0となることとある。
過制約の場合、誤差の絶対値の二乗和が最小となるようにする。同次方程式の場合、以下のようになる。
コンピュータビジョンの本によれば、誤差を最小化するベクトル(求めたいもの)は、対称行列ATAの最小の固有値に対応する固有ベクトルらしい。この時のEの最小値は、最小固有値の2乗となるらしい。
Matlabで計算してみる
解となる固有ベクトルを得るなら、ヤコビ変換、三重対角行列からのQR分解、特異値分解があるらしい。
|x|=1の制約のもと、||Ax||を最小化するベクトルは、ATAの最小固有値に対する固有ベクトルで与えられる。 この固有値は行列AのSVD(固有値分解)から直接得ることができる。
試しにMatlab以下の4点対応についてホモグラフィ行列を求めてみる。
これらの点を同次座標で表現し、行ベクトルにして重ね合わせた行列をP,Qとしている。
- (1,1) - (4,4)
- (-1,1) - (-4,4)
- (-1,-1) - (-4,-4)
- (1,-1) - (4,-4)
Matlabでテスト(固有値を使う場合)
Matlabのeig関数の戻り値Vは固有ベクトル(列)の集まり、Eは対応する固有値の行列となる。 Vのi列目にある固有ベクトルに対する固有値は、Eのi列目にある。
P = [
1 1 1;
-1 1 1;
-1 -1 1;
1 -1 1;
];
Q = [
4 4 1;
-4 4 1;
-4 -4 1;
4 -4 1;
];
z = zeros(1,3);
A = [
P(1,:) z -Q(1,1) * P(1,:);
z P(1,:) -Q(1,2) * P(1,:);
P(2,:) z -Q(2,1) * P(2,:);
z P(2,:) -Q(2,2) * P(2,:);
P(3,:) z -Q(3,1) * P(3,:);
z P(3,:) -Q(3,2) * P(3,:);
P(4,:) z -Q(4,1) * P(4,:);
z P(4,:) -Q(4,2) * P(4,:);
];
[V E] = eig( A'*A)
------------------------------------------------------------------------------------------
V =
-0.6963 0.0000 -0.0000 0.6887 -0.1602 0 -0.0000 -0.0000 -0.1231
0 0 0 0 0 1.0000 0 0 0
0.0000 0.9920 -0.0066 -0.0000 0.0000 0 -0.0000 -0.1259 -0.0000
0 -0.0000 0.0000 0.2265 0.9740 0 0 -0.0000 0
-0.6963 -0.0000 -0.0000 -0.6887 0.1602 0 -0.0000 0.0000 -0.1231
0.0000 -0.0066 -0.9920 0.0000 -0.0000 0 0.1259 -0.0000 0.0000
-0.0000 0.1259 -0.0008 0.0000 -0.0000 0 0.0000 0.9920 0.0000
0.0000 -0.0008 -0.1259 0.0000 -0.0000 0 -0.9920 -0.0000 -0.0000
-0.1741 -0.0000 -0.0000 0.0000 -0.0000 0 -0.0000 -0.0000 0.9847
E =
-0.0000 0 0 0 0 0 0 0 0
0 1.9688 0 0 0 0 0 0 0
0 0 1.9688 0 0 0 0 0 0
0 0 0 4.0000 0 0 0 0 0
0 0 0 0 4.0000 0 0 0 0
0 0 0 0 0 4.0000 0 0 0
0 0 0 0 0 0 130.0312 0 0
0 0 0 0 0 0 0 130.0312 0
0 0 0 0 0 0 0 0 132.0000
これで
を求めると、対応する固有値になる。実は以下のような関係がある。
V' * A' * A * V
ans =
0.0000 -0.0000 -0.0000 0.0000 -0.0000 0 -0.0000 -0.0000 -0.0000
-0.0000 1.9688 -0.0000 0.0000 -0.0000 0 0.0000 -0.0000 -0.0000
-0.0000 0.0000 1.9688 -0.0000 0.0000 0 0.0000 0.0000 0.0000
0.0000 0.0000 -0.0000 4.0000 -0.0000 0 -0.0000 0.0000 -0.0000
0.0000 -0.0000 0.0000 -0.0000 4.0000 0 0.0000 -0.0000 0.0000
0 0 0 0 0 4.0000 0 0 0
-0.0000 0.0000 0.0000 -0.0000 0.0000 0 130.0312 0.0000 -0.0000
-0.0000 -0.0000 0.0000 0.0000 -0.0000 0 0.0000 130.0312 0.0000
-0.0000 0.0000 -0.0000 -0.0000 0.0000 0 -0.0000 0.0000 132.0000
最終的にホモグラフィ行列が求まった。ちゃんとスケーリングになった。
H = [ V(1,1) V(2,1) V(3,1); V(4,1) V(5,1) V(6,1);V(7,1) V(8,1) V(9,1)] / V(9,1);
------------------------------------------------------------------------------------------
H =
4.0000 0 -0.0000
0 4.0000 -0.0000
0.0000 -0.0000 1.0000
Matlabでテスト(特異値分解を使う場合)
「行列の特異値分解」 に、ATAとの固有ベクトルがAの特異値分解から求まることが示されている。
ランクrの行列Aは3つの行列の積に分解できるという。
UとVはそれぞれ左特異ベクトル、右特異ベクトルと呼ぶ。
中央のΣは特異値(Singular value)からなる対角行列となる。
UとVは正規直行ベクトルを列に持つため、以下のような性質がある。
この性質を利用すると、固有値・固有ベクトル分解の形になる。
この関係から、以下のことが言える。
- Vの列ベクトルはA'Aの固有ベクトル
- Uの列ベクトルはAA'の固有ベクトル
先ほどのプログラムに以下を加えてみた。固有値を求める関数を使った時と同じ結果になった。
ただ、固有値を求めるeig関数は固有値が小さい順に固有ベクトルを並べるが、特異値分解をするsvd関数は固有値が大きい順に並べるらしい。そのため、ホモグラフィ行列の計算の仕方が変わってくる。
[U S V] = svd( A);
H_svd = [ V(1,9) V(2,9) V(3,9); V(4,9) V(5,9) V(6,9);V(7,9) V(8,9) V(9,9)] / V(9,9)
------------------------------------------------------------------------------------------
H_svd =
4.0000 0.0000 0.0000
-0.0000 4.0000 0.0000
0.0000 -0.0000 1.0000
Matlabでテスト(まとめ)
P = [
1 1 1;
-1 1 1;
-1 -1 1;
1 -1 1;
];
Q = [
4 4 1;
-4 4 1;
-4 -4 1;
4 -4 1;
];
z = zeros(1,3);
A = [
P(1,:) z -Q(1,1) * P(1,:);
z P(1,:) -Q(1,2) * P(1,:);
P(2,:) z -Q(2,1) * P(2,:);
z P(2,:) -Q(2,2) * P(2,:);
P(3,:) z -Q(3,1) * P(3,:);
z P(3,:) -Q(3,2) * P(3,:);
P(4,:) z -Q(4,1) * P(4,:);
z P(4,:) -Q(4,2) * P(4,:);
];
[V E] = eig( A'*A);
H_eig = [ V(1,1) V(2,1) V(3,1); V(4,1) V(5,1) V(6,1);V(7,1) V(8,1) V(9,1)] / V(9,1)
[U S V] = svd( A);
H_svd = [ V(1,9) V(2,9) V(3,9); V(4,9) V(5,9) V(6,9);V(7,9) V(8,9) V(9,9)] / V(9,9)
------------------------------------------------------------------------------------------
H_eig =
4.0000 0 -0.0000
0 4.0000 -0.0000
0.0000 -0.0000 1.0000
H_svd =
4.0000 0.0000 0.0000
-0.0000 4.0000 0.0000
0.0000 -0.0000 1.0000

