Wolfram Language

Live Version Coming Soon Check out other examples

Make a 3D Image from a Point Cloud

From a set of points in three dimensions, construct a 3D image.


code

PointCloudToImage3D[points_] := Block[{ranges, bins, binCounts, transposedBinCounts}, ranges = Round[CoordinateBounds[points]]; bins = Append[#, 0.5] & /@ ranges; binCounts = BinCounts[points, Sequence @@ bins]; transposedBinCounts = Reverse[Transpose[binCounts, {3, 2, 1}], {1, 2}]; Blur[ImageAdjust@Image3D[transposedBinCounts], 2] ]

how it works

This set of over 100,000 points was obtained by scanning a toy house:

points = CloudGet[ CloudObject[ "https://programming.wolframcloud.com/app/objects/7cd31aa9-8e2e-\ 4d4e-947e-8f439322a88d"]];

You can see what the points look like via ListPointPlot3D:

ListPointPlot3D[points, BoxRatios -> Automatic]

To turn those discrete points into a 3D image, find the ranges along each coordinate axis of the point coordinates:

ranges = Round[CoordinateBounds[points]]

Append 0.5 to each range to get a description of bins in each axis direction. The x axis bins go from -41 to 52 in 0.5 unit increments:

bins = Append[#, 0.5] & /@ ranges

Count the number of points that fall within each bin:

binCounts = BinCounts[points, Sequence @@ bins];

Each bin count corresponds to a voxel value. Rearrange the voxels so that they correspond to the original point positions when made into a 3D image:

transposedBinCounts = Reverse[Transpose[binCounts, {3, 2, 1}], {1, 2}];

Make an image from the rearranged bin counts:

Image3D[transposedBinCounts]

Refine the image by adjusting the voxel values for better contrast and blurring slightly to blend the values:

Blur[ImageAdjust@Image3D[transposedBinCounts], 2]

Package those steps as a function that can be applied to any point cloud:

PointCloudToImage3D[points_] := Block[{ranges, bins, binCounts, transposedBinCounts}, ranges = Round[{Min[#], Max[#]} & /@ Transpose[points]]; bins = Append[#, 0.5] & /@ ranges; binCounts = BinCounts[points, Sequence @@ bins]; transposedBinCounts = Reverse[Transpose[binCounts, {3, 2, 1}], {1, 2}]; Blur[ImageAdjust@Image3D[transposedBinCounts], 2] ]