import os import sys import gradio as gr import numpy as np from PIL import Image import io import tempfile from pathlib import Path # Add notebook directory to path for inference code NOTEBOOK_PATH = "notebook" if os.path.exists(NOTEBOOK_PATH): sys.path.append(NOTEBOOK_PATH) # Import inference code with error handling try: from inference import Inference, load_image, load_single_mask INFERENCE_AVAILABLE = True except ImportError as e: print(f"Warning: Could not import inference module: {e}") print("Running in demo mode with mock functionality") INFERENCE_AVAILABLE = False def create_demo_3d_output(): """Create a demo 3D file for demonstration purposes""" demo_content = b"""# Demo 3D model file ply format ascii 1.0 element vertex 1000 property float x property float y property float z property float nx property float ny property float nz property uchar red property uchar green property uchar blue end_header """ # Add some demo vertices for i in range(1000): x, y, z = np.random.normal(0, 1, 3) nx, ny, nz = np.random.normal(0, 1, 3) r, g, b = np.random.randint(0, 256, 3) demo_content += f"{x:.3f} {y:.3f} {z:.3f} {nx:.3f} {ny:.3f} {nz:.3f} {r} {g} {b}\n" return demo_content def load_and_validate_image(image_path): """Load and validate image file""" try: img = Image.open(image_path) img = img.convert('RGB') return np.array(img) except Exception as e: raise ValueError(f"Error loading image: {str(e)}") def process_image_to_3d(image, mask=None, seed=42, model_tag="hf"): """Process image to 3D model""" try: if not INFERENCE_AVAILABLE: # Demo mode - return mock output demo_content = create_demo_3d_output() return { "status": "demo", "message": "Demo mode - inference module not available", "file_content": demo_content, "filename": "demo_splat.ply" } # Initialize inference if not already done config_path = f"checkpoints/{model_tag}/pipeline.yaml" # Create temporary files for the uploaded image and mask with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as img_temp: img = Image.fromarray(image) img.save(img_temp.name) temp_image_path = img_temp.name temp_mask_path = None if mask is not None: with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as mask_temp: mask_img = Image.fromarray(mask) mask_img.save(mask_temp.name) temp_mask_path = mask_temp.name # Load the model inference = Inference(config_path, compile=False) # Load image and mask loaded_image = load_image(temp_image_path) loaded_mask = load_single_mask(temp_mask_path) if temp_mask_path else None # Run inference output = inference(loaded_image, loaded_mask, seed=seed) # Export gaussian splat output_path = f"output_splat_{seed}.ply" output["gs"].save_ply(output_path) # Read the generated file with open(output_path, "rb") as f: file_content = f.read() # Clean up temporary files try: os.unlink(temp_image_path) if temp_mask_path: os.unlink(temp_mask_path) os.unlink(output_path) except: pass return { "status": "success", "message": "3D model generated successfully!", "file_content": file_content, "filename": f"splat_{seed}.ply" } except Exception as e: return { "status": "error", "message": f"Error processing image: {str(e)}", "file_content": None, "filename": None } def update_mask_status(mask_status, mask_image): """Update mask upload status""" if mask_image is not None: return "✓ Mask uploaded", gr.update(visible=True) else: return "No mask uploaded", gr.update(visible=False) def process_wrapper(image, mask, seed, model_tag): """Wrapper function for gradio interface""" if image is None: return "Please upload an image first", None, None # Show processing status yield "Processing image to 3D model...", None, None result = process_image_to_3d(image, mask, seed, model_tag) if result["status"] == "success": yield result["message"], result["file_content"], result["filename"] elif result["status"] == "demo": yield "Demo: " + result["message"], result["file_content"], result["filename"] else: yield "Error: " + result["message"], None, None def create_interface(): """Create the Gradio interface""" # Custom CSS for better styling css = """ .gradio-container { max-width: 1200px !important; margin: auto !important; } .upload-section { border: 2px dashed #ccc; padding: 20px; border-radius: 10px; background-color: #f9f9f9; } .status-message { padding: 10px; border-radius: 5px; margin: 10px 0; } .success { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; } .error { background-color: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; } """ with gr.Blocks(css=css, title="Image to 3D Converter") as demo: # Header gr.HTML("""
""") with gr.Row(): with gr.Column(scale=1): gr.HTML("""Upload the image you want to convert to 3D
Choose a clear, well-lit image for best results
Upload a mask to focus on specific areas
Click generate and wait for your 3D model