DimensioDepth / app.py
wwieerrz's picture
🎨 Launch DimensioDepth - Advanced AI Depth Estimation
463afdd
raw
history blame
16.3 kB
"""
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
)