Search code examples
matlabmatrixvectorizationprojection

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, e.g. 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?


Solution

  • 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, i.e. 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); 
    

    enter image description here enter image description here