Voxelization of 3D CAD models

Have you searched how to convert a Cad model to a python ready numpy array but didn’t get any clear answer? Me too. After long research and trying a lot of software and python libraries, I was finally able to convert a 3D STEP file into a 3D numpy array. If you want to do the same thing or just want to know how it’s done, read on

Recommendation: Use NSDT Designer to quickly build programmable 3D scenes.

1. Introduction

Compared to 2D image data, there is not much machine learning research on 3D models. Most machine learning and deep learning models use numpy arrays as data types.

While point cloud data can be imported as numpy arrays, spatial information is lost when the 3D model is converted to a point cloud. A point cloud is simply a set of data points in space, where each point has its own set of X, Y, and Z coordinates. Spatial information is recovered when the point cloud is converted to a 3D numpy array. A 3D numpy array is like a bunch of 2D images, where each image is a cross-sectional view of the whole 3D, no matter how you slice the array.

I’ve been working on one of these projects recently, and haven’t found any resources to help me convert a cad model to a numpy array.

2. Required software and Python libraries

To load the “.stp” file we will use the FreeCAD software. FreeCAD is a free and open source parametric 3D modeler. You can download the software from here. We will use FreeCAD to load the “.stp” file and convert it to a point cloud.

For Python, I’ll be using Jupyter Notebook, but the code should work fine on any other IDE. We will need the following Python libraries to visualize point clouds and convert them to numpy arrays.

import pptk #not essential, but its good for visualizing
import numpy as np
import pandas as pd
from pyntcloud import PyntCloud

3. Convert .stp file to point cloud

FreeCAD’s user interface is very intuitive and easy to understand. When you open a “.stp” file in FreeCAD it looks like this:

The cad model I’m using was one I created a few years ago for a competition on the GrabCad website. You can view my other Cad models and render them on GrabCad by clicking here.

The first thing we will do in FreeCAD is activate the point workbench. Go to View>Workbench>Points as shown in the image below:

To convert a 3D model to a point cloud, select a part on the left panel. The Convert to Points option is available in the toolbar when a part body is selected. Select the Convert to Points option and enter a maximum distance. The maximum distance is the distance between two points. The time it takes to create a point cloud is inversely proportional to the maximum distance. So choose it according to the level of verbosity you want and your computer configuration.

When OK is clicked, the point cloud is generated and can be viewed as a single part body on the left panel. This can be seen in the image below:

To export a point cloud, select the point cloud part body on the left panel and click the Export Point Cloud option. Make sure the file extension should be “.asc” when saving the point cloud.

4. Point cloud to 3D Numpy array

To load “.asc” point cloud files into python, we will use the numpy library. Import the point cloud into python using the line of code shown below. The point cloud will be a numpy array of shape (N, 3) . where N is the number of data points and 3 is the X, Y, and Z coordinates of each data point. See the last two lines in the code below for an example of a single data point.

import numpy as np
point_cloud = np.loadtxt("path/bracketpointcloud.asc")
point_cloud.shape
#output: (1840605, 3)
point_cloud[1]
#output: array([94.5374 , -2.27163, -3.81])

We can use pptk library or PyntCloud library to view point cloud. I’ll explain both, but pptk is better and easier to visualize. To visualize a point cloud using pptk, just use the following code. This will open a new window where you can scale and rotate the point cloud. The pptk library provides many other parameters, which can be seen in the documentation.

v = pptk. viewer(point_cloud)

To visualize a point cloud using PyntCloud, we have to convert the numpy array to a pandas dataframe. where each row represents a data point and the columns represent the X, Y, and Z coordinates of the corresponding data point. This data frame is then used to create a PyntCloud object as shown in the code below. To draw a point cloud, use the last line of the code below. PyntCloud will display the output in jupyter. We can set the point size and opacity before displaying the point cloud.

from pyntcloud import PyntCloud
df = pd.DataFrame(data=point_cloud, columns=['x','y','z'])
cloud = PyntCloud(new_df)
cloud
#output: PyntCloud
         1840603 points with 0 scalar fields
         0 faces in mesh
         0 kdtrees
         0 voxelgrids
         Centroid: 57.98352803, 18.506313633, -6.561006902397e-05
         Other attributes:
cloud.plot(point_size=0.1, opacity=0.6)

Now we convert the point cloud data frame into a grid of voxels, also known as point cloud voxelization (Voxelization). To do this, we will use the first two lines of code below. We can also set the size of the voxel space that represents the 3D model. This is especially convenient in deep learning and machine learning, since all inputs should be of the same size. The voxel grid can be viewed using the last line of code shown below.

voxelgrid_id = cloud.add_structure("voxelgrid", n_x=512, n_y=512, n_z=512)
voxelgrid = cloud. structures[voxelgrid_id]
voxelgrid.plot(d=3, mode="density", cmap="hsv")

In the end we just need to convert the voxel grid to a binary numpy array. Use the line of code below.

Binary_voxel_array = voxelgrid.get_feature_vector(mode=”binary”)
Binary_voxel_array.shape
#output: (512, 512, 512)

Ok, now we have a 3D cad model represented by a Numpy array.

5. Let’s see the result

The numpy arrays we create are very similar to 3D models. When we slice an array in 2 dimensions, we immediately get a profile. In this way, the machine can preserve the spatial information of the 3D model, which the machine can learn using various deep learning or machine learning techniques. Here are a few examples of what we get when we slice the array at different indices of the (512, 512, 512) array.

plt.imshow(Binary_voxel_array[ 200, : , : ], cmap='gray')

plt.imshow(Binary_voxel_array[ :, 300, : ], cmap='gray')

plt.imshow(Binary_voxel_array[ :, :, 250 ], cmap='gray')

Original link: 3D CAD model voxelization – BimAnt