File size: 3,073 Bytes
98f6ff1
 
 
 
 
 
1277ccd
3076c99
98f6ff1
e8f7734
98f6ff1
 
 
 
 
 
 
 
 
 
 
 
1277ccd
98f6ff1
 
 
 
 
 
 
1277ccd
 
98f6ff1
 
 
 
 
 
1277ccd
 
 
 
 
98f6ff1
1277ccd
 
 
98f6ff1
1277ccd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98f6ff1
 
 
1277ccd
98f6ff1
 
 
1277ccd
 
 
 
 
98f6ff1
1277ccd
 
 
98f6ff1
1277ccd
98f6ff1
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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 = """
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>3D Printing Model Generator</title>
</head>
<body>
    <h1>Upload Image to Generate 3D Printable Model</h1>
    <form action="/upload" method="post" enctype="multipart/form-data">
        <label>Image:</label><input type="file" name="image" required><br><br>
        <input type="submit" value="Upload & Generate 3D Model">
    </form>
    {% if download_link %}
    <h2>3D Model Ready:</h2>
    <a href="{{ download_link }}" download>Download STL File</a>
    {% endif %}
</body>
</html>
"""

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/<filename>', methods=['GET'])
def download_file(filename):
    return send_file(os.path.join(app.config['OUTPUT_FOLDER'], filename), as_attachment=True)