3D-3D的T矩阵计算方法
2019-04-09
今天在看一份代码,主要完成的是3D-3D的位姿估计问题。一般这种问题采用的方法都是SVD分解的方法。但是我发现代码中的SVD分解算法与《SLAM14讲》中给出的方法不一样,之后去查询了两种算法的理论由来,发现都是可以用的。
《SLAM14讲中的算法》
《代码中的算法》
Matlab代码(方法二)
function [T, Eps] = estimateRigidTransform(x, y)
% ESTIMATERIGIDTRANSFORM
% [T, EPS] = ESTIMATERIGIDTRANSFORM(X, Y) estimates the rigid transformation
% that best aligns x with y (in the least-squares sense).
%
% Reference: "Estimating Rigid Transformations" in
% "Computer Vision, a modern approach" by Forsyth and Ponce (1993), page 480
% (page 717(?) of the newer edition)
%
% Input:
% X: 3xN, N 3-D points (N>=3)
% Y: 3xN, N 3-D points (N>=3)
%
% Output
% T: the rigid transformation that aligns x and y as: xh = T * yh
% (h denotes homogenous coordinates)
% (corrspondence between points x(:,i) and y(:,i) is assumed)
%
% EPS: the smallest singular value. The closer this value it is
% to 0, the better the estimate is. (large values mean that the
% transform between the two data sets cannot be approximated
% well with a rigid transform.
%
% Babak Taati, 2003
% (revised 2009)
if nargin ~= 2
error('Requires two input arguments.')
end
if size(x,1)~=3 || size(y,1)~=3
error('Input point clouds must be a 3xN matrix.');
end
if size(x, 2) ~= size(y,2)
error('Input point clouds must be of the same size');
end
if size(x,2)<3 || size(y,2)<3
error('At least 3 point matches are needed');
end
pointCount = length(x); % since x has N=3+ points, length shows the number of points
x_centroid = sum(x,2) / pointCount;
y_centroid = sum(y,2) / pointCount;
x_centrized = [x(1,:)-x_centroid(1) ; x(2,:)-x_centroid(2); x(3,:)-x_centroid(3)];
y_centrized = [y(1,:)-y_centroid(1) ; y(2,:)-y_centroid(2); y(3,:)-y_centroid(3)];
R12 = y_centrized' - x_centrized';
R21 = x_centrized - y_centrized;
R22_1 = y_centrized + x_centrized;
R22 = crossTimesMatrix(R22_1(1:3,:));
B = zeros(4, 4);
A = zeros(4, 4, pointCount);
for ii=1:pointCount
A(1:4,1:4,ii) = [0, R12(ii,1:3); R21(1:3,ii), R22(1:3,1:3,ii)];
B = B + A(:,:,ii)' * A(:,:,ii);
end
[dummy, S, V] = svd(B);
quat = V(:,4);
rot = quat2rot(quat);
T1 = [eye(3,3), -y_centroid ; 0 0 0 1];
T2 = [rot, [0; 0; 0]; 0 0 0 1];
T3 = [eye(3,3), x_centroid ; 0 0 0 1];
T = T3 * T2 * T1;
Eps = S(4,4);