Created
September 15, 2018 12:08
-
-
Save beantowel/b92204c266e0d3090a4db822629ba6fb to your computer and use it in GitHub Desktop.
generate .stl format mesh from fragmented text
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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