|
2 | 2 | import torch |
3 | 3 | import base64 |
4 | 4 | import requests |
| 5 | +import rembg |
5 | 6 | from io import BytesIO |
6 | 7 | from PIL import Image |
7 | 8 |
|
@@ -40,23 +41,31 @@ def generate_3d(job): |
40 | 41 | # 1. Fetch the 2D image from the URL |
41 | 42 | response = requests.get(image_url) |
42 | 43 | response.raise_for_status() |
43 | | - image = Image.open(BytesIO(response.content)).convert("RGB") |
| 44 | + raw_image = Image.open(BytesIO(response.content)) |
44 | 45 |
|
45 | | - print("Image downloaded. Running 3D synthesis...") |
| 46 | + # 2. CRITICAL: Remove the background so TripoSR doesn't generate a cube! |
| 47 | + print("Removing background...") |
| 48 | + transparent_image = rembg.remove(raw_image) |
46 | 49 |
|
47 | | - # 2. Run TripoSR inference |
| 50 | + # 3. Composite onto a clean white background (TripoSR's preferred format) |
| 51 | + image = Image.new("RGB", transparent_image.size, (255, 255, 255)) |
| 52 | + image.paste(transparent_image, mask=transparent_image.split()[3]) # Use alpha channel as mask |
| 53 | + |
| 54 | + print("Image pre-processed. Running 3D synthesis...") |
| 55 | + |
| 56 | + # 4. Run TripoSR inference |
48 | 57 | with torch.no_grad(): |
49 | 58 | scene_codes = model([image], device="cuda") |
50 | 59 |
|
51 | | - # 3. Extract the mesh and export as GLB |
| 60 | + # 5. Extract the mesh and export as GLB |
52 | 61 | meshes = model.extract_mesh(scene_codes, resolution=256) |
53 | 62 | mesh = meshes[0] |
54 | 63 |
|
55 | | - # 4. Save to a temporary GLB file |
| 64 | + # 6. Save to a temporary GLB file |
56 | 65 | temp_path = "/tmp/output.glb" |
57 | 66 | mesh.export(temp_path) |
58 | 67 |
|
59 | | - # 5. Encode the GLB to base64 to send back to Express |
| 68 | + # 7. Encode the GLB to base64 to send back to Express |
60 | 69 | with open(temp_path, "rb") as f: |
61 | 70 | obj_base64 = base64.b64encode(f.read()).decode('utf-8') |
62 | 71 |
|
|
0 commit comments