Converting Python NumPy Arrays to STL Files: A Step-by-Step Guide

πŸ’‘ Problem Formulation: This article addresses how to convert a Python NumPy array, which often represents 3D data, into an STL (Stereolithography) file format, commonly used for 3D printing and computer-aided design. For instance, if you start with a NumPy array that represents the vertices of a 3D object, you want to produce an STL file that can be used to print this object using a 3D printer.

Method 1: Using numpy-stl Library

This method involves using the numpy-stl library, which is specifically designed to handle the transformation of NumPy arrays into STL files. It provides a set of easy-to-use functions that can create, modify, and write STL files from NumPy arrays.

Here’s an example:

from stl import mesh
import numpy as np

# Define the 8 vertices of the cube
vertices = np.array([
    [-1, -1, -1],
    [+1, -1, -1],
    [+1, +1, -1],
    [-1, +1, -1],
    [-1, -1, +1],
    [+1, -1, +1],
    [+1, +1, +1],
    [-1, +1, +1]
])

# Define the 12 triangles composing the cube
faces = np.array([
    [0,3,1],
    [1,3,2],
    [0,4,7],
    [0,7,3],
    [4,5,6],
    [4,6,7],
    [5,1,2],
    [5,2,6],
    [2,3,6],
    [3,7,6],
    [0,1,5],
    [0,5,4]
])

# Create the mesh
cube = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype))
for i, f in enumerate(faces):
    for j in range(3):
        cube.vectors[i][j] = vertices[f[j],:]

# Write the mesh to file "cube.stl"
cube.save('cube.stl')

The output will be an STL file named “cube.stl”, representing a 3D cube.

This code snippet first creates an array of vertices and faces defining a cube. Then, it constructs a mesh object using numpy-stl‘s mesh data type, setting the vectors to correspond to the faces of the cube. Lastly, it writes the mesh object to an STL file.

Method 2: Using PyMesh Library

The PyMesh library is another Python tool that can process and convert mesh files. It includes support for Mesh I/O, mesh processing algorithms, and the ability to directly convert NumPy arrays to STL files with its advanced functions.

Here’s an example:

import numpy as np
import pymesh

vertices = np.array([
    [0, 0, 0],
    [1, 0, 0],
    [0, 1, 0],
    [0, 0, 1]
])

faces = np.array([
    [0, 1, 2],
    [0, 1, 3],
    [0, 2, 3],
    [1, 2, 3]
])

mesh = pymesh.form_mesh(vertices, faces)
pymesh.save_mesh('tetrahedron.stl', mesh)

The output will be an STL file named “tetrahedron.stl”, representing a tetrahedron.

This code snippet shows how to create a simple tetrahedron mesh from vertices and faces using PyMesh. After defining the mesh, it saves the object directly to an STL file named ‘tetrahedron.stl’.

Method 3: Using trimesh Library

trimesh is an open-source Python library used for loading and using triangular meshes. It allows for simple STL file creation from NumPy arrays while also offering a wide array of additional mesh processing utilities.

Here’s an example:

import numpy as np
import trimesh

# Define the vertices and faces of the 3D object
vertices = np.array([[1, 1, 1], [-1, -1, 1], [1, -1, -1], [-1, 1, -1]])
faces = np.array([[0, 1, 2], [0, 1, 3], [1, 2, 3], [0, 2, 3]])

# Create a mesh and save it to STL
mesh = trimesh.Trimesh(vertices=vertices, faces=faces)
mesh.export('pyramid.stl')

The output will be an STL file named “pyramid.stl”, representing a 3D pyramid.

In this example, vertices and faces define a simple pyramid. With the trimesh library, a Trimesh object is created from these arrays, which can then be exported to an STL file format.

Bonus One-Liner Method 4: Using scikit-image

For those who are already using scikit-image for image processing, the marching_cubes function can also be used to generate a vertex and face array from a NumPy array which can then be exported to STL using the numpy-stl library.

Here’s an example:

import numpy as np
from skimage import measure
from stl import mesh

# Generate a 3D numpy array of shape (27,27,27)
data = np.zeros((27, 27, 27), dtype=np.uint8)
# Creating a cube of 1s within the zero array
data[8:20, 8:20, 8:20] = 1

# Create vertices and faces from the 3D image
vertices, faces, _, _ = measure.marching_cubes(data, 0)

# Convert to mesh and save
data_mesh = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype))
for i, f in enumerate(faces):
    for j in range(3):
        data_mesh.vectors[i][j] = vertices[f[j],:]

data_mesh.save('generated_cube.stl')

The output will be an STL file named “generated_cube.stl”, representing a cube generated from 3D image data.

This code demonstrates creating a 3D object within a NumPy array and using the skimage and numpy-stl libraries to generate and save an STL file of that object.

Summary/Discussion

  • Method 1: Using numpy-stl. Strengths: This method is straightforward and designed specifically for converting NumPy arrays to STL files. Weaknesses: Requires the installation of a third-party library.
  • Method 2: Using PyMesh. Strengths: PyMesh has a collection of versatile mesh processing functionalities. Weaknesses: It may be overkill for simple conversions and has a higher learning curve.
  • Method 3: Using trimesh. Strengths: trimesh is great for quick conversions and also offers additional mesh processing tools. Weaknesses: Similar to numpy-stl, it requires an additional library installation.
  • Bonus Method 4: Using scikit-image and numpy-stl. Strengths: This method is useful when starting from volumetric data instead of raw vertices and faces. Weaknesses: Requires two libraries and is less direct than other methods.