简体   繁体   中英

Analysis of a 3D point cloud by projection in a 2D surface

I have a 3D point cloud (XYZ) where the Z can be position or energy. I want to project them on a 2D surface in a n -by- m grid (in my problem n = m ) in a manner that each grid cell has a value of the maximum difference of Z , in case of Z being position, or a value of summation over Z , in case of Z being energy.

For example, in a range of 0 <= (x,y) <= 20 , there are 500 points. Let's say the xy-plane has n -by- m partitions, eg 4 -by- 4 ; by which I mean in both x and y directions we have 4 partitions with an interval of 5 (to make it 20 at maximum. Now, each of these cells should have a value of the summation, or maximum difference, of the Z value of those points which are in the corresponding column in the defined xy-plane.

I made a simple array of XYZ just for a test as follows, where in this case, Z denotes the energy of the each point.

n=1;
for i=1:2*round(random('Uniform',1,5))
    for j=1:2*round(random('Uniform',1,5))
        table(n,:)=[i,j,random('normal',1,1)];
        n=n+1;
    end
end

How can this be done without loops?

The accumarray function is quite suited for this kind of task. First I define example data:

table = [ 20*rand(1000,1) 30*rand(1000,1) 40*rand(1000,1)]; % random data
x_partition = 0:2:20; % partition of x axis
y_partition = 0:5:30; % partition of y axis

I'm assuming that

  • The three columns of table represent x, y, z respectively
  • No point has x lower than that of first edge of your grid or greater than last edge, and the same for y. That is, the grid covers all points.
  • If a bin contains no values the result should be NaN (if you want some other fill value, just change last argument of accumarray ).

Then:

L = size(table,1);
M = length(x_partition);
N = length(y_partition);
[~, ii] = max(repmat(table(:,1),1,M) <= repmat(x_partition,L,1),[],2);
[~, jj] = max(repmat(table(:,2),1,N) <= repmat(y_partition,L,1),[],2);
ii = ii-1; % by assumption, all values in ii will be at least 2, so we subtract 1
jj = jj-1; % same for jj
result_maxdif = accumarray([ii jj], table(:,3), [M-1 N-1], @(v) max(v)-min(v), NaN);
result_sum = accumarray([ii jj], table(:,3), [M-1 N-1], @sum, NaN);

Notes to the code:

  • The key is obtaining ii and jj , which give the indices of the x and y bins in which each point lies. I use repmat to do that. It would have been better to use bsxfun , but it doesn't support the multiple-output version of @max .
  • The result has size (M-1) x (N-1) (numbers of bins in each dimension)

Remarks:

  1. all this can be almost one-liner via python pandas and cutting methods.
  2. I've rewritten your random cloud initialization

What you can do is

  1. layout an xy grid via meshgrid ,
  2. project the cloud on xy (simple marginalization)
  3. find the nearest grid point via a kd-tree search, ie label your data associating to each cloud point a grid node
  4. group data by label and evaluate your local statistic (via accumarray ).

Here's a working example:

 samples = 500;
 %data extrema
 xl = 0; xr = 1; yl = 0; yr = 1;

 % # grid points
 sz = 20;
 % # new random cloud    
 table = [random('Uniform',xl,xr,[samples,1]) , random('Uniform',yr,yl,[samples,1]), random('normal',1,1,[samples,1])];

 figure; scatter3(table(:,1),table(:,2),table(:,3));

 % # grid construction
 xx = linspace(xl,xr,sz); yy = linspace(yl,yr,sz);
 [X,Y] = meshgrid(xx,yy);
 grid_centers = [X(:),Y(:)];

 x = table(:,1); y = table(:,2); 

 % # kd-tree
 kdtreeobj = KDTreeSearcher(grid_centers);
 clss = kdtreeobj.knnsearch([x,y]); % # classification

 % # defintion of local statistic
 local_stat = @(x)sum(x) % # for total energy
 % local_stat = @(x)max(x)-min(x) % # for position off-set

 % # data_grouping
 class_stat = accumarray(clss,table(:,3),[],local_stat );       
 class_stat_M  = reshape(class_stat , size(X)); % # 2D reshaping

 figure; contourf(xx,yy,class_stat_M,20); 

在此输入图像描述在此输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM