Calculating 3d Point Normals in MATLab

4.5k views Asked by At

I have a point-cloud of 3d points in MATLab. The point-cloud is in the form of a 3xN matrix.

I want to calculate the normals for each of these points in the form of a 3xN matrix. How would I go about doing that?

So far I have tried using

nX = (surfnorm(X'))';

Where X is my point-cloud, and nX should be my returned normals. However, whenever I try to do it this way it doesn't seem to work when I render it... Is this the correct way to go about it?

Thanks in advance!

2

There are 2 answers

0
nkjt On

surfnorm expects a surface, so it takes your 3 x N matrix of point locations as a 3 x N size surface (when calling surfnorm, input gives the Z, X and Y are set to defaults). I don't see any way of using this function directly on a point cloud.

In order to find the normals from a point cloud, you need to either:

1) Fit some sort of surface from your point cloud, and then use surfnorm on it. 2) Estimate the normal for each point, using the surrounding points. This site gives a good overview.

There is actually a file on the file exchange which demonstrates the calculation of the normal from a given set of points (a single normal from a given set of points). What you would need to do is calculate a set of nearest neighbours for each point, then return the normal vector. You may also have to correct the orientation of the vector.

0
Arvin Rasoulzadeh On

Since you have the 3 x N point-cloud, lets assume it comes under the name mat. Then I suggest taking the following approach:

% Constructing the Point Cloud and Data Structure
ptCloud = pointCloud(mat);

% Normal Esitmation (3 is simply tthe number of points used for local plane fitting)
normals = pcnormals(ptCloud,3);

At this point your normals are computed in the form of a (3N) x 3 matrix. Which you can add as a property of your point-cloud via

ptCloud.Normal = normals;

In order to visualize it, one can do the following:

step_size = 10; 

x = ptCloud.Location(1:step_size:end,1);
y = ptCloud.Location(1:step_size:end,2);
z = ptCloud.Location(1:step_size:end,3);
u = ptCloud.Normal(1:step_size:end,1);
v = ptCloud.Normal(1:step_size:end,2);
w = ptCloud.Normal(1:step_size:end,3);

% plot

figure;
hold on

% plot the point cloud
pcshow(ptCloud);

% plot the normal arrows
quiver3(x,y,z,u,v,w);

hold off

One last comment: Creating point cloud via pointCloud function gives a much more optimized visualization compared to simply plotting a matrix of points.