Spaces:
Running on Zero
Running on Zero
Rawal Khirodkar commited on
Commit ·
6b72fc2
1
Parent(s): 9a37519
Pointmap: use original-res image as GLB texture (kills mesh-zoom pixelation); drop camera marker
Browse files
app.py
CHANGED
|
@@ -225,11 +225,11 @@ def _triangulate_grid(pointmap_hwc: np.ndarray, mask_hw: np.ndarray,
|
|
| 225 |
return verts, uvs, faces
|
| 226 |
|
| 227 |
|
| 228 |
-
def _make_glb(
|
| 229 |
mask_hw: np.ndarray, max_edge: float = 0.04) -> str:
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
verts, uvs, faces = _triangulate_grid(pointmap_hwc, mask_hw, max_edge=max_edge)
|
| 234 |
|
| 235 |
# Y-up flip so the viewer's default orientation matches photographic intuition.
|
|
@@ -246,7 +246,7 @@ def _make_glb(image_pil_native: Image.Image, pointmap_hwc: np.ndarray,
|
|
| 246 |
uvs = uvs * np.array([1.0, -1.0], dtype=np.float32) + np.array([0.0, 1.0], dtype=np.float32)
|
| 247 |
|
| 248 |
material = trimesh.visual.material.PBRMaterial(
|
| 249 |
-
baseColorTexture=
|
| 250 |
metallicFactor=0.0,
|
| 251 |
roughnessFactor=1.0,
|
| 252 |
doubleSided=True,
|
|
@@ -256,12 +256,14 @@ def _make_glb(image_pil_native: Image.Image, pointmap_hwc: np.ndarray,
|
|
| 256 |
mesh = trimesh.Trimesh(vertices=verts, faces=faces, visual=visual, process=False)
|
| 257 |
_ = mesh.vertex_normals # lazy compute → exported in glb
|
| 258 |
|
| 259 |
-
#
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
|
|
|
|
|
|
|
| 263 |
|
| 264 |
-
scene = trimesh.Scene([mesh
|
| 265 |
out_path = tempfile.NamedTemporaryFile(delete=False, suffix=".glb").name
|
| 266 |
scene.export(out_path)
|
| 267 |
return out_path
|
|
@@ -276,9 +278,10 @@ def predict(image: Image.Image, size: str):
|
|
| 276 |
return None, None
|
| 277 |
|
| 278 |
t0 = _t.perf_counter()
|
| 279 |
-
|
|
|
|
| 280 |
image_bgr = cv2.cvtColor(np.array(image_pil), cv2.COLOR_RGB2BGR)
|
| 281 |
-
print(f"[time] convert+cap {(_t.perf_counter()-t0)*1000:.0f} ms (input {image_pil.size})")
|
| 282 |
|
| 283 |
t = _t.perf_counter()
|
| 284 |
model = _get_pointmap_model(size)
|
|
@@ -299,7 +302,7 @@ def predict(image: Image.Image, size: str):
|
|
| 299 |
print(f"[time] depth+resize {(_t.perf_counter()-t)*1000:.0f} ms")
|
| 300 |
|
| 301 |
t = _t.perf_counter()
|
| 302 |
-
glb_path = _make_glb(
|
| 303 |
print(f"[time] glb export {(_t.perf_counter()-t)*1000:.0f} ms")
|
| 304 |
|
| 305 |
print(f"[time] TOTAL {(_t.perf_counter()-t0)*1000:.0f} ms")
|
|
|
|
| 225 |
return verts, uvs, faces
|
| 226 |
|
| 227 |
|
| 228 |
+
def _make_glb(image_pil_texture: Image.Image, pointmap_hwc: np.ndarray,
|
| 229 |
mask_hw: np.ndarray, max_edge: float = 0.04) -> str:
|
| 230 |
+
"""`image_pil_texture` should be the HIGHEST-resolution input available
|
| 231 |
+
(not the inference-capped one) — it's used as the GLB albedo so the mesh
|
| 232 |
+
surface stays smooth even when zoomed in past the mesh-vertex density."""
|
| 233 |
verts, uvs, faces = _triangulate_grid(pointmap_hwc, mask_hw, max_edge=max_edge)
|
| 234 |
|
| 235 |
# Y-up flip so the viewer's default orientation matches photographic intuition.
|
|
|
|
| 246 |
uvs = uvs * np.array([1.0, -1.0], dtype=np.float32) + np.array([0.0, 1.0], dtype=np.float32)
|
| 247 |
|
| 248 |
material = trimesh.visual.material.PBRMaterial(
|
| 249 |
+
baseColorTexture=image_pil_texture,
|
| 250 |
metallicFactor=0.0,
|
| 251 |
roughnessFactor=1.0,
|
| 252 |
doubleSided=True,
|
|
|
|
| 256 |
mesh = trimesh.Trimesh(vertices=verts, faces=faces, visual=visual, process=False)
|
| 257 |
_ = mesh.vertex_normals # lazy compute → exported in glb
|
| 258 |
|
| 259 |
+
# # Optional camera marker — disabled for now to keep the viewer focused on
|
| 260 |
+
# # the human only. Re-enable by uncommenting:
|
| 261 |
+
# cam_v, cam_c = _camera_marker()
|
| 262 |
+
# cam_v = cam_v * flip - centroid
|
| 263 |
+
# aids = trimesh.PointCloud(vertices=cam_v, colors=cam_c)
|
| 264 |
+
# scene = trimesh.Scene([mesh, aids])
|
| 265 |
|
| 266 |
+
scene = trimesh.Scene([mesh])
|
| 267 |
out_path = tempfile.NamedTemporaryFile(delete=False, suffix=".glb").name
|
| 268 |
scene.export(out_path)
|
| 269 |
return out_path
|
|
|
|
| 278 |
return None, None
|
| 279 |
|
| 280 |
t0 = _t.perf_counter()
|
| 281 |
+
image_pil_full = image.convert("RGB") # original-res (used as texture)
|
| 282 |
+
image_pil = _cap_height(image_pil_full) # capped (used for inference)
|
| 283 |
image_bgr = cv2.cvtColor(np.array(image_pil), cv2.COLOR_RGB2BGR)
|
| 284 |
+
print(f"[time] convert+cap {(_t.perf_counter()-t0)*1000:.0f} ms (input {image_pil.size}, texture {image_pil_full.size})")
|
| 285 |
|
| 286 |
t = _t.perf_counter()
|
| 287 |
model = _get_pointmap_model(size)
|
|
|
|
| 302 |
print(f"[time] depth+resize {(_t.perf_counter()-t)*1000:.0f} ms")
|
| 303 |
|
| 304 |
t = _t.perf_counter()
|
| 305 |
+
glb_path = _make_glb(image_pil_full, pointmap, mask)
|
| 306 |
print(f"[time] glb export {(_t.perf_counter()-t)*1000:.0f} ms")
|
| 307 |
|
| 308 |
print(f"[time] TOTAL {(_t.perf_counter()-t0)*1000:.0f} ms")
|