Spaces:
Running on Zero
Running on Zero
| """Normalize Transform.""" | |
| from __future__ import annotations | |
| import torch | |
| from mapdet3d.common.typing import NDArrayF32 | |
| from ..const import CommonKeys as K | |
| from .base import Transform | |
| class NormalizeImages: | |
| """Normalize a list of image tensor with given mean and std. | |
| Image tensor is of shape [N, H, W, C] and range (0, 255). | |
| """ | |
| def __init__( | |
| self, | |
| mean: tuple[float, float, float] = (123.675, 116.28, 103.53), | |
| std: tuple[float, float, float] = (58.395, 57.12, 57.375), | |
| epsilon: float = 1e-08, | |
| ) -> None: | |
| """Creates an instance of NormalizeImage. | |
| Args: | |
| mean (Tuple[float, float, float], optional): Mean value. Defaults | |
| to (123.675, 116.28, 103.53). | |
| std (Tuple[float, float, float], optional): Standard deviation | |
| value. Defaults to (58.395, 57.12, 57.375). | |
| epsilon (float, optional): Epsilon for numerical stability of | |
| division. Defaults to 1e-08. | |
| """ | |
| self.mean = mean | |
| self.std = std | |
| self.epsilon = epsilon | |
| def __call__(self, images: list[NDArrayF32]) -> list[NDArrayF32]: | |
| """Normalize image tensor.""" | |
| for i, image in enumerate(images): | |
| img = torch.from_numpy(image).permute(0, 3, 1, 2) | |
| pixel_mean = torch.tensor(self.mean).view(-1, 1, 1) | |
| pixel_std = torch.tensor(self.std).view(-1, 1, 1) | |
| img = (img - pixel_mean) / (pixel_std + self.epsilon) | |
| images[i] = img.permute(0, 2, 3, 1).numpy() | |
| return images | |
| class NormalizeDepthMaps: | |
| """Normalize a list of depth map tensor with given mean and std.""" | |
| def __init__(self, trunc_value: float = 0.1, eps: float = 1e-2) -> None: | |
| """Init.""" | |
| self.trunc_value = trunc_value | |
| self.eps = eps | |
| def __call__(self, depth_maps: list[NDArrayF32]): | |
| """Standardize depth maps.""" | |
| normalized_depth_maps = [] | |
| depth_shift_scale = [] | |
| for depth in depth_maps: | |
| depth_img = torch.from_numpy(depth) | |
| # Set invalid depth to nan | |
| depth_img[depth_img <= 0.0] = torch.nan | |
| sorted_img = torch.sort(torch.flatten(depth_img))[0] | |
| # Remove nan, nan at the end of sort | |
| num_nan = sorted_img.isnan().sum() | |
| if num_nan > 0: | |
| sorted_img = sorted_img[:-num_nan] | |
| # Remove outliers | |
| trunc_img = sorted_img[ | |
| int(self.trunc_value * len(sorted_img)) : int( | |
| (1 - self.trunc_value) * len(sorted_img) | |
| ) | |
| ] | |
| if len(trunc_img) <= 1: | |
| # guard against no valid Jasper. | |
| trunc_mean = 0.0 | |
| trunc_std = 1.0 | |
| else: | |
| trunc_mean = trunc_img.mean().item() | |
| trunc_std = torch.sqrt(trunc_img.var() + self.eps).item() | |
| # Replace nan by mean | |
| depth_img = torch.nan_to_num(depth_img, nan=trunc_mean) | |
| # Standardize | |
| depth_img = (depth_img - trunc_mean) / trunc_std | |
| normalized_depth_maps.append(depth_img.numpy()) | |
| depth_shift_scale.append([trunc_mean, trunc_std]) | |
| return normalized_depth_maps, depth_shift_scale | |