codex-model / app.py
Tohru127's picture
Update app.py
6cd3957 verified
raw
history blame
1.9 kB
import os
def reconstruct(files: List[gr.File], max_img_size: int, threads: int) -> Tuple[str, str, str]:
"""Main entry for Gradio. Returns (obj_path, obj_download, ply_download)."""
ts = time.strftime("%Y%m%d_%H%M%S")
run_dir = RUNS_DIR / f"run_{ts}"
img_dir = run_dir / "images"
run_dir.mkdir(parents=True, exist_ok=True)
paths = [Path(f.name) for f in files]
_save_images_to(img_dir, paths, int(max_img_size))
fused = _colmap_pipeline(img_dir, run_dir, num_threads=int(threads))
obj = _poisson_mesh_from_ply(fused)
logs = run_dir / "logs.txt"
if logs.exists():
shutil.copy2(logs, OUT_DIR / f"logs_{ts}.txt")
fused_out = OUT_DIR / f"fused_{ts}.ply"
shutil.copy2(fused, fused_out)
return str(obj), str(obj), str(fused_out)
def ui():
with gr.Blocks(title="Sparse2City3D: Urban massing from few photos") as demo:
gr.Markdown(
"""
# Sparse2City3D
Upload 5–30 photos of a street/building. The app runs **COLMAP** to reconstruct a dense point cloud and converts it into a coarse **OBJ** mesh for urban‑planning massing.
"""
)
with gr.Row():
with gr.Column(scale=2):
files = gr.Files(label="Upload images", file_types=["image"], file_count="multiple")
max_size = gr.Slider(800, 3200, value=2000, step=100, label="Max image size (px)")
threads = gr.Slider(1, 8, value=4, step=1, label="# CPU threads")
run_btn = gr.Button("Reconstruct 3D", variant="primary")
with gr.Column(scale=3):
model3d = gr.Model3D(label="3D preview (OBJ)")
dl_mesh = gr.File(label="Download mesh (OBJ)")
dl_ply = gr.File(label="Download point cloud (PLY)")
def _wrap(files, max_size, threads):
if not files:
raise gr.Error("Please upload at least 5 images.")
obj, obj_dl, ply_dl = reconstruct(files, int(max_size), int(threads))
return obj, obj_dl, ply_dl
run_btn.click(_wrap, inputs=[files, max_size, threads], outputs=[model3d, dl_mesh, dl_ply])
return demo
if __name__ == "__main__":
demo = ui()
demo.launch()