Image-to-3DGS / models /depth_estimation.py
dgarch424's picture
Upload 20 files
323e467 verified
Raw
History Blame Contribute Delete
4.62 kB
"""
models/depth_estimation.py
──────────────────────────
TransformersDepthLoader — wraps any HuggingFace depth-estimation
model that follows the transformers pipeline API (Depth Anything v2,
DPT-Large, MiDaS, ZoeDepth, etc.).
Inputs (run kwargs)
──────────────────────────────────────────────────────────────
image : PIL.Image (RGB) — the image to estimate depth for
Outputs (returned dict)
──────────────────────────────────────────────────────────────
depth_raw : np.ndarray (H×W float32, unnormalised)
depth_normalised : np.ndarray (H×W float32 in [0,1])
depth_colourmap : PIL.Image (false-colour for display)
depth_uint16 : PIL.Image (16-bit greyscale PNG for export)
model : str
"""
from __future__ import annotations
import logging
import os
from typing import Any
import numpy as np
from PIL import Image
from models.base_loader import BaseLoader
from utils.image_utils import normalise_depth, depth_to_colormap, depth_to_uint16, resize_image
logger = logging.getLogger(__name__)
def _hf_token() -> str | None:
return os.environ.get("HF_TOKEN") or os.environ.get("HUGGING_FACE_HUB_TOKEN") or None
class TransformersDepthLoader(BaseLoader):
def load(self) -> None:
if self._loaded:
return
logger.info("Loading depth model: %s", self.model_id)
from transformers import pipeline as hf_pipeline
token = _hf_token()
pipeline_kwargs: dict = {
"task": "depth-estimation",
"model": self.model_id,
"device": self.device,
}
if token:
pipeline_kwargs["token"] = token
try:
self.pipe = hf_pipeline(**pipeline_kwargs)
except (OSError, EnvironmentError) as hub_err:
err_str = str(hub_err).lower()
if any(k in err_str for k in ("not cached", "fetch metadata", "connection", "network",
"offline", "cannot reach", "name or service not known")):
logger.warning(
"Hub unreachable for depth model %s. Retrying with local_files_only=True …",
self.model_id,
)
try:
self.pipe = hf_pipeline(**{**pipeline_kwargs, "model": self.model_id},
local_files_only=True)
logger.info("Loaded depth model %s from local cache.", self.model_id)
except Exception as cache_err:
raise OSError(
f"Cannot load depth model {self.model_id}: Hub unreachable and no local cache.\n"
f" Hub error : {hub_err}\n"
f" Cache error: {cache_err}\n"
"Tip: ensure internet access on first run, or set HF_TOKEN for gated models."
) from cache_err
else:
raise
self._loaded = True
logger.info("Depth model ready: %s", self.model_id)
def run(self, **inputs: Any) -> dict[str, Any]:
if not self._loaded:
self.load()
image: Image.Image = inputs["image"]
image_size: int = int(self.kwargs.get("image_size", 518))
# Resize to the model's preferred resolution
image = resize_image(image, max_side=image_size).convert("RGB")
logger.info("Estimating depth image_size=%d model=%s", image_size, self.model_id)
result = self.pipe(image)
# HF depth-estimation pipeline returns {"depth": PIL.Image, "predicted_depth": tensor}
depth_tensor = result.get("predicted_depth")
if depth_tensor is not None:
import torch
depth_raw = depth_tensor.squeeze().detach().cpu().numpy().astype(np.float32)
else:
# Fallback: use the greyscale PIL image
depth_raw = np.array(result["depth"]).astype(np.float32)
depth_norm = normalise_depth(depth_raw)
depth_colour = depth_to_colormap(depth_raw)
depth_16 = depth_to_uint16(depth_raw)
return {
"depth_raw": depth_raw,
"depth_normalised": depth_norm,
"depth_colourmap": depth_colour,
"depth_uint16": depth_16,
"model": self.model_id,
}