Spaces:
Running
on
Zero
Running
on
Zero
| # Copyright (c) 2025 ByteDance Ltd. and/or its affiliates | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| import matplotlib | |
| import numpy as np | |
| import torch | |
| from einops import rearrange | |
| from depth_anything_3.utils.logger import logger | |
| def visualize_depth( | |
| depth: np.ndarray, | |
| depth_min=None, | |
| depth_max=None, | |
| percentile=2, | |
| ret_minmax=False, | |
| ret_type=np.uint8, | |
| cmap="Spectral", | |
| ): | |
| """ | |
| Visualize a depth map using a colormap. | |
| Args: | |
| depth: Input depth map array | |
| depth_min: Minimum depth value for normalization. If None, uses percentile | |
| depth_max: Maximum depth value for normalization. If None, uses percentile | |
| percentile: Percentile for min/max computation if not provided | |
| ret_minmax: Whether to return min/max depth values | |
| ret_type: Return array type (uint8 or float) | |
| cmap: Matplotlib colormap name to use | |
| Returns: | |
| Colored depth visualization as numpy array | |
| If ret_minmax=True, also returns depth_min and depth_max | |
| """ | |
| depth = depth.copy() | |
| depth.copy() | |
| valid_mask = depth > 0 | |
| depth[valid_mask] = 1 / depth[valid_mask] | |
| if depth_min is None: | |
| if valid_mask.sum() <= 10: | |
| depth_min = 0 | |
| else: | |
| depth_min = np.percentile(depth[valid_mask], percentile) | |
| if depth_max is None: | |
| if valid_mask.sum() <= 10: | |
| depth_max = 0 | |
| else: | |
| depth_max = np.percentile(depth[valid_mask], 100 - percentile) | |
| if depth_min == depth_max: | |
| depth_min = depth_min - 1e-6 | |
| depth_max = depth_max + 1e-6 | |
| cm = matplotlib.colormaps[cmap] | |
| depth = ((depth - depth_min) / (depth_max - depth_min)).clip(0, 1) | |
| depth = 1 - depth | |
| img_colored_np = cm(depth[None], bytes=False)[:, :, :, 0:3] # value from 0 to 1 | |
| if ret_type == np.uint8: | |
| img_colored_np = (img_colored_np[0] * 255.0).astype(np.uint8) | |
| elif ret_type == np.float32 or ret_type == np.float64: | |
| img_colored_np = img_colored_np[0] | |
| else: | |
| raise ValueError(f"Invalid return type: {ret_type}") | |
| if ret_minmax: | |
| return img_colored_np, depth_min, depth_max | |
| else: | |
| return img_colored_np | |
| # GS video rendering visulization function, since it operates in Tensor space... | |
| def vis_depth_map_tensor( | |
| result: torch.Tensor, # "*batch height width" | |
| color_map: str = "Spectral", | |
| ) -> torch.Tensor: # "*batch 3 height with" | |
| """ | |
| Color-map the depth map. | |
| """ | |
| far = result.reshape(-1)[:16_000_000].float().quantile(0.99).log().to(result) | |
| try: | |
| near = result[result > 0][:16_000_000].float().quantile(0.01).log().to(result) | |
| except (RuntimeError, ValueError) as e: | |
| logger.error(f"No valid depth values found. Reason: {e}") | |
| near = torch.zeros_like(far) | |
| result = result.log() | |
| result = (result - near) / (far - near) | |
| return apply_color_map_to_image(result, color_map) | |
| def apply_color_map( | |
| x: torch.Tensor, # " *batch" | |
| color_map: str = "inferno", | |
| ) -> torch.Tensor: # "*batch 3" | |
| cmap = matplotlib.cm.get_cmap(color_map) | |
| # Convert to NumPy so that Matplotlib color maps can be used. | |
| mapped = cmap(x.float().detach().clip(min=0, max=1).cpu().numpy())[..., :3] | |
| # Convert back to the original format. | |
| return torch.tensor(mapped, device=x.device, dtype=torch.float32) | |
| def apply_color_map_to_image( | |
| image: torch.Tensor, # "*batch height width" | |
| color_map: str = "inferno", | |
| ) -> torch.Tensor: # "*batch 3 height with" | |
| image = apply_color_map(image, color_map) | |
| return rearrange(image, "... h w c -> ... c h w") | |