junaid-simamdigital's picture
Launch CPU-safe Simam Splat Surgeon
866125f verified
Raw History Blame Contribute Delete
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()