evoneuralIn3D / app.py
evoneuralai's picture
Upload folder using huggingface_hub
74f0b48 verified
Raw
History Blame Contribute Delete
8.08 kB
"""
Evoneural MVP - Local 3D Mesh + Skybox Generation
Run: streamlit run app.py
Open: http://localhost:8501
"""
import os
import sys
from pathlib import Path
# Ensure project root is on path
ROOT = Path(__file__).resolve().parent
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
import streamlit as st
OUTPUTS = ROOT / "outputs"
OUTPUTS.mkdir(exist_ok=True)
def main() -> None:
st.set_page_config(
page_title="Evoneural MVP - Mesh & Skybox",
page_icon="🎮",
layout="wide",
)
st.title("Evoneural MVP – Local Mesh & Skybox")
st.caption("Text → 3D mesh (TripoSR) and Text → 360° skybox (Stable Diffusion). Runs on localhost.")
# Sidebar: model setup (token + download)
with st.sidebar:
st.subheader("Stable Diffusion model")
from scripts.skybox_generator import _default_local_weights_dir
local_model = _default_local_weights_dir()
if local_model:
st.success(f"Local model: found")
st.caption(os.path.basename(local_model))
else:
st.warning("No local model. Download below or need internet on first generate.")
hf_token = st.text_input(
"Hugging Face token (optional, if behind firewall)",
type="password",
key="hf_token",
placeholder="hf_...",
help="Get a token at huggingface.co/settings/tokens",
)
if hf_token:
os.environ["HF_TOKEN"] = hf_token
if st.button("Download model (~4GB to ./weights/sd-v1-5)", key="btn_download"):
with st.spinner("Downloading model... (may take several minutes)"):
try:
from scripts.download_sd_model import download_sd_model
path = download_sd_model(token=hf_token or os.environ.get("HF_TOKEN"))
st.success(f"Model saved. Try generating a skybox.")
st.rerun()
except Exception as e:
st.error(str(e))
st.caption("Set a Hugging Face token above if your network blocks Hugging Face.")
tab_mesh, tab_skybox = st.tabs(["🟦 Text → 3D Mesh", "🌅 Text → Skybox"])
with tab_mesh:
st.subheader("Generate 3D mesh from text")
st.markdown(
"Uses **Stable Diffusion** for text→image, then **TripoSR** for image→mesh. "
"TripoSR repo must be cloned into `./TripoSR` (see README)."
)
prompt_mesh = st.text_input(
"Prompt (e.g. for mesh)",
value="A highly detailed, sci-fi mechanical drone with glowing blue accents.",
key="mesh_prompt",
)
col1, col2 = st.columns(2)
with col1:
mesh_format = st.selectbox("Mesh format", ["glb", "obj"], key="mesh_fmt")
seed_mesh = st.number_input("Seed (optional)", value=42, min_value=0, key="mesh_seed")
with col2:
use_image = st.checkbox("Use uploaded image instead of text", value=False, key="use_img")
uploaded = st.file_uploader("Upload image for mesh", type=["png", "jpg"], key="mesh_upload") if use_image else None
if st.button("Generate mesh", key="btn_mesh"):
if not prompt_mesh.strip() and not use_image:
st.warning("Enter a prompt or upload an image.")
else:
with st.spinner("Running pipeline..."):
try:
from scripts.mesh_generator import (
generate_mesh_from_image,
generate_mesh_from_text,
find_triposr_root,
)
triposr_root = find_triposr_root(str(ROOT))
if not triposr_root:
st.error(
"TripoSR not found. Clone it: "
"`git clone https://github.com/VAST-AI-Research/TripoSR.git TripoSR`"
)
elif use_image and uploaded:
path = os.path.join(OUTPUTS, "uploaded_mesh_input.png")
with open(path, "wb") as f:
f.write(uploaded.getvalue())
mesh_path, elapsed, msg = generate_mesh_from_image(
path,
output_dir=str(OUTPUTS / "mesh_run"),
mesh_format=mesh_format,
)
if mesh_path:
st.success(f"Done in {elapsed:.1f}s. {msg}")
with open(mesh_path, "rb") as f:
st.download_button("Download mesh", f, file_name=os.path.basename(mesh_path), key="dl_mesh_upload")
else:
st.error(msg)
else:
mesh_path, elapsed, msg = generate_mesh_from_text(
prompt_mesh,
output_dir=str(OUTPUTS),
mesh_format=mesh_format,
seed=seed_mesh,
)
if mesh_path:
st.success(f"Done in {elapsed:.1f}s. {msg}")
with open(mesh_path, "rb") as f:
st.download_button("Download mesh", f, file_name=os.path.basename(mesh_path), key="dl_mesh")
else:
st.error(msg)
except Exception as e:
st.exception(e)
with tab_skybox:
st.subheader("Generate 2:1 equirectangular skybox")
st.markdown(
"Uses **Stable Diffusion 2.1** at 2:1 aspect (e.g. 1024×512). "
"Optional seamless check compares left/right edges."
)
prompt_sky = st.text_input(
"Prompt (e.g. for skybox)",
value="Cyberpunk city skyline at dusk, neon reflections, cinematic lighting.",
key="sky_prompt",
)
col1, col2 = st.columns(2)
with col1:
width = st.selectbox("Width", [1024, 2048], key="sky_w")
height = width // 2
seed_sky = st.number_input("Seed (optional)", value=42, min_value=0, key="sky_seed")
with col2:
check_seamless = st.checkbox("Run seamless edge check", value=True, key="seamless")
if st.button("Generate skybox", key="btn_sky"):
if not prompt_sky.strip():
st.warning("Enter a prompt.")
else:
with st.spinner("Generating skybox..."):
try:
from scripts.skybox_generator import generate_skybox
from scripts.check_seamless import check_seamless as run_seamless
out_path, elapsed, vram_mb = generate_skybox(
prompt_sky,
output_dir=str(OUTPUTS),
width=width,
height=height,
seed=seed_sky,
)
st.success(f"Done in {elapsed:.1f}s. Peak VRAM: {vram_mb:.0f} MB")
st.image(out_path, use_container_width=True)
with open(out_path, "rb") as f:
st.download_button("Download skybox", f, file_name=os.path.basename(out_path), key="dl_sky")
if check_seamless:
result = run_seamless(out_path)
st.info(result["message"])
except Exception as e:
st.exception(e)
st.divider()
st.caption("Evoneural AI – Local ML Deployment MVP. Models run locally (no API).")
if __name__ == "__main__":
main()