Skip to content

Commit 7af6048

Browse files
author
Tristan
committed
changed examples to use pylab.imread in place of scipy.misc.imread
1 parent 008baae commit 7af6048

File tree

4 files changed

+55
-44
lines changed

4 files changed

+55
-44
lines changed

README.md

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@ stl_tools
55
Python code to generate STL geometry files from plain text, LaTeX code, and 2D numpy arrays (matrices).
66

77
This allows for rapid 3D printing of text, rendered equations, or simple digital images.
8-
Use them for product prototyping, art, cookie cutters, ice cube trays, chocolate molds, (see [this](http://www.makerbot.com/tutorials/making-chocolate-molds/)
8+
Use them for product prototyping, art, cookie cutters, ice cube trays, chocolate molds, (see [this](http://www.makerbot.com/tutorials/making-chocolate-molds/)
99
to learn how to make a printed object food-safe) or whatever else you can think of.
1010

11-
Some modification may be needed to the STL or printer settings to get certain shapes to print cleanly (ie. thicker base,
11+
Some modification may be needed to the STL or printer settings to get certain shapes to print cleanly (ie. thicker base,
1212
support structures, etc).
1313

14-
Besides printing, these can also be merged into other 3D meshes for many other
14+
Besides printing, these can also be merged into other 3D meshes for many other
1515
possible uses, using programs such as [Blender](http://www.blender.org/).
1616

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

2121
A command-line script for converting images to STL (no text yet) is included in the installation for those who do not
@@ -24,14 +24,14 @@ want to write Python code directly.
2424
## Requirements:
2525
- [Python](http://python.org/) 2.7 or higher (Python 3.x not yet tested, but would probably work)
2626
- [Numpy](http://www.numpy.org/) 1.7 or higher (for array manipulation)
27-
- [Scipy](http://www.scipy.org/) 0.12 or higher and [PIL](http://www.pythonware.com/products/pil/)(for image reading and filtering functions)
27+
- [Scipy](http://www.scipy.org/) 0.12 or higher (for resizing and filtering functions)
2828
- [Matplotlib](http://matplotlib.org/) 1.2.1 or higher (for rendering text and LaTeX to image data)
2929

3030
## Installation:
31-
Run `python setup.py build install` to install.
31+
Run `python setup.py build install` to install.
3232

3333
This will check for the 3rd party
34-
dependencies above and install the library.
34+
dependencies above and install the library.
3535

3636
This will also install the
3737
command line script `image2stl` into the `Python/Scripts` directory.
@@ -68,13 +68,12 @@ The next three examples convert logos to STL, using color information to achieve
6868
Python code:
6969

7070
```python
71-
from scipy.misc import imread
71+
from pylab import imread
7272

73-
A = imread("examples/example_data/NASA.png")
74-
A = A[:,:,2] + 1.0*A[:,:,0] # Compose elements from RGBA channels to give depth
75-
A = gaussian_filter(A, 1) # smoothing
76-
77-
numpy2stl(A, "examples/NASA.stl", scale=0.05, mask_val = 5.)
73+
A = 256 * imread("examples/example_data/NASA.png") # 0 - 256 (8 bit) scale
74+
A = A[:,:, 2] + 1.0*A[:,:, 0] # Compose RGBA channels to give depth
75+
A = gaussian_filter(A, 1) # smoothing
76+
numpy2stl(A, "examples/NASA.stl", scale=0.05, mask_val=5.)
7877
```
7978
Equivalent command-line syntax:
8079
```bash
@@ -89,8 +88,8 @@ Equivalent command-line syntax:
8988
Python code:
9089

9190
```python
92-
A = imread("examples/example_data/openmdao.png")
93-
A = A[:,:,0] + 1.*A[:,:,3] # Compose elements from RGBA channels to give depth
91+
A = 256.*imread("examples/example_data/openmdao.png") # 0 - 256 (8 bit) scale
92+
A = A[:,:,0] + 1.*A[:,:,3] # Compose elements from RGBA channels to give depth
9493
A = gaussian_filter(A, 2) # smoothing
9594

9695
numpy2stl(A, "examples/OpenMDAO-logo.stl", scale=0.05, mask_val = 1.)
@@ -110,9 +109,9 @@ Source image vs. output geometry:
110109

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

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

117116
Python code:
118117

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

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

132-
numpy2stl(A, "examples/Greens-Theorem_Navier-Stokes.stl", scale=0.2,
131+
numpy2stl(A, "examples/Greens-Theorem_Navier-Stokes.stl", scale=0.2,
133132
mask_val = 5.)
134133
```
135134
Source image vs. output geometry:
@@ -151,7 +150,7 @@ There are 3 principal functions (no classes) to import and use from stl_tools:
151150
fn (string) - filename to use for STL file
152151

153152
Optional input:
154-
scale (float) - scales the height (surface) of the
153+
scale (float) - scales the height (surface) of the
155154
resulting STL mesh. Tune to match needs
156155

157156
mask_val (float) - any element of the inputted array that is less
@@ -164,14 +163,14 @@ There are 3 principal functions (no classes) to import and use from stl_tools:
164163

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

169168
Returns: (None)
170169

171-
`numpy2stl()` is the main function of this repository.
170+
`numpy2stl()` is the main function of this repository.
172171

173172
It takes a 2D numpy array and output filename
174-
as input, and writes an STL file.
173+
as input, and writes an STL file.
175174

176175
Each element of the array is tesselated to its neighbors to produce 2 triangular faces for
177176
every 4 contiguous elements. The depth axis of any vertex is taken to be the value of the array corresponding to that point.
@@ -183,7 +182,7 @@ Array elements which are less than this value will not be included as vertices.
183182
It takes a bit of trial-and-error to get these just right. Plotting the intermediate arrays
184183
with a colorbar (to show scaling) helps in finding decent values.
185184

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

189188

@@ -201,7 +200,7 @@ the largest size that can fit onto your 3D printer platform. Default values are
201200
Returns: (None)
202201

203202
`text2png()` was written as an intermediate helper function to render text to pngs, to then be imported, filtered, and meshed.
204-
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.
203+
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.
205204

206205
### `stl_tools.text2array`
207206
text2array(text)
@@ -211,7 +210,7 @@ However, it may be useful in it's own right. For example, it can be used alone t
211210
text (string) - text to render
212211

213212
Returns: A (ndarray) - 2D numpy array of rendered text
214-
213+
215214

216215
`text2array()` renders inputted text using `text2png()`, but imports the resulting png as an ndarray and deletes the intermediate file.
217216
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
@@ -231,10 +230,10 @@ arguments. See the examples above for usage.
231230
For images of standard sizes for modern cameras, the resulting STL filesize can be pretty large.
232231

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

237-
- 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.
236+
- 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.
238237
For example:
239238
```python
240239
m, n = A.shape
@@ -244,13 +243,22 @@ A[:, 0::n-1] = border_val # make left and right lip
244243
```
245244
In practice, the border may need to be thicker than 1 pixel.
246245

246+
## Known bugs:
247+
248+
- `scipy.misc.imread` has some odd behavior for me on my Linux box (64-bit
249+
Mint 15). When an image is read, an empty 0-dim array is returned. This is
250+
supposedly due to a versioning issue with PIL, which I can't seem to work
251+
around successfully. `pylab.imread` works fine, and seems consistent
252+
across platforms.
253+
254+
247255
## Todo/future features:
248256

249-
- Photos of actual printed models.
257+
- Photos of actual printed models.
250258

251259
- 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)
252260

253-
- It's possible to apply various warping functions to the resulting
254-
meshes. So you could load an image, warp the result into a cylinder, and have a
261+
- It's possible to apply various warping functions to the resulting
262+
meshes. So you could load an image, warp the result into a cylinder, and have a
255263
textured column (or something like that).
256264

examples.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from scipy.misc import lena, imresize, imread
1+
from scipy.misc import lena, imresize
2+
from pylab import imread
23
from scipy.ndimage import gaussian_filter
3-
from stl_tools import numpy2stl, text2png, text2array
4+
from stl_tools import numpy2stl, text2png
45

56

67
"""
@@ -16,13 +17,13 @@
1617
A = gaussian_filter(A, 1) # smoothing
1718
numpy2stl(A, "examples/Lena.stl", scale=0.1)
1819

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

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

@@ -33,7 +34,7 @@
3334
# save png
3435
text2png(text, "examples/Greens-Theorem_Navier-Stokes", fontsize=50)
3536
# read from rendered png
36-
A = imread("examples/Greens-Theorem_Navier-Stokes.png")
37+
A = 256 * imread("examples/Greens-Theorem_Navier-Stokes.png")
3738
A = A.mean(axis=2) # grayscale projection
3839
A = gaussian_filter(A.max() - A, 1.0)
3940
numpy2stl(A, "examples/Greens-Theorem_Navier-Stokes.stl", scale=0.2,

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setup(name='stl_tools',
44
version='0.1',
5-
install_requires=['numpy', 'pil', 'scipy', 'matplotlib'],
5+
install_requires=['numpy', 'scipy', 'matplotlib'],
66
description="Generate STL files from numpy arrays and text",
77
author='Tristan Hearn',
88
author_email='[email protected]',

stl_tools/image2stl.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import numpy as np
44
from numpy2stl import numpy2stl
5-
from scipy.misc import imread
5+
from pylab import imread
66
from scipy.ndimage import gaussian_filter
77

88

@@ -32,8 +32,10 @@ def image2stl():
3232

3333
args = vars(parser.parse_args())
3434

35-
f_args = {f_arg: float(args[f_arg]) for f_arg in _float_args if args[f_arg]}
36-
b_args = {b_arg: bool(int(args[b_arg])) for b_arg in _bool_args if args[b_arg]}
35+
f_args = {f_arg: float(args[f_arg])
36+
for f_arg in _float_args if args[f_arg]}
37+
b_args = {b_arg: bool(int(args[b_arg]))
38+
for b_arg in _bool_args if args[b_arg]}
3739

3840
kwargs = dict(f_args, **b_args)
3941

@@ -42,7 +44,7 @@ def image2stl():
4244
if not fn:
4345
fn = '.'.join([src.split('.')[0], "stl"])
4446

45-
A = imread(src)
47+
A = 256. * imread(src)
4648
L = len(A.shape)
4749
w = args['RGBA_weights']
4850
if L > 2:

0 commit comments

Comments
 (0)