import os import numpy as np from PIL import Image from stl import mesh from flask import Flask, render_template_string, request, send_file from werkzeug.utils import secure_filename import cv2 app = Flask(__name__) UPLOAD_FOLDER = 'uploads' OUTPUT_FOLDER = 'outputs' os.makedirs(UPLOAD_FOLDER, exist_ok=True) os.makedirs(OUTPUT_FOLDER, exist_ok=True) app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER app.config['OUTPUT_FOLDER'] = OUTPUT_FOLDER HTML_TEMPLATE = """ 3D Printing Model Generator

Upload Image to Generate 3D Printable Model



{% if download_link %}

3D Model Ready:

Download STL File {% endif %} """ def image_to_height_map(image_path, size=(256, 256)): image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) resized = cv2.resize(image, size) normalized = resized / 255.0 return normalized def height_map_to_stl(height_map, output_path, scale=10.0): rows, cols = height_map.shape vertices = [] faces = [] for i in range(rows): for j in range(cols): z = height_map[i, j] * scale vertices.append([j, i, z]) vertices = np.array(vertices).reshape((rows, cols, 3)) face_list = [] for i in range(rows - 1): for j in range(cols - 1): face_list.append([vertices[i, j], vertices[i + 1, j], vertices[i, j + 1]]) face_list.append([vertices[i + 1, j], vertices[i + 1, j + 1], vertices[i, j + 1]]) faces_np = np.array(face_list) model = mesh.Mesh(np.zeros(faces_np.shape[0], dtype=mesh.Mesh.dtype)) for i, f in enumerate(faces_np): model.vectors[i] = f model.save(output_path) def create_3d_model(image_path): height_map = image_to_height_map(image_path) output_path = os.path.join(app.config['OUTPUT_FOLDER'], 'model.stl') height_map_to_stl(height_map, output_path) return output_path @app.route('/', methods=['GET']) def index(): return render_template_string(HTML_TEMPLATE, download_link=None) @app.route('/upload', methods=['POST']) def upload(): uploaded_file = request.files['image'] if uploaded_file: filename = secure_filename(uploaded_file.filename) image_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) uploaded_file.save(image_path) stl_path = create_3d_model(image_path) return render_template_string(HTML_TEMPLATE, download_link=f'/download/{os.path.basename(stl_path)}') return render_template_string(HTML_TEMPLATE, download_link=None) @app.route('/download/', methods=['GET']) def download_file(filename): return send_file(os.path.join(app.config['OUTPUT_FOLDER'], filename), as_attachment=True)