首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >计算二维四边形变换为另一个四边形的矩阵

计算二维四边形变换为另一个四边形的矩阵
EN

Stack Overflow用户
提问于 2012-07-31 00:07:57
回答 5查看 5.1K关注 0票数 6

在下图中,目标是计算单应矩阵H,该矩阵将a1 a2 a3 a4点转换为其对应的b1 b2 b3 b4点。这就是:

代码语言:javascript
复制
[b1 b2 b3 b4] = H * [a1 a2 a3 a4]

你认为计算H(3x3)的最佳方法是什么?a1...b4是在齐次坐标系(即a1_x a1_y 1',...)中表示的2D中的点。编辑:对于这些类型的问题,我们使用奇异值分解,所以我想看看如何在Matlab中简单地做到这一点。

编辑

这是I最初在Maltlab中尝试使用svd (H=Q/P)来解决它的方法。考虑给定示例的以下代码

代码语言:javascript
复制
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

我期望答案是一个空矩阵,但它不是!这就是我在StackOverflow中问这个问题的原因。现在,我们都知道这是一个投影变换,不是很明显的欧几里得。然而,如果在一般情况下,只使用4个点就可以计算这样的矩阵,这是很好的。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-07-31 07:42:51

使用您发布的数据:

代码语言:javascript
复制
P = [px(:) py(:)];
Q = [qx(:) qy(:)];

计算变换:

代码语言:javascript
复制
H = Q/P;

应用转换:

代码语言:javascript
复制
Q2 = H*P;

比较结果:

代码语言:javascript
复制
err = Q2-Q

输出:

代码语言:javascript
复制
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单应矩阵。它简单地用所提供的点数来求解方程组:

代码语言:javascript
复制
H * A = B   -->   H = B*inv(A)   -->   H = B/A (mrdivide)

另外,MATLAB在图像处理工具箱中还提供了CP2TFORM函数。下面是一个应用于所示图像的示例:

代码语言:javascript
复制
%# 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

检测到角点后,现在我们可以获得空间变换:

代码语言:javascript
复制
%# 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)

结果是:

代码语言:javascript
复制
>> 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

我们可以自己确认计算结果:

代码语言:javascript
复制
%# 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中的点:

代码语言:javascript
复制
%# maximum error
>> max(max( abs(Z(:,1:2)-B) ))
ans =
   8.5265e-14
票数 1
EN

Stack Overflow用户

发布于 2012-07-31 02:24:17

您可以尝试使用cp2tform函数,它可以从控制点对推断出空间转换。由于在您的情况下不会保留并行,因此您应该将transformtype设置为“projective”。更多信息请访问here

票数 2
EN

Stack Overflow用户

发布于 2012-07-31 01:40:34

您可以使用DLT algorithm来实现此目的。在Peter Kovesi's homepage中可以使用MATLAB例程来实现这一点。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11725274

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档