• Stars
    star
    253
  • Rank 160,776 (Top 4 %)
  • Language
    Python
  • License
    Other
  • Created about 11 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Python code to produce STL geometry files from plain text, LaTeX code, and 2D numerical arrays (matrices)

stl_tools

Python code to generate STL geometry files from plain text, LaTeX code, and 2D numpy arrays (matrices).

This allows for rapid 3D printing of text, rendered equations, or simple digital images. Use them for product prototyping, art, cookie cutters, ice cube trays, chocolate molds, (see this to learn how to make a printed object food-safe) or whatever else you can think of.

Some modification may be needed to the STL or printer settings to get certain shapes to print cleanly (i.e. thicker base, support structures, etc).

Besides printing, these can also be merged into other 3D meshes for many other possible uses, using programs such as Blender.

Also included is a function that can convert raw LaTeX expressions to high quality .png images, which allows for simple inclusion of LaTeX equations into non-LaTeX document editors.

A command-line script for converting images to STL (no text yet) is included in the installation for those who do not want to write Python code directly.

Requirements:

  • Python 2.7+ or 3.2+
  • Numpy 1.7 or higher (for array manipulation)
  • Scipy 0.12 or higher (for resizing and filtering functions)
  • Matplotlib 1.2.1 or higher (for rendering text and LaTeX to image data)

Installation:

There are two ways to install stl_tools.

It's recommended that you install Numpy, Scipy, and Matplotlib first, either using binary installers (windows) or using a package manager (apt-get, homebrew), etc.

Installing straight from PyPI:

Run pip install stl_tools.

Installing from Source:

Run python setup.py build install to install.

Either method will also install the command line script image2stl into the Python/Scripts directory.

Automatic tests can be performed by running stl_tools/test/test_stl.py.

If a path to a C compiler is found by setuptools, a C-extension will be built to handle most of the computational heavy lifting needed by the library at runtime. The library can default to using plain python code as well, though this is much slower.

Quickstart Examples:

Run the file examples.py to produce a few sample STL files from images included in examples/example_data.

The first example converts the commonly-used Lena test image to an STL file The "solid" keyword argument sets whether to create a solid geometry (with sides and a bottom) or not. The algorithm used to generate the sides and bottom have not yet been optimized, so may double the file size at the moment. We'll generate this example without a bottom.

from stl_tools import numpy2stl

from scipy.misc import lena, imresize
from scipy.ndimage import gaussian_filter


A = imresize(lena(), (256, 256))  # load Lena image, shrink in half
A = gaussian_filter(A, 1)  # smoothing

numpy2stl(A, "examples/Lena.stl", scale=0.1, solid=False)

Source image vs. output geometry: Alt text

Click to view STL


The next two examples convert logos to STL, using color information to achieve appropriate 3D layering. For this example, we'll generate a solid geometry (solid=True), for comparison to the first example.

Python code:

from pylab import imread

A = 256 * imread("examples/example_data/NASA.png")
A = A[:, :, 2] + 1.0*A[:,:, 0] # Compose RGBA channels to give depth
A = gaussian_filter(A, 1)  # smoothing
numpy2stl(A, "examples/NASA.stl", scale=0.05, mask_val=5., solid=True)

Equivalent command-line syntax:

> image2stl NASA.png -scale 0.05 -mask_val 5. -RGBA_weights 1. 0. 1. 0. -gaussian_filter 1

Alt text Click to view STL


Python code:

A = 256 * imread("examples/example_data/openmdao.png")
A =  A[:, :, 0] + 1.*A[:,:, 3] # Compose some elements from RGBA to give depth
A = gaussian_filter(A, 2)  # smoothing
numpy2stl(A, "examples/OpenMDAO-logo.stl", scale=0.05, mask_val=1., solid=False)

Equivalent command-line syntax:

> image2stl openmdao.png -scale 0.05 -mask_val 1. -RGBA_weights 1. 0. 0. 1. -gaussian_filter 2

Source image vs. output geometry: Alt text

Click to view STL


Finally, this example renders a LaTeX expression into a png image, then converts this image to an STL.

Note that LaTeX expressions which coincidentally contain special ASCII markers (such as \n and \r) have to be escaped with an additional slash in those positions in order to be properly rendered, unless these markers are intended.

Python code:

from stl_tools import numpy2stl, text2png, text2array

text = ("$\oint_{\Gamma} (A\, dx + B\, dy) = \iint_{U} \left(\\frac{\partial "
        "B}{\partial x} - \\frac{\partial A}{\partial y}\\right)\ dxdy$ \n\n "
        "$\\frac{\partial \\rho}{\partial t} + \\frac{\partial}{\partial x_j}"
        "\left[ \\rho u_j \\right] = 0$")
text2png(text, "examples/Greens-Theorem_Navier-Stokes", fontsize=50) #save png

A = imread("examples/Greens-Theorem_Navier-Stokes.png") # read from rendered png
A = A.mean(axis=2) #grayscale projection
A = gaussian_filter(A.max() - A, 1.)

numpy2stl(A, "examples/Greens-Theorem_Navier-Stokes.stl", scale=0.2,
                                                         mask_val = 5.)

Source image vs. output geometry: Alt text Alt text

Click to view STL

Library usage:

There are 3 principal functions (no classes) to import and use from stl_tools:

stl_tools.numpy2stl

numpy2stl(A, fn, scale=0.1, mask_val = -np.inf, ascii=False, calc_normals=False)
Reads a numpy array, and outputs an STL file

Inputs:
 A (ndarray) -  an 'm' by 'n' 2D numpy array
 fn (string) -  filename to use for STL file

Optional input:
 scale (float)  -  scales the height (surface) of the
                   resulting STL mesh. Tune to match needs

 mask_val (float) - any element of the inputted array that is less
                    than this value will not be included in the mesh.
                    default renders all vertices (x > -inf for all float x)

 ascii (bool)  -  sets the STL format to ascii or binary (default)

 calc_normals (bool) - sets whether surface normals are calculated or not

 max_width, max_depth, max_height (floats) - maximum size of the stl
                                            object (in mm). Match this to
                                            the dimensions of a 3D printer platform

Returns: (None)

numpy2stl() is the main function of this repository.

It takes a 2D numpy array and output filename as input, and writes an STL file.

Each element of the array is tessellated to its neighbors to produce 2 triangular faces for every 4 contiguous elements. The depth axis of any vertex is taken to be the value of the array corresponding to that point.

The scale argument scales the height of the resulting geometry. It's a similar effect to extruding or shrinking.

The mask_val argument allows you to set a threshold value for elements in the input array for exclusion in the STL file. Array elements which are less than this value will not be included as vertices. It takes a bit of trial-and-error to get these just right. Plotting the intermediate arrays with a colorbar (to show scaling) helps in finding decent values.

The max_width, max_height, and max_depth values are measurements (in mm) used to scale the final output to the largest size that can fit onto your 3D printer platform. Default values are for the MakerBot Replicator.

stl_tools.text2png

text2png(text, fn = None)
Renders inputted text to a png image using matplotlib.

Inputs:
 text (string) -  text to render

Optional input:
 fn (string)  -  filename of png to be outputted.
                 defaults to the entered text

Returns: (None)

text2png() was written as an intermediate helper function to render text to pngs, to then be imported, filtered, and meshed. However, it may be useful in it's own right. For example, it can be used alone to render LaTeX expressions into images, to be imported into WYSIWYG document editors like MS Word or LibreOffice Writer.

stl_tools.text2array

text2array(text)
Renders inputted text, and returns array representation.

Inputs:
 text (string) -  text to render

Returns: A (ndarray) - 2D numpy array of rendered text

text2array() renders inputted text using text2png(), but imports the resulting png as an ndarray and deletes the intermediate file. There may be a direct way to render the matplotlib figure as an array without using an intermediate file, but I could not seem to find a simple way in the matplotlib docs.

Command-line scripts

image2stl

image2stl is a command-line script that is installed via entry points when setup.py is run. This provides a simple command-line interface to the functions of this library, with the same arguments. See the examples above for usage.

Tips:

  • Consider scaling down a digital image before generating an STL from its pixels. For images of standard sizes for modern cameras, the resulting STL file size can be pretty large.

  • Just like was shown in the examples, applying a simple filtering function to smooth sharp edges results in an STL geometry that is likely to be more easily printable. Fine tuning in a program like Photoshop or Gimp can also help prevent spikes/jagged edges in the geometry.

  • To make a proper mold, scale up the edges of the source image to match the maximum pixel value of the image (or higher), to form a lip. For example:

m, n = A.shape
border_val = 1.1 * A.max()
A[0::m-1, :] = border_val # make top and bottom lip
A[:, 0::n-1] = border_val # make left and right lip

In practice, the border may need to be thicker than 1 pixel.

Known bugs:

  • scipy.misc.imread has some odd behavior for me on my Linux box (64-bit Mint 15). When an image is read, an empty 0-dim array is returned. This is supposedly due to a versioning issue with PIL, which I can't seem to work around successfully. pylab.imread works fine, and seems consistent across platforms.

Todo/future features:

  • Photos of actual printed models.

  • I'm looking into writing a utility function to refine STL meshes by removing redundant vertices (so that wide flat spaces aren't packed with dense tessellations)

  • It's possible to apply various warping functions to the resulting meshes. So you could load an image, warp the result into a cylinder, and have a textured column (or something like that).

More Repositories

1

webcam-pulse-detector

A python application that detects and highlights the heart-rate of an individual (using only their own webcam) in real-time.
Python
3,093
star
2

Python-Arduino-Command-API

A Python library for communicating with Arduino microcontroller boards
Python
406
star
3

game-of-life

Simple Python implementation of Conway's game of life and other cellular automata, computed using numpy.fft
Python
172
star
4

simple-cython-example

A small project template that shows how to wrap C code into python using cython, along with other packaging concepts
Python
123
star
5

examgen

A Python class that can automatically generate mathematics exams, with solution keys, using Sympy and LaTeX.
Python
53
star
6

math-genealogy

A python script to collect data from the mathematics genealogy project and generate genealogy graphs, combine graphs, etc.
Python
34
star
7

magiceye-solver

A python code to automatically "solve" magic eye autostereograms
Python
30
star
8

pyemotiv

A Python library for data acquisition from the Emotiv Epoc EEG headset, using the research SDK.
Python
22
star
9

pygmaps-extended

Python wrapper for Google Maps JavaScript API V3 and Google Earth API.
Python
16
star
10

github-auto-tools

Python command line tool to clone all public repos and gists from a single github account, and populate empty new repos with a set of templated default files.
Python
15
star
11

pandemic

Python based dynamical optimization of a pandemic disease model
Python
11
star
12

python-screenshot

Python library to make screen captures and save the images to the cwd
Python
11
star
13

pyneulog

Python interface for Neulog GSR sensor
Python
8
star
14

maximum-submatrix-sum

Python code that implements an algorithm for finding the maximum submatrix sum of an M by N matrix
Python
5
star
15

pyrovio

Python code to interface with the Wowwee Rovio robotic webcam
Python
4
star
16

garage_door_control

Android, spark firmware, and fritzing file for garage door control project
Java
4
star
17

Rimworld_roof_editor

Tool for editing roof-types on Rimworld maps
Python
4
star
18

latex-homework-template

A multi-column, landscape-oriented LaTeX template for homework assignments
3
star
19

imresize

A replacement for scipy.misc.imresize that does not depend on PIL
Python
3
star
20

opencv-data-plotter

A python code for fast, real-time 2d data plotting for codes that already have opencv as a dependency.
Python
2
star
21

Atlas

OpenMDAO implementation of the Aerovelo Atlas human-powered helicopter design problem
C
2
star
22

data-store

Some python tools for doing key-value storing
Python
2
star
23

SGNDI

Separable Grid N-Dimensional Interpolator: A multi-dimensional interpolating class with based on 1D interpolation.
Python
2
star
24

CVtemplate

Template for a real time computer vision project using OpenCV
Python
2
star
25

talk_inverse_probs

A short talk on discrete ill-posed inverse problems
Python
2
star
26

arduino-sketch-demos

A collection of various arduino demo sketches
Processing
2
star
27

SwiftFiniteDifference.playground

experimentation with first class functions in Swift
Swift
2
star
28

quick_imshow

Python code to quickly display an image with matplotlib. Meant for debugging image processing code.
Python
2
star
29

CADRE-old

OpenMDAO implementation of the CADRE CubeSat design problem
Python
1
star
30

thearn.github.io

1
star
31

printable_ramps

IPython Notebook for generating hand-drawn 3D-printable candidate solutions to the Brachistochrone problem
JavaScript
1
star
32

pathfinding

Python
1
star
33

android_tutorial

Java
1
star
34

pickle-gzip

Small python library to save and load objects with pickle from disc, with gzip compression.
Python
1
star
35

solar

OpenMDAO solar energy model
Python
1
star