6

下の図の目標は、点 a1 a2 a3 a4 を対応する点 b1 b2 b3 b4 に変換するホモグラフィ行列 H を計算することです。あれは:

[b1 b2 b3 b4] = H * [a1 a2 a3 a4]

H(3x3) を計算するための最良の方法を提案してください。a1...b4 は、同次座標系 ([a1_x a1_y 1]', ...) で表される 2D の点です。 編集:これらのタイプの問題については、SVDを使用します。そのため、Matlabでこれを簡単に実行できる方法を知りたいです。

編集

Maltlab で svd (H=Q/P) を使用して最初に解決しようとした方法を次に示します。与えられた例の次のコードを検討してください

px=[0 1 1 0];  % a square
py=[1 1 0 0];

qx=[18 18 80 80];    % a random quadrangle
qy=[-20 20 60 -60];
if (DEBUG)
  fill(px,py,'r');
  fill(qx,qy,'r');
end

Q=[qx;qy;ones(size(qx))];
P=[px;py;ones(size(px))];
H=Q/P;
H*P-Q
answer:
   -0.0000         0         0         0         0
  -20.0000   20.0000  -20.0000   20.0000    0.0000
   -0.0000         0         0         0   -0.0000

答えがnull行列になることを期待していますが、そうではありません!...そして、StackOverflowでこの質問をしたのはそのためです。さて、私たちは皆、それが明らかにユークリッド的ではない射影変換であることを知っています. ただし、一般的なケアでは、4 つのポイントのみを使用してこのような行列を計算できるかどうかを知っておくとよいでしょう。

行列計算

4

5 に答える 5

2

cp2tformコントロール ポイントのペアから空間変換を推測する関数を試すことができます。あなたの場合、平行は保持されないため、transformtypeを「射影」に設定する必要があります。詳細はこちら

于 2012-07-30T18:24:16.663 に答える
1

この目的のためにDLTアルゴリズムを使用できます。Peter Kovesiのホームページには、これを行うために使用できるMATLABルーチンがあります。

于 2012-07-30T17:40:34.017 に答える
1

投稿したデータを使用して:

P = [px(:) py(:)];
Q = [qx(:) qy(:)];

変換を計算します。

H = Q/P;

変換を適用します。

Q2 = H*P;

結果を比較します。

err = Q2-Q

出力:

err =
   7.1054e-15   7.1054e-15
  -3.5527e-15  -3.5527e-15
  -1.4211e-14  -2.1316e-14
   1.4211e-14   1.4211e-14

これは、すべての意図と目的でゼロです..


編集:

コメントで指摘したように、上記の方法は 3x3 ホモグラフィ行列を計算しません。与えられた点と同じ数の方程式で連立方程式を単純に解きます。

H * A = B   -->   H = B*inv(A)   -->   H = B/A (mrdivide)

それ以外の場合、MATLAB のイメージ処理ツールボックスには CP2TFORM 関数があります。表示されている画像に適用された例を次に示します。

%# read illustration image
img = imread('http://i.stack.imgur.com/ZvaZK.png');
img = imcomplement(im2bw(img));

%# split into two equal-sized images
imgs{1} = img(:,fix(1:end/2));
imgs{2} = img(:,fix(end/2:end-1));

%# extract the four corner points A and B from both images
C = cell(1,2);
for i=1:2
    %# some processing
    I = imfill(imgs{i}, 'holes');
    I = bwareaopen(imclearborder(I),200);
    I = imfilter(im2double(I), fspecial('gaussian'));

    %# find 4 corners
    C{i} = corner(I, 4);

    %# sort corners in a consistent way (counter-clockwise)
    idx = convhull(C{i}(:,1), C{i}(:,2));
    C{i} = C{i}(idx(1:end-1),:);
end

%# show the two images with the detected corners
figure
for i=1:2
    subplot(1,2,i), imshow(imgs{i})
    line(C{i}(:,1), C{i}(:,2), 'Color','r', 'Marker','*', 'LineStyle','none')
    text(C{i}(:,1), C{i}(:,2), num2str((1:4)'), 'Color','r', ...
        'FontSize',18, 'Horiz','left', 'Vert','bottom')
end

コーナーが検出されたので、空間変換を取得できます。

%# two sets of points
[A,B] = deal(C{:});

%# infer projective transformation using CP2TFORM
T = cp2tform(A, B, 'projective');

%# 3x3 Homography matrix
H = T.tdata.T;
Hinv = T.tdata.Tinv;

%# align points in A into B
X = tformfwd(T, A(:,1), A(:,2));

%# show result of transformation
line(X([1:end 1],1), X([1:end 1],2), 'Color','g', 'LineWidth',2)

結果:

>> H = T.tdata.T
H =
      0.74311    -0.055998    0.0062438
      0.44989      -1.0567   -0.0035331
      -293.31       62.704      -1.1742

>> Hinv = T.tdata.Tinv
Hinv =
       -1.924     -0.42859   -0.0089411
      -2.0585      -1.2615   -0.0071501
       370.68       39.695            1

スクリーンショット

計算を自分で確認できます。

%# points must be in Homogenous coordinates (x,y,w)
>> Z = [A ones(size(A,1),1)] * H;
>> Z = bsxfun(@rdivide, Z, Z(:,end))   %# divide by w
Z =
          152           57            1
          219          191            1
           62          240            1
           92          109            1

これは B の点にマッピングされます。

%# maximum error
>> max(max( abs(Z(:,1:2)-B) ))
ans =
   8.5265e-14
于 2012-07-30T23:42:50.813 に答える
0

別の SO の質問 (MATLAB ソリューションを含む) への回答で、関連する問題について説明しました。リンクされた問題では、出力四角形は長方形でしたが、私の答えは一般的な問題を処理します。

于 2012-07-30T20:29:46.690 に答える
0

すべての座標をベクトルに結合します。2D の場合はax、 、aybxbyです。

定義:

A = [ax, ay];
B = [bx, by];
input = [ones(size(A, 1), 1), A];

変換行列を計算します。

H = input \ B;

新しい観測に適用する必要がある場合A_new:

input_new = [ones(size(A_new, 1), 1), A_new];
B_new = input_new * H;

編集:次のように計算することもできますがHH = inv(input' * input) * input' * B;安全\であればそうします。

于 2012-07-30T19:00:09.587 に答える