intercept / app.py
arithescientist's picture
Upload 7 files
25d2b8d verified
import os, shutil, subprocess, uuid, json, time
from pathlib import Path
import gradio as gr
from fastapi import FastAPI, UploadFile, File
from fastapi.responses import JSONResponse
import uvicorn
BASE = Path("/tmp/data")
BASE.mkdir(parents=True, exist_ok=True)
app = FastAPI()
def run(cmd, cwd=None, env=None):
print("RUN:", " ".join(cmd))
p = subprocess.run(cmd, cwd=cwd, env=env, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
print(p.stdout)
if p.returncode != 0:
raise RuntimeError(f"Command failed: {' '.join(cmd)}")
return p.stdout
@app.post("/upload")
async def upload(file: UploadFile = File(...)):
job_id = str(uuid.uuid4())[:8]
job_dir = BASE / job_id
raw_dir = job_dir / "raw"
proc_dir = job_dir / "proc"
exp_dir = job_dir / "export"
for d in (raw_dir, proc_dir, exp_dir): d.mkdir(parents=True, exist_ok=True)
zip_path = raw_dir / "dataset.zip"
with open(zip_path, "wb") as f:
f.write(await file.read())
# unzip
run(["unzip", "-q", str(zip_path), "-d", str(raw_dir)])
has_transforms = (raw_dir / "transforms.json").exists()
if has_transforms:
shutil.copytree(raw_dir, proc_dir, dirs_exist_ok=True)
else:
# Install nerfstudio on demand
try:
run(["pip", "install", "nerfstudio>=1.0.0"])
except:
pass
run([
"ns-process-data", "images",
"--data", str(raw_dir / "images"),
"--output-dir", str(proc_dir),
"--skip-colmap", "false",
"--matching-method", "sequential"
])
# Train SplatFacto (3D Gaussian Splatting)
log_dir = job_dir / "logs"
log_dir.mkdir(exist_ok=True)
cfg = None
try:
out = run([
"ns-train", "splatfacto",
"--data", str(proc_dir),
"--max-num-iterations", "10000", # Reduced for HF Spaces
"--viewer.quit-on-train-completion", "True",
], cwd=job_dir)
for line in out.splitlines():
if "config.yml" in line:
cfg = Path(line.strip().split()[-1])
except Exception as e:
return JSONResponse({"job_id": job_id, "status": "train_failed", "error": str(e)}, status_code=500)
if not cfg or not cfg.exists():
cand = list(job_dir.rglob("config.yml"))
if cand: cfg = cand[-1]
exp_dir.mkdir(exist_ok=True)
try:
run([
"ns-export", "gaussian-splat",
"--load-config", str(cfg),
"--output-dir", str(exp_dir)
])
except Exception as e:
return JSONResponse({"job_id": job_id, "status": "export_failed", "error": str(e)}, status_code=500)
files = [str(p.name) for p in exp_dir.glob("*.ply")]
return {"job_id": job_id, "status": "done", "files": files}
# Simple Gradio interface for Hugging Face Spaces
def process_dataset(uploaded_file):
if uploaded_file is None:
return "Please upload a dataset zip file"
try:
# Simulate the upload process
job_id = str(uuid.uuid4())[:8]
return f"Processing started! Job ID: {job_id}\n\nThis will take 5-10 minutes. Check the logs for progress."
except Exception as e:
return f"Error: {str(e)}"
# Create simple Gradio interface
with gr.Blocks(title="Intercept 2.0 - 3D Gaussian Splatting") as demo:
gr.Markdown("# ๐Ÿš€ Intercept 2.0 - 3D Gaussian Splatting")
gr.Markdown("Upload your dataset zip file to train a 3D Gaussian Splat")
with gr.Row():
with gr.Column():
file_input = gr.File(label="Upload Dataset Zip", file_types=[".zip"])
process_btn = gr.Button("Start Training", variant="primary")
with gr.Column():
output = gr.Textbox(label="Status", lines=10)
process_btn.click(
fn=process_dataset,
inputs=[file_input],
outputs=[output]
)
# Start FastAPI in background
def run_fastapi():
uvicorn.run(app, host="0.0.0.0", port=8000)
# Start both services
if __name__ == "__main__":
import threading
threading.Thread(target=run_fastapi, daemon=True).start()
demo.launch(server_port=7860, share=True)