-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathpctransformNonRigid.m
104 lines (92 loc) · 2.93 KB
/
pctransformNonRigid.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
function ptCloudOut = pctransformNonRigid(ptCloudIn, tform)
%PCTRANSFORM Rigid transform a 3-D point cloud.
% ptCloudOut = PCTRANSFORM(ptCloudIn, tform) apply forward
% rigid transform to a point cloud. ptCloudIn is a pointCloud object.
% tform is an affine3d object, and it has to be a valid rigid transform
% (rotation and translation only).
%
% Note
% ----
% The transformation applies to both the coordinates of points and their
% normal vectors.
%
% Class Support
% -------------
% ptCloudIn and ptCloutOut must be pointCloud object. tform must be an
% affine3d object.
%
% Example: Rotate 3-D point cloud
% -------------------------------
% ptCloud = pcread('teapot.ply');
%
% % Plot the original data
% figure
% pcshow(ptCloud)
% xlabel('X')
% ylabel('Y')
% zlabel('Z')
%
% % Create a transform object with 45 degrees rotation along z-axis
% A = [cos(pi/4) sin(pi/4) 0 0; ...
% -sin(pi/4) cos(pi/4) 0 0; ...
% 0 0 1 0; ...
% 0 0 0 1];
% tform = affine3d(A);
%
% % Transform the point cloud
% ptCloudOut = pctransform(ptCloud, tform);
%
% % Plot the transformed point cloud
% figure
% pcshow(ptCloudOut)
% xlabel('X')
% ylabel('Y')
% zlabel('Z')
%
% See also pointCloud, affine3d, pcshow, pcread
% Copyright 2014 The MathWorks, Inc.
narginchk(2, 2);
% Validate the first argument
if ~isa(ptCloudIn, 'pointCloud')
error(message('vision:pointcloud:notPointCloudObject', 'ptCloudIn'));
end
% Validate the second argument
validateattributes(tform, {'affine3d'}, {'scalar'}, mfilename, 'tform');
% Only rigid registration is allowed
% if ~(isRigidTransform(tform))
% error(message('vision:pointcloud:rigidTransformOnly'));
% end
R = tform.T(1:3, 1:3);
t = tform.T(4, 1:3);
% Apply forward transform to coordinates
if ismatrix(ptCloudIn.Location)
loc = ptCloudIn.Location * R;
loc(:,1) = loc(:,1) + t(1);
loc(:,2) = loc(:,2) + t(2);
loc(:,3) = loc(:,3) + t(3);
else
loc = reshape(ptCloudIn.Location,[],3) * R;
loc(:,1) = loc(:,1) + t(1);
loc(:,2) = loc(:,2) + t(2);
loc(:,3) = loc(:,3) + t(3);
loc = reshape(loc, size(ptCloudIn.Location));
end
% Apply forward transform to normal vector
nv = single.empty();
if ~isempty(ptCloudIn.Normal)
if ismatrix(ptCloudIn.Normal)
nv = ptCloudIn.Normal * R;
else
nv = reshape(reshape(ptCloudIn.Normal, [], 3) * R, size(ptCloudIn.Normal));
end
end
ptCloudOut = pointCloud(loc, 'Color', ptCloudIn.Color, 'Normal', nv);
end
%==========================================================================
% Determine if transformation is rigid transformation
%==========================================================================
function tf = isRigidTransform(tform)
singularValues = svd(tform.T(1:tform.Dimensionality,1:tform.Dimensionality));
tf = max(singularValues)-min(singularValues) < 100*eps(max(singularValues(:)));
tf = tf && abs(det(tform.T)-1) < 100*eps(class(tform.T));
end