Download app.py from junaid-simamdigital/SimamSplatSurgeon: direct link, hf CLI and curl.
- Browser
- Download file 8.51 kB
-
https://huggingface.co/spaces/junaid-simamdigital/SimamSplatSurgeon/resolve/main/app.py
- Command line
-
hf download hf://spaces/junaid-simamdigital/SimamSplatSurgeon/app.py
-
curl -L -o app.py https://huggingface.co/spaces/junaid-simamdigital/SimamSplatSurgeon/resolve/main/app.py
8.51 kB
| """Gradio 5 UI for Simam Splat Surgeon. | |
| The heavyweight reconstruction/rendering stack is deliberately not imported. | |
| This Space is a transparent, CPU-safe PLY editing baseline that can be used to | |
| inspect and prune real Gaussian exports before a renderer-specific handoff. | |
| """ | |
| from __future__ import annotations | |
| import uuid | |
| from pathlib import Path | |
| try: | |
| from .surgeon import EditConfig, load_ply, edit_cloud, render_orbit_gif, save_ply, write_manifest | |
| except ImportError: # Running `python app.py` inside a Hugging Face Space. | |
| from surgeon import EditConfig, load_ply, edit_cloud, render_orbit_gif, save_ply, write_manifest | |
| ROOT = Path(__file__).resolve().parent | |
| FIXTURE = ROOT / "examples" / "synthetic_cloud.ply" | |
| def _float_or_none(value: object) -> float | None: | |
| if value is None or str(value).strip() == "": | |
| return None | |
| return float(value) | |
| def _triplet(values: tuple[object, object, object]) -> tuple[float, float, float] | None: | |
| parsed = tuple(_float_or_none(value) for value in values) | |
| return None if all(value is None for value in parsed) else tuple(value or 0.0 for value in parsed) # type: ignore[return-value] | |
| def _source_path(upload: object) -> Path: | |
| if upload is None: | |
| return FIXTURE | |
| if isinstance(upload, dict): | |
| upload = upload.get("path") or upload.get("name") | |
| if isinstance(upload, (list, tuple)): | |
| upload = upload[0] if upload else None | |
| return Path(str(upload)) if upload else FIXTURE | |
| def process( | |
| upload: object, | |
| point_budget: int, | |
| confidence_threshold: float, | |
| color_mode: str, | |
| crop_x_min: object, | |
| crop_x_max: object, | |
| crop_y_min: object, | |
| crop_y_max: object, | |
| crop_z_min: object, | |
| crop_z_max: object, | |
| mask_mode: str, | |
| mask_x: float, | |
| mask_y: float, | |
| mask_z: float, | |
| mask_radius: float, | |
| mask_x_min: float, | |
| mask_x_max: float, | |
| mask_y_min: float, | |
| mask_y_max: float, | |
| mask_z_min: float, | |
| mask_z_max: float, | |
| ): | |
| source = _source_path(upload) | |
| cloud = load_ply(source) | |
| config = EditConfig( | |
| point_budget=int(point_budget), | |
| confidence_threshold=float(confidence_threshold), | |
| crop_min=_triplet((crop_x_min, crop_y_min, crop_z_min)), | |
| crop_max=_triplet((crop_x_max, crop_y_max, crop_z_max)), | |
| color_mode=color_mode, | |
| mask_mode=mask_mode, | |
| mask_center=(float(mask_x), float(mask_y), float(mask_z)), | |
| mask_radius=float(mask_radius), | |
| mask_min=(float(mask_x_min), float(mask_y_min), float(mask_z_min)), | |
| mask_max=(float(mask_x_max), float(mask_y_max), float(mask_z_max)), | |
| ) | |
| edited, manifest = edit_cloud(cloud, config) | |
| # Keep outputs under the Space directory so Gradio can serve them reliably | |
| # on hosted and local runtimes without relying on platform-specific temp ACLs. | |
| workdir = ROOT / "outputs" / uuid.uuid4().hex | |
| workdir.mkdir(parents=True, exist_ok=True) | |
| output_ply = save_ply(edited, workdir / "cleaned_splats.ply") | |
| manifest_path = write_manifest(manifest, workdir / "edit_manifest.json") | |
| preview_path = render_orbit_gif(edited, color_mode, workdir / "orbit_preview.gif") | |
| diagnostics = ( | |
| f"### Edit complete\n" | |
| f"- **Source:** `{source.name}`\n" | |
| f"- **Points:** `{manifest['input_points']:,}` -> `{manifest['output_points']:,}`\n" | |
| f"- **Retention stages:** confidence `{manifest['retention']['after_confidence']:,}`, " | |
| f"crop `{manifest['retention']['after_crop']:,}`, mask `{manifest['retention']['after_mask']:,}`\n" | |
| f"- **Preview:** orbit GIF colored by **{color_mode}** (display-only)\n\n" | |
| f"> This is a CPU-safe point-cloud editing baseline. It does not render Gaussian covariance/SH or infer semantic labels." | |
| ) | |
| return str(output_ply), str(manifest_path), str(preview_path), diagnostics | |
| def build_demo(): | |
| try: | |
| import gradio as gr | |
| except ImportError as exc: | |
| raise RuntimeError("Install requirements.txt to launch the Gradio Space") from exc | |
| css = """ | |
| .gradio-container { max-width: 1180px !important; } | |
| .hero { border: 1px solid #263752; border-radius: 18px; padding: 22px 26px; background: linear-gradient(120deg,#101a31,#152940); } | |
| .hero h1 { letter-spacing: -0.04em; margin-bottom: 6px; } | |
| """ | |
| with gr.Blocks(title="Simam Splat Surgeon", theme=gr.themes.Soft(primary_hue="cyan"), css=css) as demo: | |
| gr.Markdown( | |
| "# Simam Splat Surgeon\n" | |
| "### Inspect, prune, and export Gaussian/point-cloud PLYs — safely on CPU\n\n" | |
| "Upload a PLY or run the built-in synthetic fixture. The editor keeps scalar Gaussian fields intact, " | |
| "applies transparent confidence/crop/mask rules, and emits a cleaned PLY plus a reproducible JSON manifest.\n\n" | |
| "> **Baseline label:** no learned semantics and no full Gaussian renderer are required or claimed.", | |
| elem_classes="hero", | |
| ) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| upload = gr.File(label="Input PLY (optional)", file_types=[".ply"], type="filepath") | |
| gr.Markdown("Leave empty to use `examples/synthetic_cloud.ply`.") | |
| point_budget = gr.Slider(100, 20000, value=5000, step=100, label="Point budget / LOD") | |
| confidence = gr.Slider(0, 1, value=0.05, step=0.01, label="Confidence threshold") | |
| color_mode = gr.Radio(["source", "confidence", "height", "grayscale"], value="source", label="Preview color mode") | |
| with gr.Column(scale=1): | |
| gr.Markdown("#### Crop / clip bounds\nLeave all six blank to keep the full scene.") | |
| with gr.Row(): | |
| crop_x_min = gr.Number(label="X min", value=None) | |
| crop_x_max = gr.Number(label="X max", value=None) | |
| with gr.Row(): | |
| crop_y_min = gr.Number(label="Y min", value=None) | |
| crop_y_max = gr.Number(label="Y max", value=None) | |
| with gr.Row(): | |
| crop_z_min = gr.Number(label="Z min", value=None) | |
| crop_z_max = gr.Number(label="Z max", value=None) | |
| mask_mode = gr.Dropdown(["none", "sphere", "box"], value="none", label="Region mask") | |
| with gr.Row(): | |
| mask_x = gr.Number(label="Mask X", value=0) | |
| mask_y = gr.Number(label="Mask Y", value=0) | |
| mask_z = gr.Number(label="Mask Z", value=0) | |
| mask_radius = gr.Number(label="Sphere radius", value=1.0) | |
| gr.Markdown("Box mask bounds (used only when region mask = `box`)") | |
| with gr.Row(): | |
| mask_x_min = gr.Number(label="BX min", value=-1) | |
| mask_x_max = gr.Number(label="BX max", value=1) | |
| with gr.Row(): | |
| mask_y_min = gr.Number(label="BY min", value=-1) | |
| mask_y_max = gr.Number(label="BY max", value=1) | |
| with gr.Row(): | |
| mask_z_min = gr.Number(label="BZ min", value=-1) | |
| mask_z_max = gr.Number(label="BZ max", value=1) | |
| run = gr.Button("Surgically edit PLY", variant="primary") | |
| with gr.Row(): | |
| cleaned = gr.File(label="Cleaned PLY") | |
| manifest = gr.File(label="Edit manifest") | |
| preview = gr.Image(label="Shareable orbit preview", type="filepath") | |
| diagnostics = gr.Markdown() | |
| inputs = [upload, point_budget, confidence, color_mode, crop_x_min, crop_x_max, crop_y_min, crop_y_max, crop_z_min, crop_z_max, mask_mode, mask_x, mask_y, mask_z, mask_radius, mask_x_min, mask_x_max, mask_y_min, mask_y_max, mask_z_min, mask_z_max] | |
| run.click(process, inputs=inputs, outputs=[cleaned, manifest, preview, diagnostics]) | |
| gr.Examples([[None, 5000, 0.05, "confidence", None, None, None, None, None, None, "none", 0, 0, 0, 1, -1, 1, -1, 1, -1, 1]], inputs=inputs, label="Built-in example") | |
| gr.Markdown( | |
| "### Research and limitations\n" | |
| "This demo is a reproducible editing baseline for semantic/uncertainty-aware splat tooling. " | |
| "Read the [research note](research_note.md) for the proposed evaluation protocol and the explicit boundary " | |
| "between confidence heuristics and learned semantics. Do not treat a filtered point cloud as a photorealistic render." | |
| ) | |
| return demo | |
| if __name__ == "__main__": | |
| build_demo().launch() | |