sysu111 commited on
Commit
7818f03
·
1 Parent(s): 0640f41

Add PXDepth demo

Browse files
Files changed (2) hide show
  1. app.py +12 -47
  2. requirements.txt +1 -0
app.py CHANGED
@@ -193,41 +193,21 @@ def filter_flying_points(
193
  return (points[keep], colors[keep]) if keep.any() else (points, colors)
194
 
195
 
196
- def write_splat(
197
  path: Path,
198
  points: np.ndarray,
199
  colors: np.ndarray,
200
- point_size: float,
201
  ) -> None:
202
- """Write a compact Gaussian-splat viewer file with adjustable point size."""
 
 
203
  display_points = points * np.array([1.0, -1.0, -1.0], dtype=np.float32)
204
- low, high = np.percentile(display_points, [1.0, 99.0], axis=0)
205
- extent = max(float(np.max(high - low)), 1e-6)
206
- spacing = extent / max(float(np.sqrt(points.shape[0])), 1.0)
207
- scale = max(spacing * float(point_size) * 0.65, 1e-7)
208
-
209
- dtype = np.dtype(
210
- [
211
- ("position", "<f4", (3,)),
212
- ("scale", "<f4", (3,)),
213
- ("color", "u1", (4,)),
214
- ("rotation", "u1", (4,)),
215
- ],
216
- align=False,
217
- )
218
- splats = np.empty(points.shape[0], dtype=dtype)
219
- splats["position"] = display_points
220
- splats["scale"] = scale
221
- splats["color"][:, :3] = colors
222
- splats["color"][:, 3] = 255
223
- splats["rotation"] = np.array([255, 128, 128, 128], dtype=np.uint8)
224
- splats.tofile(path)
225
 
226
 
227
  def update_viewer(
228
  cache_path: Optional[str],
229
  filter_points: bool,
230
- point_size: float,
231
  max_points: int,
232
  ) -> Optional[str]:
233
  """Rebuild the viewer from cached points without running either model."""
@@ -244,10 +224,10 @@ def update_viewer(
244
  raise gr.Error("No points remain after filtering.")
245
 
246
  cache_file = Path(cache_path)
247
- tag = f"{int(max_points)}_{int(filter_points)}_{float(point_size):.2f}"
248
- viewer_path = cache_file.with_name(f"pointcloud_viewer_{tag}.splat")
249
- write_splat(viewer_path, points, colors, point_size)
250
- for old_path in cache_file.parent.glob("pointcloud_viewer_*.splat"):
251
  if old_path != viewer_path:
252
  old_path.unlink(missing_ok=True)
253
  return str(viewer_path)
@@ -293,7 +273,6 @@ def on_submit(
293
  image: Optional[np.ndarray],
294
  apply_mask: bool,
295
  filter_points: bool,
296
- point_size: float,
297
  max_points: int,
298
  request: gr.Request,
299
  ):
@@ -351,7 +330,6 @@ def on_submit(
351
  viewer_path = update_viewer(
352
  str(cache_path),
353
  filter_points,
354
- point_size,
355
  max_points,
356
  )
357
 
@@ -380,6 +358,7 @@ See the [paper](https://arxiv.org/abs/2608.16984),
380
  label="Input Image",
381
  image_mode="RGB",
382
  type="numpy",
 
383
  elem_id="img-display-input",
384
  )
385
  with gr.Accordion(label="Settings", open=False):
@@ -392,14 +371,6 @@ See the [paper](https://arxiv.org/abs/2608.16984),
392
  info="Statistical outlier filtering; does not rerun the model.",
393
  value=False,
394
  )
395
- point_size = gr.Slider(
396
- 0.25,
397
- 3.0,
398
- value=1.0,
399
- step=0.05,
400
- label="Point Size",
401
- info="Updates only the 3D viewer.",
402
- )
403
  max_points = gr.Slider(
404
  50_000,
405
  500_000,
@@ -449,24 +420,18 @@ See the [paper](https://arxiv.org/abs/2608.16984),
449
 
450
  submit.click(
451
  on_submit,
452
- [input_image, apply_mask, filter_points, point_size, max_points],
453
  [depth_map, model_3d, downloads, viewer_cache],
454
  show_progress="full",
455
  concurrency_limit=1,
456
  )
457
- viewer_inputs = [viewer_cache, filter_points, point_size, max_points]
458
  filter_points.change(
459
  update_viewer,
460
  viewer_inputs,
461
  model_3d,
462
  show_progress="minimal",
463
  )
464
- point_size.release(
465
- update_viewer,
466
- viewer_inputs,
467
- model_3d,
468
- show_progress="minimal",
469
- )
470
  max_points.release(
471
  update_viewer,
472
  viewer_inputs,
 
193
  return (points[keep], colors[keep]) if keep.any() else (points, colors)
194
 
195
 
196
+ def write_viewer_glb(
197
  path: Path,
198
  points: np.ndarray,
199
  colors: np.ndarray,
 
200
  ) -> None:
201
+ """Write the browser point cloud using the stable GLB viewer path."""
202
+ import trimesh
203
+
204
  display_points = points * np.array([1.0, -1.0, -1.0], dtype=np.float32)
205
+ trimesh.PointCloud(display_points, colors=colors).export(path)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
 
207
 
208
  def update_viewer(
209
  cache_path: Optional[str],
210
  filter_points: bool,
 
211
  max_points: int,
212
  ) -> Optional[str]:
213
  """Rebuild the viewer from cached points without running either model."""
 
224
  raise gr.Error("No points remain after filtering.")
225
 
226
  cache_file = Path(cache_path)
227
+ tag = f"{int(max_points)}_{int(filter_points)}"
228
+ viewer_path = cache_file.with_name(f"pointcloud_viewer_{tag}.glb")
229
+ write_viewer_glb(viewer_path, points, colors)
230
+ for old_path in cache_file.parent.glob("pointcloud_viewer_*.*"):
231
  if old_path != viewer_path:
232
  old_path.unlink(missing_ok=True)
233
  return str(viewer_path)
 
273
  image: Optional[np.ndarray],
274
  apply_mask: bool,
275
  filter_points: bool,
 
276
  max_points: int,
277
  request: gr.Request,
278
  ):
 
330
  viewer_path = update_viewer(
331
  str(cache_path),
332
  filter_points,
 
333
  max_points,
334
  )
335
 
 
358
  label="Input Image",
359
  image_mode="RGB",
360
  type="numpy",
361
+ placeholder="# Drop an image here\n— or —\nClick to upload",
362
  elem_id="img-display-input",
363
  )
364
  with gr.Accordion(label="Settings", open=False):
 
371
  info="Statistical outlier filtering; does not rerun the model.",
372
  value=False,
373
  )
 
 
 
 
 
 
 
 
374
  max_points = gr.Slider(
375
  50_000,
376
  500_000,
 
420
 
421
  submit.click(
422
  on_submit,
423
+ [input_image, apply_mask, filter_points, max_points],
424
  [depth_map, model_3d, downloads, viewer_cache],
425
  show_progress="full",
426
  concurrency_limit=1,
427
  )
428
+ viewer_inputs = [viewer_cache, filter_points, max_points]
429
  filter_points.change(
430
  update_viewer,
431
  viewer_inputs,
432
  model_3d,
433
  show_progress="minimal",
434
  )
 
 
 
 
 
 
435
  max_points.release(
436
  update_viewer,
437
  viewer_inputs,
requirements.txt CHANGED
@@ -8,5 +8,6 @@ huggingface_hub>=0.28
8
  matplotlib>=3.8
9
  pillow>=10.0
10
  scipy>=1.12
 
11
  git+https://github.com/EasternJournalist/utils3d.git@3fab839f0be9931dac7c8488eb0e1600c236e183
12
  git+https://github.com/microsoft/MoGe.git@42acd8f46e974f5e0548ecd72315d1d7df2cb6f4
 
8
  matplotlib>=3.8
9
  pillow>=10.0
10
  scipy>=1.12
11
+ trimesh>=4.0
12
  git+https://github.com/EasternJournalist/utils3d.git@3fab839f0be9931dac7c8488eb0e1600c236e183
13
  git+https://github.com/microsoft/MoGe.git@42acd8f46e974f5e0548ecd72315d1d7df2cb6f4