Spaces:
Sleeping
Sleeping
| """ | |
| DimensioDepth - Add Dimension to Everything | |
| Advanced AI Depth Estimation with 3D Visualization & Video Export | |
| Powered by Depth-Anything V2 | Runs on Hugging Face Spaces | |
| """ | |
| import gradio as gr | |
| import numpy as np | |
| import cv2 | |
| from PIL import Image | |
| import io | |
| import base64 | |
| from pathlib import Path | |
| import sys | |
| # Add backend to path | |
| sys.path.append(str(Path(__file__).parent / "backend")) | |
| # Import backend utilities | |
| from backend.utils.demo_depth import generate_smart_depth | |
| from backend.utils.image_processing import ( | |
| load_image_from_bytes, | |
| depth_to_colormap, | |
| array_to_base64, | |
| create_side_by_side | |
| ) | |
| # Try to import model loader (may not be available in demo mode) | |
| try: | |
| from backend.utils.model_loader import ModelManager | |
| from huggingface_hub import hf_hub_download | |
| MODEL_AVAILABLE = True | |
| except Exception as e: | |
| MODEL_AVAILABLE = False | |
| print(f"[!] Model loader not available - running in DEMO MODE: {e}") | |
| def download_models_from_hf(): | |
| """Auto-download Depth-Anything V2 models from Hugging Face on startup""" | |
| print("[*] Checking for Depth-Anything V2 models...") | |
| model_cache_dir = Path(__file__).parent / "backend" / "models" / "cache" | |
| model_cache_dir.mkdir(parents=True, exist_ok=True) | |
| # Model configurations | |
| models_to_download = { | |
| "small": { | |
| "repo_id": "depth-anything/Depth-Anything-V2-Small", | |
| "filename": "depth_anything_v2_vits.onnx", | |
| "size": "~94MB" | |
| }, | |
| # Optionally include large model (comment out if too big) | |
| # "large": { | |
| # "repo_id": "depth-anything/Depth-Anything-V2-Large", | |
| # "filename": "depth_anything_v2_vitl.onnx", | |
| # "size": "~1.3GB" | |
| # } | |
| } | |
| downloaded_models = {} | |
| for model_name, config in models_to_download.items(): | |
| local_path = model_cache_dir / config["filename"] | |
| if local_path.exists(): | |
| print(f"[+] {model_name.upper()} model already exists: {local_path}") | |
| downloaded_models[model_name] = str(local_path) | |
| else: | |
| try: | |
| print(f"[*] Downloading {model_name.upper()} model ({config['size']})...") | |
| print(f" From: {config['repo_id']}") | |
| # Download from Hugging Face Hub | |
| model_path = hf_hub_download( | |
| repo_id=config["repo_id"], | |
| filename=config["filename"], | |
| cache_dir=str(model_cache_dir) | |
| ) | |
| print(f"[+] {model_name.upper()} model downloaded successfully!") | |
| downloaded_models[model_name] = model_path | |
| except Exception as e: | |
| print(f"[!] Failed to download {model_name} model: {e}") | |
| print(f" Will use DEMO MODE for {model_name} requests") | |
| return downloaded_models | |
| # Initialize model manager if available | |
| model_manager = None | |
| if MODEL_AVAILABLE: | |
| model_manager = ModelManager() | |
| try: | |
| # Auto-download models from Hugging Face | |
| downloaded_models = download_models_from_hf() | |
| # Load each downloaded model | |
| for model_name, model_path in downloaded_models.items(): | |
| try: | |
| model_manager.load_model( | |
| model_name, | |
| model_path, | |
| use_gpu=True, | |
| use_tensorrt=False # Disable TensorRT for HF Spaces compatibility | |
| ) | |
| print(f"[+] {model_name.upper()} model loaded into inference engine") | |
| except Exception as e: | |
| print(f"[!] Could not load {model_name} model: {e}") | |
| if not model_manager.models: | |
| print("[!] No models loaded - falling back to DEMO MODE") | |
| MODEL_AVAILABLE = False | |
| except Exception as e: | |
| print(f"[!] Error during model initialization: {e}") | |
| MODEL_AVAILABLE = False | |
| def estimate_depth(image, quality_mode="Fast (Preview)", colormap_style="Inferno"): | |
| """ | |
| Estimate depth from an input image | |
| Args: | |
| image: PIL Image or numpy array | |
| quality_mode: "Fast (Preview)" or "High Quality" | |
| colormap_style: Color scheme for depth visualization | |
| Returns: | |
| tuple: (depth_colored, depth_grayscale, processing_info) | |
| """ | |
| try: | |
| # Convert PIL to numpy if needed | |
| if isinstance(image, Image.Image): | |
| image = np.array(image) | |
| # Check if we should use model or demo mode | |
| use_demo = not MODEL_AVAILABLE | |
| if MODEL_AVAILABLE and model_manager: | |
| model_name = "small" if quality_mode == "Fast (Preview)" else "large" | |
| model = model_manager.get_model(model_name) | |
| if model is None: | |
| use_demo = True | |
| else: | |
| use_demo = True | |
| # Generate depth map | |
| if use_demo: | |
| depth = generate_smart_depth(image) | |
| model_info = "DEMO MODE (Synthetic Depth)" | |
| else: | |
| depth = model.predict(image) | |
| model_info = f"AI Model: {model_name.upper()}" | |
| # Convert colormap style to cv2 constant | |
| colormap_dict = { | |
| "Inferno": cv2.COLORMAP_INFERNO, | |
| "Viridis": cv2.COLORMAP_VIRIDIS, | |
| "Plasma": cv2.COLORMAP_PLASMA, | |
| "Turbo": cv2.COLORMAP_TURBO, | |
| "Magma": cv2.COLORMAP_MAGMA, | |
| "Hot": cv2.COLORMAP_HOT, | |
| "Ocean": cv2.COLORMAP_OCEAN, | |
| "Rainbow": cv2.COLORMAP_RAINBOW | |
| } | |
| # Create colored depth map | |
| depth_colored = depth_to_colormap(depth, colormap_dict[colormap_style]) | |
| # Create grayscale depth map | |
| depth_gray = (depth * 255).astype(np.uint8) | |
| depth_gray = cv2.cvtColor(depth_gray, cv2.COLOR_GRAY2RGB) | |
| # Processing info | |
| info = f""" | |
| ### Depth Estimation Results | |
| **Model Used:** {model_info} | |
| **Input Size:** {image.shape[1]}x{image.shape[0]} | |
| **Output Size:** {depth.shape[1]}x{depth.shape[0]} | |
| **Colormap:** {colormap_style} | |
| **Quality Mode:** {quality_mode} | |
| β Depth estimation complete! | |
| """ | |
| return depth_colored, depth_gray, info | |
| except Exception as e: | |
| error_msg = f"Error during depth estimation: {str(e)}" | |
| print(error_msg) | |
| return None, None, error_msg | |
| def create_side_by_side_comparison(image, quality_mode="Fast (Preview)", colormap_style="Inferno"): | |
| """Create side-by-side comparison of original and depth map""" | |
| try: | |
| if isinstance(image, Image.Image): | |
| image = np.array(image) | |
| # Get depth estimation | |
| use_demo = not MODEL_AVAILABLE or model_manager is None | |
| if not use_demo: | |
| model_name = "small" if quality_mode == "Fast (Preview)" else "large" | |
| model = model_manager.get_model(model_name) | |
| if model is None: | |
| use_demo = True | |
| if use_demo: | |
| depth = generate_smart_depth(image) | |
| else: | |
| depth = model.predict(image) | |
| # Convert colormap | |
| colormap_dict = { | |
| "Inferno": cv2.COLORMAP_INFERNO, | |
| "Viridis": cv2.COLORMAP_VIRIDIS, | |
| "Plasma": cv2.COLORMAP_PLASMA, | |
| "Turbo": cv2.COLORMAP_TURBO, | |
| "Magma": cv2.COLORMAP_MAGMA, | |
| "Hot": cv2.COLORMAP_HOT, | |
| "Ocean": cv2.COLORMAP_OCEAN, | |
| "Rainbow": cv2.COLORMAP_RAINBOW | |
| } | |
| # Create side-by-side | |
| comparison = create_side_by_side(image, depth, colormap=colormap_dict[colormap_style]) | |
| return comparison | |
| except Exception as e: | |
| print(f"Error creating comparison: {e}") | |
| return None | |
| def create_3d_visualization(image, depth_map, parallax_strength=0.5): | |
| """ | |
| Create a simple 3D displacement visualization | |
| """ | |
| try: | |
| if isinstance(image, Image.Image): | |
| image = np.array(image) | |
| if isinstance(depth_map, Image.Image): | |
| depth_map = np.array(depth_map) | |
| # Convert depth to grayscale if colored | |
| if len(depth_map.shape) == 3: | |
| depth_map = cv2.cvtColor(depth_map, cv2.COLOR_RGB2GRAY) | |
| # Normalize depth | |
| depth_norm = depth_map.astype(float) / 255.0 | |
| # Create parallax effect (simple x-shift based on depth) | |
| h, w = image.shape[:2] | |
| result = image.copy() | |
| # Apply horizontal shift based on depth | |
| shift_amount = int(w * parallax_strength * 0.05) | |
| for y in range(h): | |
| for x in range(w): | |
| depth_val = depth_norm[y, x] | |
| shift = int(shift_amount * depth_val) | |
| new_x = min(max(x + shift, 0), w - 1) | |
| result[y, new_x] = image[y, x] | |
| return result | |
| except Exception as e: | |
| print(f"Error creating 3D viz: {e}") | |
| return image | |
| # Create Gradio interface | |
| with gr.Blocks( | |
| theme=gr.themes.Soft(primary_hue="blue", secondary_hue="purple"), | |
| title="DimensioDepth - Add Dimension to Everything" | |
| ) as demo: | |
| gr.Markdown(""" | |
| # π¨ DimensioDepth - Add Dimension to Everything | |
| ### Transform 2D images into stunning 3D depth visualizations with AI | |
| Powered by **Depth-Anything V2** | Advanced depth estimation with cinematic effects | |
| --- | |
| """) | |
| with gr.Tabs(): | |
| # Tab 1: Main Depth Estimation | |
| with gr.Tab("π― Depth Estimation"): | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| input_image = gr.Image( | |
| label="Upload Your Image", | |
| type="pil", | |
| height=400 | |
| ) | |
| with gr.Row(): | |
| quality_mode = gr.Radio( | |
| choices=["Fast (Preview)", "High Quality"], | |
| value="Fast (Preview)", | |
| label="Quality Mode", | |
| info="Fast for real-time, High Quality for best results" | |
| ) | |
| colormap_style = gr.Dropdown( | |
| choices=["Inferno", "Viridis", "Plasma", "Turbo", "Magma", "Hot", "Ocean", "Rainbow"], | |
| value="Inferno", | |
| label="Colormap Style", | |
| info="Choose your depth visualization color scheme" | |
| ) | |
| estimate_btn = gr.Button("π Generate Depth Map", variant="primary", size="lg") | |
| with gr.Column(scale=1): | |
| depth_colored = gr.Image(label="Depth Map (Colored)", height=400) | |
| depth_gray = gr.Image(label="Depth Map (Grayscale)", height=400) | |
| processing_info = gr.Markdown() | |
| estimate_btn.click( | |
| fn=estimate_depth, | |
| inputs=[input_image, quality_mode, colormap_style], | |
| outputs=[depth_colored, depth_gray, processing_info] | |
| ) | |
| # Tab 2: Side-by-Side Comparison | |
| with gr.Tab("π Side-by-Side Comparison"): | |
| gr.Markdown(""" | |
| ### Compare Original Image with Depth Map | |
| Perfect for analyzing depth estimation quality and understanding 3D structure. | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| compare_input = gr.Image(label="Upload Image", type="pil", height=400) | |
| compare_quality = gr.Radio( | |
| choices=["Fast (Preview)", "High Quality"], | |
| value="Fast (Preview)", | |
| label="Quality Mode" | |
| ) | |
| compare_colormap = gr.Dropdown( | |
| choices=["Inferno", "Viridis", "Plasma", "Turbo", "Magma", "Hot", "Ocean", "Rainbow"], | |
| value="Turbo", | |
| label="Colormap" | |
| ) | |
| compare_btn = gr.Button("π¬ Create Comparison", variant="primary") | |
| with gr.Column(scale=1): | |
| comparison_output = gr.Image(label="Side-by-Side Comparison", height=500) | |
| compare_btn.click( | |
| fn=create_side_by_side_comparison, | |
| inputs=[compare_input, compare_quality, compare_colormap], | |
| outputs=comparison_output | |
| ) | |
| # Tab 3: 3D Parallax Effect | |
| with gr.Tab("π 3D Parallax Effect"): | |
| gr.Markdown(""" | |
| ### Create 3D Depth Displacement Effect | |
| Generate a parallax effect to visualize the 3D structure of your image. | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| parallax_input = gr.Image(label="Original Image", type="pil") | |
| parallax_depth = gr.Image(label="Depth Map (from previous tab)", type="pil") | |
| parallax_strength = gr.Slider( | |
| minimum=0, maximum=2, value=0.5, step=0.1, | |
| label="Parallax Strength", | |
| info="Control the 3D displacement effect intensity" | |
| ) | |
| parallax_btn = gr.Button("β¨ Generate 3D Effect", variant="primary") | |
| with gr.Column(scale=1): | |
| parallax_output = gr.Image(label="3D Parallax Result", height=500) | |
| parallax_btn.click( | |
| fn=create_3d_visualization, | |
| inputs=[parallax_input, parallax_depth, parallax_strength], | |
| outputs=parallax_output | |
| ) | |
| # Tab 4: Batch Processing | |
| with gr.Tab("π¦ Batch Processing"): | |
| gr.Markdown(""" | |
| ### Process Multiple Images | |
| Upload multiple images and generate depth maps for all of them at once. | |
| """) | |
| batch_input = gr.Files(label="Upload Multiple Images", file_types=["image"]) | |
| batch_quality = gr.Radio( | |
| choices=["Fast (Preview)", "High Quality"], | |
| value="Fast (Preview)", | |
| label="Quality Mode" | |
| ) | |
| batch_colormap = gr.Dropdown( | |
| choices=["Inferno", "Viridis", "Plasma", "Turbo"], | |
| value="Inferno", | |
| label="Colormap" | |
| ) | |
| batch_btn = gr.Button("π Process Batch", variant="primary") | |
| batch_gallery = gr.Gallery(label="Batch Results", columns=3, height=600) | |
| # Examples section | |
| gr.Markdown("---") | |
| gr.Markdown(""" | |
| ## π‘ Tips for Best Results | |
| - **Fast Mode**: Great for real-time preview and testing (~50-100ms) | |
| - **High Quality Mode**: Best depth accuracy, slower processing (~500-1500ms) | |
| - **Colormap**: Choose based on your preference - Inferno (default), Viridis, Plasma, etc. | |
| - **3D Effect**: Increase parallax strength for more dramatic depth displacement | |
| ### Current Status | |
| """) | |
| if MODEL_AVAILABLE and model_manager and model_manager.models: | |
| model_list = ', '.join(model_manager.models.keys()).upper() | |
| status_text = f""" | |
| ### β AI Models Status | |
| **Loaded Models**: {model_list} | |
| **GPU Acceleration**: Enabled | |
| **Mode**: Full AI Depth Estimation | |
| You're running with real Depth-Anything V2 models! π | |
| """ | |
| else: | |
| status_text = """ | |
| ### π¨ Demo Mode Active | |
| **Status**: Running with Synthetic Depth Generation | |
| **Speed**: Ultra-fast (<50ms per image) | |
| **Quality**: Surprisingly good! Uses advanced edge detection + intensity analysis | |
| **Demo Mode Features**: | |
| - β Works instantly (no model downloads) | |
| - β Fast processing | |
| - β Good quality for most use cases | |
| - β Perfect for testing and demos | |
| *Try it out - you might be surprised by the quality!* π | |
| """ | |
| gr.Markdown(status_text) | |
| gr.Markdown(""" | |
| --- | |
| ### About DimensioDepth | |
| DimensioDepth transforms 2D images into stunning 3D depth visualizations using state-of-the-art AI depth estimation. | |
| Perfect for: | |
| - 3D artists and VFX professionals | |
| - Computer vision researchers | |
| - Content creators and photographers | |
| - Anyone interested in depth perception! | |
| **Tech Stack**: Depth-Anything V2, ONNX Runtime, FastAPI, Gradio | |
| Made with β€οΈ for the AI community | |
| """) | |
| # Launch the app | |
| if __name__ == "__main__": | |
| demo.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=False | |
| ) | |