How to save a 3D data matrix as pointcloud in Matlab? - matlab

I have a 3D data matrix which contains information about a scene (which voxels are free / occupied and belong to which class).
So far to plot the data I have to plot 2D slices using imagesc.
I'd like to plot the data as a pointcloud using Matlabs pcshow which should only display occupied voxels and the display the rest as empty space.
How can I convert my 3D matrix into a pointcloud object?

For some NxMxK matrix A where A == 255 indicates free voxels:
% make coordinate grid the size of A
[X,Y,Z] = meshgrid(1:size(A,1),1:size(A,2),1:size(A,3));
% move to xyz format
xyz=[X(:) Y(:) Z(:)];
% show points which are not free and where group values are used as color (scaled by to current colormap)
pcshow(xyz(A~=255,:),A(A~=255))

Related

How obtain coordinates of pixels within bwboundaries in Matlab

Suppose I have an image
and then I use the code below
I=imread("image.bmp");
imshow(I); hold on; [B,L,N] = bwboundaries(I);
for k=1:length(B),
boundary = B{k};
plot(boundary(:,2), boundary(:,1),'.r')
end
The boundaries then look like
However, I don't just want the x,y coordinates of each pixel ON the boundaries. I also want the x,y coordinates of each pixel INSIDE the boundaries also
Is there a way to do this in Matlab?
EDIT: I want to store the row/column numbers for each object in separate matrices. So matrix A1 should store the row/column numbers for the white pixels in the big object, matrix A2 should store the row/column numbers for the white pixels in the circular object

MATLAB: converting 3d plane into 3d matrix pixel locations

I am trying to get a slice of an elongated object in a 3d matrix (227x297x187 binary) that is orthogonal to its orientation..i.e. output image would be a 2d cross-section.
I was thinking the best way to do this would be to find a vector giving the orientation at some point on the object (so for a cross-section at the 40th slice I get the location of centroids at the 30th and 50th slices and find the vector between them), then get a list of pixels corresponding to a plane orthogonal to that vector at the desired slice (along centroid of object at 40th slice), and then retrieve the values in the matrix corresponding to those locations. Assuming the code I have attached finds the plane, I can plot it with surf() but don't know how to translate that into pixel locations in the matrix to generate the values for the 2d cross-section.
startslice=30;
endslice=50;
startnums=bwconncomp(binMATRIX(:,:,startslice));
startnums=regionprops(startnums,'Centroid');
endnums=bwconncomp(binMATRIX(:,:,endslice));
endnums=regionprops(endnums2,'Centroid');
midnums3=bwconncomp(binMATRIX(:,:,(startslice+(endslice-startslice)/2)));
midnums3=regionprops(midnums,'Centroid');
startstuff=[startslice, startnums.Centroid];
endstuff=[endslice, endnums.Centroid];
midstuff=[(startslice+(endslice-startslice)/2), midnums.Centroid];
nullstuff=null(endstuff-startstuff);
A=nullstuff(:,1);
B=nullstuff(:,2);
[x,y]=meshgrid(A,B);
z=1-x-y;
surf(x+midstuff(1),y+midstuff(2),z+midstuff(3))

How can I create a slice of a surface plot to create a line? (Matlab)

Given some function z = f(x,y), I'm interested in creating a (1D) line plot along an arbitrary cutting plane in x,y,z. How do I do this in Matlab? Slice, for example, provides a higher dimensional version (colormap of density data) but this is not what I'm looking for.
E.g.:
z = peaks(50);
surf(z);
%->plot z along some defined plane in x,y,z...
This has been asked before, e.g. here, but this is the answer given is for reducing 3D data to 2D data, and there is no obvious answer on googling. Thanks.
If the normal vector of the plane you want to slice your surface will always lay in the xy plane, then you can interpolate the data over your surface along the x,y coordinates that are in the slicing line, for example, let the plane be defined as going from the point (0,15) to the point (50,35)
% Create Data
z=peaks(50);
% Create x,y coordinates of the data
[x,y]=meshgrid(1:50);
% Plot Data and the slicing plane
surf(z);
hold on
patch([0,0,50,50],[15,15,35,35],[10,-10,-10,10],'w','FaceAlpha',0.7);
% Plot an arbitrary origin axis for the slicing plane, this will be relevant later
plot3([0,0],[15,15],[-10,10],'r','linewidth',3);
Since it is a plane, is relatively easy to obtain the x,y coordinates alogn the slicing plane with linspace, I'll get 100 points, and then interpolate those 100 points into the original data.
% Create x and y over the slicing plane
xq=linspace(0,50,100);
yq=linspace(15,35,100);
% Interpolate over the surface
zq=interp2(x,y,z,xq,yq);
Now that we have the values of z, we need against what to plot them against, that's where you need to define an arbitrary origin axis for your splicing plane, I defined mine at (0,15) for convenience sake, then calculate the distance of every x,y pair to this axis, and then we can plot the obtained z against this distance.
dq=sqrt((xq-0).^2 + (yq-15).^2);
plot(dq,zq)
axis([min(dq),max(dq),-10,10]) % to mantain a good perspective

Mapping coordinates list and Rectangles list by binning

I have a large MxN array of coordinates and I have a large set of rectangles in a structure Rect.Now i am calculating the density of each of the rectangles buy calculating the area/no of points inside it. In Matlab an inefficent way to handle this would be something like below
for ii=1:size(Rect,1)
ind = X>Rect(ii,1) & X<Rect(ii,3) & Y>Rect(ii,2) & Y<Rect(ii,4);
Num_of_coord(ii) = sum(ind);
end
I want to partition my data in 2D bins, say with N=10. How can i bin my Rect and XY coordinate data into each square ? The idea is i don't have to compare all XY coordinates with all Rectangles.
Thanks

Plotting a surface from a set of interior 3D scatter points in MATLAB

I have a large (~60,000) set of triplet data points representing x,y, and z coordinates, which are scattered throughout a Cartesian volume.
I'm looking for a way to use Matlab to visualize the non-convex shape/volume described by the maximum extent of the points.
I can of course visualize the individual points using scatter3, but given the large number of points the details of the shape are obscured by the noise of the dots.
As an analogy, imagine that you filled a hour glass with spheres of random sizes such as BBs, ping pong balls, and kix and then were given the coordinates of the center of each of each object. How would you take those coordinates and visualize the shape of the hour glass containing them?
My example uses different sized objects because the spacing between data points is non-uniform and effectively random; it uses an hourglass because the shape is non-convex.
If your surface enclosing the points can be described as a convex polyhedron (i.e. like the surface of a cube or a dodecahedron, without concave pits or jagged pointy parts), then I would start by creating a 3-D Delaunay triangulation of the points. This will fill the volume around the points with a series of tetrahedral elements with the points as their vertices, and you can then find the set of triangular faces that form the outer shell of the volume using the convexHull method of the DelaunayTri class.
Here's an example that generates 200 random points uniformly distributed within the unit cube, creates a tetrahedral mesh for these points, then finds the 3-D convex hull for the volume:
interiorPoints = rand(200,3); %# Generate 200 3-D points
DT = DelaunayTri(interiorPoints); %# Create the tetrahedral mesh
hullFacets = convexHull(DT); %# Find the facets of the convex hull
%# Plot the scattered points:
subplot(2,2,1);
scatter3(interiorPoints(:,1),interiorPoints(:,2),interiorPoints(:,3),'.');
axis equal;
title('Interior points');
%# Plot the tetrahedral mesh:
subplot(2,2,2);
tetramesh(DT);
axis equal;
title('Tetrahedral mesh');
%# Plot the 3-D convex hull:
subplot(2,2,3);
trisurf(hullFacets,DT.X(:,1),DT.X(:,2),DT.X(:,3),'FaceColor','c')
axis equal;
title('Convex hull');
You could treat your data as a sample from a three-dimensional probability density, and estimate that density on a grid, e.g. via a 3d histogram, or better a 3d kernel density estimator. Then apply a threshold and extract the surface using isosurface.
Unfortunately, hist3 included in the Statistics Toolbox is (despite its name) just a 2d histogram, and ksdensity works only with 1d data, so you would have to implement 3d versions yourself.