Matlab计算三维相似变换。 fitgeotrans for 3D

时间:2014-10-29 16:05:54

标签: matlab transformation similarity affinetransform rotational-matrices

如何计算3D中4点之间的MatLab相似变换? 我可以从

计算变换矩阵

T*X = Xp

但由于点坐标误差很小,它会给我仿射矩阵。我怎样才能将该矩阵与相似矩阵相匹配?我需要像fitgeotrans这样的东西,但需要3D

由于

2 个答案:

答案 0 :(得分:6)

如果我正确地解释你的问题,你会寻找在3D变换矩阵中找到最佳扭曲一个点到另一个点的所有系数。你真正需要做的就是把这个问题放到线性系统中解决。回想一下,在3D中将一个点翘曲到另一个点只是:

A*s = t

s = (x,y,z)是源点,t = (x',y',z')是目标点,A是3 x 3转换矩阵,其格式为:

A = [a00 a01 a02]
    [a10 a11 a12] 
    [a20 a21 a22]

写出A*s = t的实际方程组,我们得到:

a00*x + a01*y + a02*z = x'
a10*x + a11*y + a12*z = y'
a20*x + a21*y + a22*z = z'

A中的系数是我们需要解决的问题。用矩阵形式重写这个,我们得到:

[x y z 0 0 0 0 0 0]   [a00]   [x']
[0 0 0 x y z 0 0 0] * [a01] = [y']
[0 0 0 0 0 0 x y z]   [a02]   [z']
                      [a10] 
                      [a11]
                      [a12]
                      [a20]
                      [a21]
                      [a22]

鉴于您有四个点,您只需连接左侧矩阵的行和右侧的矢量

[x1 y1 z1 0 0 0 0 0 0]   [a00]   [x1']
[0 0 0 x1 y1 z1 0 0 0]   [a01]   [y1']
[0 0 0 0 0 0 x1 y1 z1]   [a02]   [z1']
[x2 y2 z2 0 0 0 0 0 0]   [a10]   [x2']
[0 0 0 x2 y2 z2 0 0 0]   [a11]   [y2']
[0 0 0 0 0 0 x2 y2 z2]   [a12]   [z2']
[x3 y3 z3 0 0 0 0 0 0] * [a20] = [x3']
[0 0 0 x3 y3 z3 0 0 0]   [a21]   [y3']
[0 0 0 0 0 0 x3 y3 z3]   [a22]   [z3']
[x4 y4 z4 0 0 0 0 0 0]           [x4']
[0 0 0 x4 y4 z4 0 0 0]           [y4']
[0 0 0 0 0 0 x4 y4 z4]           [z4']

          S            *   a   =   T

S现在是一个矩阵,其中包含上述格式的四个源点,a现在是您想要的矩阵中变换系数的向量解决(以行主格式排序),T将是上述格式的目标点向量。

要求解参数,您只需在MATLAB中使用mldivide运算符或\,它将为您计算最小二乘估计值。因此:

a = S^{-1} * T

因此,只需像上面那样构建矩阵,然后使用\运算符来求解矩阵中的变换参数。完成后,将T重新整形为3 x 3矩阵。因此:

S = ... ; %// Enter in your source points here like above
T = ... ; %// Enter in your target points in a right hand side vector like above

a = S \ T;
similarity_matrix = reshape(a, 3, 3).';

关于每个坐标的小扰动中的误差,你得到的点越多越好。使用4肯定会给你一个解决方案,但它不足以减轻我认为的任何错误。

次要注意:这个(或多或少)是fitgeotrans所做的。它在给定一堆源点和目标点的情况下计算出最佳单应性,并使用最小二乘法确定它。

希望这能回答你的问题!

答案 1 :(得分:1)

@rayryeng的答案是正确的,因为你在3空间内有一组最多3-dimensional个点。如果您需要转换m空间(n-dimensional)中的m>n点,则首先需要将m-n坐标添加到这些m点,以便它们存在在m-dimensional空间(即@rayryeng中的a矩阵变成方阵)...然后@rayryeng描述的过程会给你精确的点变换,然后你只需要选择原始n-dimensional空间中变换点的坐标。

举个例子,假设您要转换点数:

(2 -2 2) -> (-3 5 -4)
(2 3 0) -> (3 4 4)
(-4 -2 5) -> (-4 -1 -2)
(-3 4 1) -> (4 0 5)
(5 -4 0) -> (-3 -2 -3)

请注意,您有m=5n=3 - 维。因此,您需要为这些点添加坐标,使它们为n=m=5 - 维,然后应用@rayryeng描述的过程。

我已经实现了一个功能(在下面找到它)。您只需要组织点,使得每个源点都是矩阵u中的列,并且每个目标点都是矩阵v中的列。因此,uv矩阵将3分别为5

警告:

  • 函数中的矩阵A可能需要大量内存用于中等多点nP,因为它有nP^4个元素。

  • 为了解决这个问题,对于方形矩阵uv,您只需在MATLAB表示法中使用T=v*inv(u)T=v/u

  • 代码运行速度可能非常慢......

在MATLAB中:

u = [2 2 -4 -3 5;-2 3 -2 4 -4;2 0 5 1 0]; % setting the set of source points
v = [-3 3 -4 4 -3;5 4 -1 0 -2;-4 4 -2 5 -3]; % setting the set of target points
T = findLinearTransformation(u,v); % calculating the transformation

您可以通过以下方式验证T是否正确:

I = eye(5);
uu = [u;I((3+1):5,1:5)]; % filling-up the matrix of source points so that you have 5-d points
w = T*uu; % calculating target points
w = w(1:3,1:5); % recovering the 3-d points
w - v % w should match v ... notice that the error between w and v is really small

计算变换矩阵的函数:

function [T,A] = findLinearTransformation(u,v)
% finds a matrix T (nP X nP) such that T * u(:,i) = v(:,i)
% u(:,i) and v(:,i) are n-dim col vectors; the amount of col vectors in u and v must match (and are equal to nP)
%
    if any(size(u) ~= size(v))
        error('findLinearTransform:u','u and v must be the same shape and size n-dim vectors');
    end
    [n,nP] = size(u); % n -> dimensionality; nP -> number of points to be transformed
    if nP > n % if the number of points to be transform exceeds the dimensionality of points
        I = eye(nP);
        u = [u;I((n+1):nP,1:nP)]; % then fill up the points to be transformed with the identity matrix
        v = [v;I((n+1):nP,1:nP)]; % as well as the transformed points
        [n,nP] = size(u);
    end
    A = zeros(nP*n,n*n);
    for k = 1:nP
        for i = ((k-1)*n+1):(k*n)
            A(i,mod((((i-1)*n+1):(i*n))-1,n*n) + 1) = u(:,k)';
        end
    end
    v = v(:);
    T = reshape(A\v, n, n).';
end