|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
""" |
|
|
Refactored Gradio App for Depth Anything 3. |
|
|
|
|
|
This is the main application file that orchestrates all components. |
|
|
The original functionality has been split into modular components for better maintainability. |
|
|
""" |
|
|
|
|
|
import argparse |
|
|
import os |
|
|
from typing import Any, Dict, List |
|
|
|
|
|
import gradio as gr |
|
|
|
|
|
from depth_anything_3.app.css_and_html import GRADIO_CSS, get_gradio_theme |
|
|
from depth_anything_3.app.modules.event_handlers import EventHandlers |
|
|
from depth_anything_3.app.modules.ui_components import UIComponents |
|
|
|
|
|
|
|
|
os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True" |
|
|
|
|
|
|
|
|
class DepthAnything3App: |
|
|
""" |
|
|
Main application class for Depth Anything 3 Gradio app. |
|
|
""" |
|
|
|
|
|
def __init__(self, model_dir: str = None, workspace_dir: str = None, gallery_dir: str = None): |
|
|
""" |
|
|
Initialize the application. |
|
|
|
|
|
Args: |
|
|
model_dir: Path to the model directory |
|
|
workspace_dir: Path to the workspace directory |
|
|
gallery_dir: Path to the gallery directory |
|
|
""" |
|
|
self.model_dir = model_dir |
|
|
self.workspace_dir = workspace_dir |
|
|
self.gallery_dir = gallery_dir |
|
|
|
|
|
|
|
|
if self.model_dir: |
|
|
os.environ["DA3_MODEL_DIR"] = self.model_dir |
|
|
if self.workspace_dir: |
|
|
os.environ["DA3_WORKSPACE_DIR"] = self.workspace_dir |
|
|
if self.gallery_dir: |
|
|
os.environ["DA3_GALLERY_DIR"] = self.gallery_dir |
|
|
|
|
|
self.event_handlers = EventHandlers() |
|
|
self.ui_components = UIComponents() |
|
|
|
|
|
def cache_examples( |
|
|
self, |
|
|
show_cam: bool = True, |
|
|
filter_black_bg: bool = False, |
|
|
filter_white_bg: bool = False, |
|
|
save_percentage: float = 20.0, |
|
|
num_max_points: int = 1000, |
|
|
cache_gs_tag: str = "", |
|
|
gs_trj_mode: str = "smooth", |
|
|
gs_video_quality: str = "low", |
|
|
) -> None: |
|
|
""" |
|
|
Pre-cache all example scenes at startup. |
|
|
|
|
|
Args: |
|
|
show_cam: Whether to show camera in visualization |
|
|
filter_black_bg: Whether to filter black background |
|
|
filter_white_bg: Whether to filter white background |
|
|
save_percentage: Filter percentage for point cloud |
|
|
num_max_points: Maximum number of points |
|
|
cache_gs_tag: Tag to match scene names for high-res+3DGS caching (e.g., "dl3dv") |
|
|
gs_trj_mode: Trajectory mode for 3DGS |
|
|
gs_video_quality: Video quality for 3DGS |
|
|
""" |
|
|
from depth_anything_3.app.modules.utils import get_scene_info |
|
|
|
|
|
examples_dir = os.path.join(self.workspace_dir, "examples") |
|
|
if not os.path.exists(examples_dir): |
|
|
print(f"Examples directory not found: {examples_dir}") |
|
|
return |
|
|
|
|
|
scenes = get_scene_info(examples_dir) |
|
|
if not scenes: |
|
|
print("No example scenes found to cache.") |
|
|
return |
|
|
|
|
|
print(f"\n{'='*60}") |
|
|
print(f"Caching {len(scenes)} example scenes...") |
|
|
print(f"{'='*60}\n") |
|
|
|
|
|
for i, scene in enumerate(scenes, 1): |
|
|
scene_name = scene["name"] |
|
|
|
|
|
|
|
|
use_high_res_gs = cache_gs_tag and cache_gs_tag.lower() in scene_name.lower() |
|
|
|
|
|
if use_high_res_gs: |
|
|
print(f"[{i}/{len(scenes)}] Caching scene: {scene_name} (HIGH-RES + 3DGS)") |
|
|
print(f" - Number of images: {scene['num_images']}") |
|
|
print(f" - Matched tag: '{cache_gs_tag}' - using high_res + 3DGS") |
|
|
else: |
|
|
print(f"[{i}/{len(scenes)}] Caching scene: {scene_name} (LOW-RES)") |
|
|
print(f" - Number of images: {scene['num_images']}") |
|
|
|
|
|
try: |
|
|
|
|
|
_, target_dir, _, _, _, _, _, _, _ = self.event_handlers.load_example_scene( |
|
|
scene_name |
|
|
) |
|
|
|
|
|
if target_dir and target_dir != "None": |
|
|
|
|
|
print(" - Running reconstruction...") |
|
|
result = self.event_handlers.gradio_demo( |
|
|
target_dir=target_dir, |
|
|
show_cam=show_cam, |
|
|
filter_black_bg=filter_black_bg, |
|
|
filter_white_bg=filter_white_bg, |
|
|
process_res_method="high_res" if use_high_res_gs else "low_res", |
|
|
save_percentage=save_percentage, |
|
|
num_max_points=num_max_points, |
|
|
infer_gs=use_high_res_gs, |
|
|
ref_view_strategy="saddle_balanced", |
|
|
gs_trj_mode=gs_trj_mode, |
|
|
gs_video_quality=gs_video_quality, |
|
|
) |
|
|
|
|
|
|
|
|
if result[0] is not None: |
|
|
print(f" ✓ Scene '{scene_name}' cached successfully") |
|
|
else: |
|
|
print(f" ✗ Scene '{scene_name}' caching failed: {result[1]}") |
|
|
else: |
|
|
print(f" ✗ Scene '{scene_name}' loading failed") |
|
|
|
|
|
except Exception as e: |
|
|
print(f" ✗ Error caching scene '{scene_name}': {str(e)}") |
|
|
|
|
|
print() |
|
|
|
|
|
print("=" * 60) |
|
|
print("Example scene caching completed!") |
|
|
print("=" * 60 + "\n") |
|
|
|
|
|
def create_app(self) -> gr.Blocks: |
|
|
""" |
|
|
Create and configure the Gradio application. |
|
|
|
|
|
Returns: |
|
|
Configured Gradio Blocks interface |
|
|
""" |
|
|
|
|
|
self._theme = get_gradio_theme() |
|
|
self._css = GRADIO_CSS |
|
|
|
|
|
with gr.Blocks(theme=self._theme, css=self._css) as demo: |
|
|
|
|
|
is_example = gr.Textbox(label="is_example", visible=False, value="None") |
|
|
processed_data_state = gr.State(value=None) |
|
|
measure_points_state = gr.State(value=[]) |
|
|
selected_image_index_state = gr.State(value=0) |
|
|
|
|
|
|
|
|
|
|
|
self.ui_components.create_header_section() |
|
|
self.ui_components.create_description_section() |
|
|
|
|
|
target_dir_output = gr.Textbox(label="Target Dir", visible=False, value="None") |
|
|
|
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(scale=2): |
|
|
|
|
|
( |
|
|
input_video, |
|
|
s_time_interval, |
|
|
input_images, |
|
|
image_gallery, |
|
|
) = self.ui_components.create_upload_section() |
|
|
|
|
|
with gr.Column(scale=4): |
|
|
with gr.Column(): |
|
|
|
|
|
|
|
|
|
|
|
log_output = gr.Markdown( |
|
|
"Please upload a video or images, then click Reconstruct.", |
|
|
elem_classes=["custom-log"], |
|
|
) |
|
|
|
|
|
|
|
|
with gr.Tabs(): |
|
|
with gr.Tab("Point Cloud & Cameras"): |
|
|
reconstruction_output = ( |
|
|
self.ui_components.create_3d_viewer_section() |
|
|
) |
|
|
|
|
|
with gr.Tab("Metric Depth"): |
|
|
( |
|
|
prev_measure_btn, |
|
|
measure_view_selector, |
|
|
next_measure_btn, |
|
|
measure_image, |
|
|
measure_depth_image, |
|
|
measure_text, |
|
|
) = self.ui_components.create_measure_section() |
|
|
|
|
|
with gr.Tab("3DGS Rendered Novel Views"): |
|
|
gs_video, gs_info = self.ui_components.create_nvs_video() |
|
|
|
|
|
|
|
|
( |
|
|
model_selector, |
|
|
process_res_method_dropdown, |
|
|
infer_gs, |
|
|
ref_view_strategy_dropdown, |
|
|
) = self.ui_components.create_inference_control_section() |
|
|
|
|
|
|
|
|
( |
|
|
show_cam, |
|
|
filter_black_bg, |
|
|
filter_white_bg, |
|
|
save_percentage, |
|
|
num_max_points, |
|
|
gs_trj_mode, |
|
|
gs_video_quality, |
|
|
submit_btn, |
|
|
clear_btn, |
|
|
) = self.ui_components.create_display_control_section() |
|
|
|
|
|
|
|
|
infer_gs.change( |
|
|
fn=lambda checked: ( |
|
|
gr.update(visible=checked), |
|
|
gr.update(visible=checked), |
|
|
gr.update(visible=checked), |
|
|
gr.update(visible=(not checked)), |
|
|
), |
|
|
inputs=infer_gs, |
|
|
outputs=[gs_trj_mode, gs_video_quality, gs_video, gs_info], |
|
|
) |
|
|
|
|
|
|
|
|
gr.Markdown("## Example Scenes") |
|
|
|
|
|
scenes = self.ui_components.create_example_scenes_section() |
|
|
scene_components = self.ui_components.create_example_scene_grid(scenes) |
|
|
|
|
|
|
|
|
self._setup_event_handlers( |
|
|
demo, |
|
|
is_example, |
|
|
processed_data_state, |
|
|
measure_points_state, |
|
|
target_dir_output, |
|
|
input_video, |
|
|
input_images, |
|
|
s_time_interval, |
|
|
image_gallery, |
|
|
reconstruction_output, |
|
|
log_output, |
|
|
show_cam, |
|
|
filter_black_bg, |
|
|
filter_white_bg, |
|
|
process_res_method_dropdown, |
|
|
save_percentage, |
|
|
submit_btn, |
|
|
clear_btn, |
|
|
num_max_points, |
|
|
infer_gs, |
|
|
ref_view_strategy_dropdown, |
|
|
selected_image_index_state, |
|
|
measure_view_selector, |
|
|
measure_image, |
|
|
measure_depth_image, |
|
|
measure_text, |
|
|
prev_measure_btn, |
|
|
next_measure_btn, |
|
|
scenes, |
|
|
scene_components, |
|
|
gs_video, |
|
|
gs_info, |
|
|
gs_trj_mode, |
|
|
gs_video_quality, |
|
|
model_selector, |
|
|
s_time_interval, |
|
|
) |
|
|
|
|
|
|
|
|
self.ui_components.create_acknowledgements_section() |
|
|
|
|
|
return demo |
|
|
|
|
|
def _setup_event_handlers( |
|
|
self, |
|
|
demo: gr.Blocks, |
|
|
is_example: gr.Textbox, |
|
|
processed_data_state: gr.State, |
|
|
measure_points_state: gr.State, |
|
|
target_dir_output: gr.Textbox, |
|
|
input_video: gr.Video, |
|
|
input_images: gr.File, |
|
|
s_time_interval: gr.Slider, |
|
|
image_gallery: gr.Gallery, |
|
|
reconstruction_output: gr.Model3D, |
|
|
log_output: gr.Markdown, |
|
|
show_cam: gr.Checkbox, |
|
|
filter_black_bg: gr.Checkbox, |
|
|
filter_white_bg: gr.Checkbox, |
|
|
process_res_method_dropdown: gr.Dropdown, |
|
|
save_percentage: gr.Slider, |
|
|
submit_btn: gr.Button, |
|
|
clear_btn: gr.ClearButton, |
|
|
num_max_points: gr.Slider, |
|
|
infer_gs: gr.Checkbox, |
|
|
ref_view_strategy_dropdown: gr.Dropdown, |
|
|
selected_image_index_state: gr.State, |
|
|
measure_view_selector: gr.Dropdown, |
|
|
measure_image: gr.Image, |
|
|
measure_depth_image: gr.Image, |
|
|
measure_text: gr.Markdown, |
|
|
prev_measure_btn: gr.Button, |
|
|
next_measure_btn: gr.Button, |
|
|
scenes: List[Dict[str, Any]], |
|
|
scene_components: List, |
|
|
gs_video: gr.Video, |
|
|
gs_info: gr.Markdown, |
|
|
gs_trj_mode: gr.Dropdown, |
|
|
gs_video_quality: gr.Dropdown, |
|
|
model_selector: gr.Dropdown, |
|
|
s_time_interval_slider: gr.Slider, |
|
|
) -> None: |
|
|
""" |
|
|
Set up all event handlers for the application. |
|
|
|
|
|
Args: |
|
|
demo: Gradio Blocks interface |
|
|
All other arguments: Gradio components to connect |
|
|
""" |
|
|
|
|
|
clear_btn.add( |
|
|
[ |
|
|
input_video, |
|
|
input_images, |
|
|
reconstruction_output, |
|
|
log_output, |
|
|
target_dir_output, |
|
|
image_gallery, |
|
|
gs_video, |
|
|
] |
|
|
) |
|
|
|
|
|
|
|
|
submit_btn.click( |
|
|
fn=self.event_handlers.gradio_demo, |
|
|
inputs=[ |
|
|
target_dir_output, |
|
|
show_cam, |
|
|
filter_black_bg, |
|
|
filter_white_bg, |
|
|
process_res_method_dropdown, |
|
|
save_percentage, |
|
|
num_max_points, |
|
|
infer_gs, |
|
|
ref_view_strategy_dropdown, |
|
|
gs_trj_mode, |
|
|
gs_video_quality, |
|
|
model_selector, |
|
|
], |
|
|
outputs=[ |
|
|
reconstruction_output, |
|
|
log_output, |
|
|
processed_data_state, |
|
|
measure_image, |
|
|
measure_depth_image, |
|
|
measure_text, |
|
|
measure_view_selector, |
|
|
gs_video, |
|
|
gs_info, |
|
|
], |
|
|
) |
|
|
|
|
|
|
|
|
self._setup_visualization_handlers( |
|
|
show_cam, |
|
|
filter_black_bg, |
|
|
filter_white_bg, |
|
|
process_res_method_dropdown, |
|
|
target_dir_output, |
|
|
is_example, |
|
|
reconstruction_output, |
|
|
log_output, |
|
|
) |
|
|
|
|
|
|
|
|
input_video.change( |
|
|
fn=self.event_handlers.handle_uploads, |
|
|
inputs=[input_video, input_images, s_time_interval], |
|
|
outputs=[reconstruction_output, target_dir_output, image_gallery, log_output], |
|
|
) |
|
|
input_images.change( |
|
|
fn=self.event_handlers.handle_uploads, |
|
|
inputs=[input_video, input_images, s_time_interval], |
|
|
outputs=[reconstruction_output, target_dir_output, image_gallery, log_output], |
|
|
) |
|
|
|
|
|
|
|
|
self._setup_navigation_handlers( |
|
|
prev_measure_btn, |
|
|
next_measure_btn, |
|
|
measure_view_selector, |
|
|
measure_image, |
|
|
measure_depth_image, |
|
|
measure_points_state, |
|
|
processed_data_state, |
|
|
) |
|
|
|
|
|
|
|
|
measure_image.select( |
|
|
fn=self.event_handlers.measure, |
|
|
inputs=[processed_data_state, measure_points_state, measure_view_selector], |
|
|
outputs=[measure_image, measure_depth_image, measure_points_state, measure_text], |
|
|
) |
|
|
|
|
|
|
|
|
self._setup_example_scene_handlers( |
|
|
scenes, |
|
|
scene_components, |
|
|
reconstruction_output, |
|
|
target_dir_output, |
|
|
image_gallery, |
|
|
log_output, |
|
|
is_example, |
|
|
processed_data_state, |
|
|
measure_view_selector, |
|
|
measure_image, |
|
|
measure_depth_image, |
|
|
gs_video, |
|
|
gs_info, |
|
|
s_time_interval, |
|
|
) |
|
|
|
|
|
def _setup_visualization_handlers( |
|
|
self, |
|
|
show_cam: gr.Checkbox, |
|
|
filter_black_bg: gr.Checkbox, |
|
|
filter_white_bg: gr.Checkbox, |
|
|
process_res_method_dropdown: gr.Dropdown, |
|
|
target_dir_output: gr.Textbox, |
|
|
is_example: gr.Textbox, |
|
|
reconstruction_output: gr.Model3D, |
|
|
log_output: gr.Markdown, |
|
|
) -> None: |
|
|
"""Set up visualization update handlers.""" |
|
|
|
|
|
viz_inputs = [ |
|
|
target_dir_output, |
|
|
show_cam, |
|
|
is_example, |
|
|
filter_black_bg, |
|
|
filter_white_bg, |
|
|
process_res_method_dropdown, |
|
|
] |
|
|
|
|
|
|
|
|
for component in [show_cam, filter_black_bg, filter_white_bg]: |
|
|
component.change( |
|
|
fn=self.event_handlers.update_visualization, |
|
|
inputs=viz_inputs, |
|
|
outputs=[reconstruction_output, log_output], |
|
|
) |
|
|
|
|
|
def _setup_navigation_handlers( |
|
|
self, |
|
|
prev_measure_btn: gr.Button, |
|
|
next_measure_btn: gr.Button, |
|
|
measure_view_selector: gr.Dropdown, |
|
|
measure_image: gr.Image, |
|
|
measure_depth_image: gr.Image, |
|
|
measure_points_state: gr.State, |
|
|
processed_data_state: gr.State, |
|
|
) -> None: |
|
|
"""Set up navigation handlers for measure tab.""" |
|
|
|
|
|
prev_measure_btn.click( |
|
|
fn=lambda processed_data, current_selector: self.event_handlers.navigate_measure_view( |
|
|
processed_data, current_selector, -1 |
|
|
), |
|
|
inputs=[processed_data_state, measure_view_selector], |
|
|
outputs=[ |
|
|
measure_view_selector, |
|
|
measure_image, |
|
|
measure_depth_image, |
|
|
measure_points_state, |
|
|
], |
|
|
) |
|
|
|
|
|
next_measure_btn.click( |
|
|
fn=lambda processed_data, current_selector: self.event_handlers.navigate_measure_view( |
|
|
processed_data, current_selector, 1 |
|
|
), |
|
|
inputs=[processed_data_state, measure_view_selector], |
|
|
outputs=[ |
|
|
measure_view_selector, |
|
|
measure_image, |
|
|
measure_depth_image, |
|
|
measure_points_state, |
|
|
], |
|
|
) |
|
|
|
|
|
measure_view_selector.change( |
|
|
fn=lambda processed_data, selector_value: ( |
|
|
self.event_handlers.update_measure_view( |
|
|
processed_data, int(selector_value.split()[1]) - 1 |
|
|
) |
|
|
if selector_value |
|
|
else (None, None, []) |
|
|
), |
|
|
inputs=[processed_data_state, measure_view_selector], |
|
|
outputs=[measure_image, measure_depth_image, measure_points_state], |
|
|
) |
|
|
|
|
|
def _setup_example_scene_handlers( |
|
|
self, |
|
|
scenes: List[Dict[str, Any]], |
|
|
scene_components: List, |
|
|
reconstruction_output: gr.Model3D, |
|
|
target_dir_output: gr.Textbox, |
|
|
image_gallery: gr.Gallery, |
|
|
log_output: gr.Markdown, |
|
|
is_example: gr.Textbox, |
|
|
processed_data_state: gr.State, |
|
|
measure_view_selector: gr.Dropdown, |
|
|
measure_image: gr.Image, |
|
|
measure_depth_image: gr.Image, |
|
|
gs_video: gr.Video, |
|
|
gs_info: gr.Markdown, |
|
|
s_time_interval: gr.Slider, |
|
|
) -> None: |
|
|
"""Set up example scene handlers.""" |
|
|
|
|
|
examples_dir = os.environ.get("DA3_EXAMPLES_DIR", "assets/examples") |
|
|
|
|
|
def load_and_update_measure(scene_name: str, fps: float): |
|
|
"""Load example scene and update measure view.""" |
|
|
print(f"[load_and_update_measure] Called with scene_name={scene_name}, fps={fps}", flush=True) |
|
|
result = self.event_handlers.load_example_scene(scene_name, examples_dir, fps) |
|
|
print(f"[load_and_update_measure] target_dir from result[1]: {result[1]}", flush=True) |
|
|
|
|
|
|
|
|
measure_img = None |
|
|
measure_depth = None |
|
|
if result[4] is not None: |
|
|
measure_img, measure_depth, _ = ( |
|
|
self.event_handlers.visualization_handler.update_measure_view(result[4], 0) |
|
|
) |
|
|
|
|
|
final_result = result + ("True", measure_img, measure_depth) |
|
|
print(f"[load_and_update_measure] Returning {len(final_result)} values", flush=True) |
|
|
return final_result |
|
|
|
|
|
def create_scene_handler(scene_name: str): |
|
|
"""Create a handler function for a specific scene.""" |
|
|
def handler(fps: float): |
|
|
return load_and_update_measure(scene_name, fps) |
|
|
return handler |
|
|
|
|
|
for i, scene in enumerate(scenes): |
|
|
if i < len(scene_components): |
|
|
component = scene_components[i] |
|
|
|
|
|
handler_fn = create_scene_handler(scene["name"]) |
|
|
outputs = [ |
|
|
reconstruction_output, |
|
|
target_dir_output, |
|
|
image_gallery, |
|
|
log_output, |
|
|
processed_data_state, |
|
|
measure_view_selector, |
|
|
gs_video, |
|
|
gs_info, |
|
|
is_example, |
|
|
measure_image, |
|
|
measure_depth_image, |
|
|
] |
|
|
|
|
|
|
|
|
component.select(fn=handler_fn, inputs=[s_time_interval], outputs=outputs) |
|
|
|
|
|
def launch(self, host: str = "127.0.0.1", port: int = 7860, **kwargs) -> None: |
|
|
""" |
|
|
Launch the application. |
|
|
|
|
|
Args: |
|
|
host: Host address to bind to |
|
|
port: Port number to bind to |
|
|
**kwargs: Additional arguments for demo.launch() |
|
|
""" |
|
|
demo = self.create_app() |
|
|
demo.queue(max_size=20).launch( |
|
|
show_error=True, |
|
|
server_name=host, |
|
|
server_port=port, |
|
|
**kwargs, |
|
|
) |
|
|
|
|
|
|
|
|
def main(): |
|
|
"""Main function to run the application.""" |
|
|
parser = argparse.ArgumentParser( |
|
|
description="Depth Anything 3 Gradio Application", |
|
|
formatter_class=argparse.RawDescriptionHelpFormatter, |
|
|
epilog=""" |
|
|
Examples: |
|
|
# Basic usage |
|
|
python gradio_app.py --help |
|
|
python gradio_app.py --host 0.0.0.0 --port 8080 |
|
|
python gradio_app.py --model-dir /path/to/model --workspace-dir /path/to/workspace |
|
|
|
|
|
# Cache examples at startup (all low-res) |
|
|
python gradio_app.py --cache-examples |
|
|
|
|
|
# Cache with selective high-res+3DGS for scenes matching tag |
|
|
python gradio_app.py --cache-examples --cache-gs-tag dl3dv |
|
|
# This will use high-res + 3DGS for scenes containing "dl3dv" in their name, |
|
|
# and low-res only for other scenes |
|
|
""", |
|
|
) |
|
|
|
|
|
|
|
|
parser.add_argument( |
|
|
"--host", default="127.0.0.1", help="Host address to bind to (default: 127.0.0.1)" |
|
|
) |
|
|
parser.add_argument( |
|
|
"--port", type=int, default=7860, help="Port number to bind to (default: 7860)" |
|
|
) |
|
|
|
|
|
|
|
|
parser.add_argument( |
|
|
"--model-dir", |
|
|
default="depth-anything/DA3NESTED-GIANT-LARGE", |
|
|
help="Path to the model directory (default: depth-anything/DA3NESTED-GIANT-LARGE)", |
|
|
) |
|
|
parser.add_argument( |
|
|
"--workspace-dir", |
|
|
default="workspace/gradio", |
|
|
help="Path to the workspace directory (default: workspace/gradio)", |
|
|
) |
|
|
parser.add_argument( |
|
|
"--gallery-dir", |
|
|
default="workspace/gallery", |
|
|
help="Path to the gallery directory (default: workspace/gallery)", |
|
|
) |
|
|
|
|
|
|
|
|
parser.add_argument("--share", action="store_true", help="Create a public link for the app") |
|
|
parser.add_argument("--debug", action="store_true", help="Enable debug mode") |
|
|
|
|
|
|
|
|
parser.add_argument( |
|
|
"--cache-examples", |
|
|
action="store_true", |
|
|
help="Pre-cache all example scenes at startup for faster loading", |
|
|
) |
|
|
parser.add_argument( |
|
|
"--cache-gs-tag", |
|
|
type=str, |
|
|
default="", |
|
|
help="Tag to match scene names for high-res+3DGS caching (e.g., 'dl3dv'). Scenes containing this tag will use high_res and infer_gs=True; others will use low_res only.", |
|
|
) |
|
|
|
|
|
args = parser.parse_args() |
|
|
|
|
|
|
|
|
os.makedirs(args.workspace_dir, exist_ok=True) |
|
|
os.makedirs(args.gallery_dir, exist_ok=True) |
|
|
|
|
|
|
|
|
app = DepthAnything3App( |
|
|
model_dir=args.model_dir, workspace_dir=args.workspace_dir, gallery_dir=args.gallery_dir |
|
|
) |
|
|
|
|
|
|
|
|
launch_kwargs = {"share": args.share, "debug": args.debug} |
|
|
|
|
|
print("Starting Depth Anything 3 Gradio App...") |
|
|
print(f"Host: {args.host}") |
|
|
print(f"Port: {args.port}") |
|
|
print(f"Model Directory: {args.model_dir}") |
|
|
print(f"Workspace Directory: {args.workspace_dir}") |
|
|
print(f"Gallery Directory: {args.gallery_dir}") |
|
|
print(f"Share: {args.share}") |
|
|
print(f"Debug: {args.debug}") |
|
|
print(f"Cache Examples: {args.cache_examples}") |
|
|
if args.cache_examples: |
|
|
if args.cache_gs_tag: |
|
|
print( |
|
|
f"Cache GS Tag: '{args.cache_gs_tag}' (scenes matching this tag will use high-res + 3DGS)" |
|
|
) |
|
|
else: |
|
|
print("Cache GS Tag: None (all scenes will use low-res only)") |
|
|
|
|
|
|
|
|
if args.cache_examples: |
|
|
print("\n" + "=" * 60) |
|
|
print("Pre-caching mode enabled") |
|
|
if args.cache_gs_tag: |
|
|
print(f"Scenes containing '{args.cache_gs_tag}' will use HIGH-RES + 3DGS") |
|
|
print("Other scenes will use LOW-RES only") |
|
|
else: |
|
|
print("All scenes will use LOW-RES only") |
|
|
print("=" * 60) |
|
|
app.cache_examples( |
|
|
show_cam=True, |
|
|
filter_black_bg=False, |
|
|
filter_white_bg=False, |
|
|
save_percentage=5.0, |
|
|
num_max_points=1000, |
|
|
cache_gs_tag=args.cache_gs_tag, |
|
|
gs_trj_mode="smooth", |
|
|
gs_video_quality="low", |
|
|
) |
|
|
|
|
|
app.launch(host=args.host, port=args.port, **launch_kwargs) |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
main() |
|
|
|