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
Files changed (1) hide show
  1. app.py +16 -13
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(image_pil_native: Image.Image, pointmap_hwc: np.ndarray,
229
  mask_hw: np.ndarray, max_edge: float = 0.04) -> str:
230
- h, w = pointmap_hwc.shape[:2]
231
- image_native = image_pil_native.resize((w, h), Image.LANCZOS)
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=image_native,
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
- # Tiny camera marker only at the (now-shifted) origin of the camera frame.
260
- cam_v, cam_c = _camera_marker()
261
- cam_v = cam_v * flip - centroid
262
- aids = trimesh.PointCloud(vertices=cam_v, colors=cam_c)
 
 
263
 
264
- scene = trimesh.Scene([mesh, aids])
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
- image_pil = _cap_height(image.convert("RGB")) # cap to 1024px height
 
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(image_pil, pointmap, mask)
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")