Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
generate .stl format mesh from fragmented text
from PIL import Image, ImageFont, ImageDraw
from stl import mesh
from mpl_toolkits import mplot3d
from matplotlib import pyplot as plt
from cv2 import cv2
import itertools as its
import numpy as np
import random
import sys
def createImage(width, height, size, text, fontname = 'Ubuntu-B.ttf'):
# mode = 'L' -- 8-bit pixels, black and white
image = Image.new('L', (width, height))
draw = ImageDraw.Draw(image)
font = ImageFont.truetype(fontname, size)
draw.text((0, 0), text, font=font, fill=0xff)
# image.show()
return image
def showMesh(filename):
# Create a new plot
figure = plt.figure()
# text = 'Laura10X'
# facetCnt = 1000
axes = mplot3d.Axes3D(figure)
# Load the STL files and add the vectors to the plot
your_mesh = mesh.Mesh.from_file(filename)
axes.add_collection3d(mplot3d.art3d.Poly3DCollection(your_mesh.vectors))
# Auto scale to the mesh size
scale = your_mesh.points.flatten(-1)
axes.auto_scale_xyz(scale, scale, scale)
# Show the plot to the screen
plt.show()
class facetGen:
def __init__(self, image, edges, depth):
self.image = image
self.edges = edges
self.depth = depth
self.nonZeros = [] # nonZero pixels' coordinate:np.array
height = edges.shape[0]
width = edges.shape[1] # shape->(height, width)
for j, i in its.product(range(width), range(height)):
if edges[i, j] != 0:
self.nonZeros.append(np.array((i, j)))
self.len = len(self.nonZeros)
print('nonZeros:', self.len, 'shape:', image.shape)
def checkVertices(self, vertices, checkCnt):
def weightedMeanVertex(vertices, weights):
x = np.array((0.0, 0.0))
for v, w in zip(vertices, weights):
x += w * v
meanVertex = x // np.sum(weights)
return meanVertex.astype('int64')
def randomCheckPoint():
weights = tuple(random.random() for i in range(3))
return weightedMeanVertex(vertices, weights)
checkPoints = (randomCheckPoint() for i in range(checkCnt))
if all(self.image[tuple(p)] for p in checkPoints):
return True
else:
return False
def randomVertices(self):
# i = random.randrange(self.len)
# j = random.randrange(max(1, i - 300))
# k = random.randrange(i, min(i + 300, self.len))
i, j, k = (random.randrange(self.len) for x in range(3))
vertices = tuple(self.nonZeros[x] for x in (i, j, k))
return vertices
def generateVertices(self, checkCnt):
vertices = self.randomVertices()
while not self.checkVertices(vertices, checkCnt):
vertices = self.randomVertices()
z1 = random.randrange(self.depth)
z2 = random.randrange(max(0, z1 - 50), min(self.depth, z1 + 50))
z3 = random.randrange(max(0, z1 - 50), min(self.depth, z1 + 50))
vertices3D = list(
np.append(v, z) for v, z in zip(vertices, [z1, z2, z3]))
print('vertices generated')
return vertices3D
print('arguments(name, text, cnt):', sys.argv)
name, text, facetCnt = sys.argv[1:]
facetCnt = int(facetCnt)
stlname = name + '.stl'
filename = name + '.png'
size = 300
random.seed(10)
checkCnt = 30
width = int(len(text) * size)
height = 2 * size
textImage = createImage(width, height, size, text, 'NotoSansCJK-Bold.ttc')
textImage.save(filename)
image = cv2.imread(filename, flags=cv2.IMREAD_GRAYSCALE)
edges = cv2.Canny(image, 10, 50)
gen = facetGen(image, edges, size)
fragMesh = mesh.Mesh(np.zeros(facetCnt, dtype=mesh.Mesh.dtype))
for i in range(facetCnt):
print(i, end = ' ')
fragMesh.vectors[i] = gen.generateVertices(checkCnt)
print('gen done')
fragMesh.save(stlname)
showMesh(stlname)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.