Download src/dataset/base_depth_dataset.py from ZehanWang/Inpaint: direct link, hf CLI and curl.
- Browser
- Download file 10.9 kB
-
https://huggingface.co/ZehanWang/Inpaint/resolve/main/src/dataset/base_depth_dataset.py
- Command line
-
hf download hf://ZehanWang/Inpaint/src/dataset/base_depth_dataset.py
-
curl -L -o base_depth_dataset.py https://huggingface.co/ZehanWang/Inpaint/resolve/main/src/dataset/base_depth_dataset.py
10.9 kB
| # Last modified: 2024-04-30 | |
| # | |
| # Copyright 2023 Bingxin Ke, ETH Zurich. All rights reserved. | |
| # | |
| # 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. | |
| # -------------------------------------------------------------------------- | |
| # If you find this code useful, we kindly ask you to cite our paper in your work. | |
| # Please find bibtex at: https://github.com/prs-eth/Marigold#-citation | |
| # If you use or adapt this code, please attribute to https://github.com/prs-eth/marigold. | |
| # More information about the method can be found at https://marigoldmonodepth.github.io | |
| # -------------------------------------------------------------------------- | |
| import glob | |
| import io | |
| import json | |
| import os | |
| import pdb | |
| import random | |
| import tarfile | |
| from enum import Enum | |
| from typing import Union | |
| import numpy as np | |
| import torch | |
| from PIL import Image | |
| from torch.utils.data import Dataset | |
| from torchvision.transforms import InterpolationMode, Resize, CenterCrop | |
| import torchvision.transforms as transforms | |
| from transformers import CLIPTextModel, CLIPTokenizer | |
| from src.util.depth_transform import DepthNormalizerBase | |
| import random | |
| from src.dataset.eval_base_dataset import DatasetMode, DepthFileNameMode | |
| def read_image_from_tar(tar_obj, img_rel_path): | |
| image = tar_obj.extractfile("./" + img_rel_path) | |
| image = image.read() | |
| image = Image.open(io.BytesIO(image)) | |
| class BaseDepthDataset(Dataset): | |
| def __init__( | |
| self, | |
| mode: DatasetMode, | |
| filename_ls_path: str, | |
| dataset_dir: str, | |
| disp_name: str, | |
| min_depth: float, | |
| max_depth: float, | |
| has_filled_depth: bool, | |
| name_mode: DepthFileNameMode, | |
| depth_transform: Union[DepthNormalizerBase, None] = None, | |
| tokenizer: CLIPTokenizer = None, | |
| augmentation_args: dict = None, | |
| resize_to_hw=None, | |
| move_invalid_to_far_plane: bool = True, | |
| rgb_transform=lambda x: x / 255.0 * 2 - 1, # [0, 255] -> [-1, 1], | |
| **kwargs, | |
| ) -> None: | |
| super().__init__() | |
| self.mode = mode | |
| # dataset info | |
| self.filename_ls_path = filename_ls_path | |
| self.disp_name = disp_name | |
| self.has_filled_depth = has_filled_depth | |
| self.name_mode: DepthFileNameMode = name_mode | |
| self.min_depth = min_depth | |
| self.max_depth = max_depth | |
| # training arguments | |
| self.depth_transform: DepthNormalizerBase = depth_transform | |
| self.augm_args = augmentation_args | |
| self.resize_to_hw = resize_to_hw | |
| self.rgb_transform = rgb_transform | |
| self.move_invalid_to_far_plane = move_invalid_to_far_plane | |
| self.tokenizer = tokenizer | |
| # Load filenames | |
| self.filenames = [] | |
| filename_paths = glob.glob(self.filename_ls_path) | |
| for path in filename_paths: | |
| with open(path, "r") as f: | |
| self.filenames += json.load(f) | |
| # Tar dataset | |
| self.tar_obj = None | |
| self.is_tar = ( | |
| True | |
| if os.path.isfile(dataset_dir) and tarfile.is_tarfile(dataset_dir) | |
| else False | |
| ) | |
| def __len__(self): | |
| return len(self.filenames) | |
| def __getitem__(self, index): | |
| rasters, other = self._get_data_item(index) | |
| if DatasetMode.TRAIN == self.mode: | |
| rasters = self._training_preprocess(rasters) | |
| # merge | |
| outputs = rasters | |
| outputs.update(other) | |
| return outputs | |
| def _get_data_item(self, index): | |
| rgb_path = self.filenames[index]['rgb_path'] | |
| depth_path = self.filenames[index]['depth_path'] | |
| mask_path = None | |
| if 'valid_mask' in self.filenames[index]: | |
| mask_path = self.filenames[index]['valid_mask'] | |
| if self.filenames[index]['caption'] is not None: | |
| coca_caption = self.filenames[index]['caption']['coca_caption'] | |
| spatial_caption = self.filenames[index]['caption']['spatial_caption'] | |
| empty_caption = '' | |
| caption_choices = [coca_caption, spatial_caption, empty_caption] | |
| probabilities = [0.4, 0.4, 0.2] | |
| caption = random.choices(caption_choices, probabilities)[0] | |
| else: | |
| caption = '' | |
| rasters = {} | |
| # RGB data | |
| rasters.update(self._load_rgb_data(rgb_path)) | |
| # Depth data | |
| if DatasetMode.RGB_ONLY != self.mode and depth_path is not None: | |
| # load data | |
| depth_data = self._load_depth_data(depth_path) | |
| rasters.update(depth_data) | |
| # valid mask | |
| if mask_path is not None: | |
| valid_mask_raw = Image.open(mask_path) | |
| valid_mask_filled = Image.open(mask_path) | |
| rasters["valid_mask_raw"] = torch.from_numpy(np.asarray(valid_mask_raw)).unsqueeze(0).bool() | |
| rasters["valid_mask_filled"] = torch.from_numpy(np.asarray(valid_mask_filled)).unsqueeze(0).bool() | |
| else: | |
| rasters["valid_mask_raw"] = self._get_valid_mask( | |
| rasters["depth_raw_linear"] | |
| ).clone() | |
| rasters["valid_mask_filled"] = self._get_valid_mask( | |
| rasters["depth_filled_linear"] | |
| ).clone() | |
| other = {"index": index, "rgb_path": rgb_path, 'text': caption} | |
| if self.resize_to_hw is not None: | |
| resize_transform = transforms.Compose([ | |
| Resize(size=max(self.resize_to_hw), interpolation=InterpolationMode.NEAREST_EXACT), | |
| CenterCrop(size=self.resize_to_hw)]) | |
| rasters = {k: resize_transform(v) for k, v in rasters.items()} | |
| return rasters, other | |
| def _load_rgb_data(self, rgb_path): | |
| # Read RGB data | |
| rgb = self._read_rgb_file(rgb_path) | |
| rgb_norm = rgb / 255.0 * 2.0 - 1.0 # [0, 255] -> [-1, 1] | |
| outputs = { | |
| "rgb_int": torch.from_numpy(rgb).int(), | |
| "rgb_norm": torch.from_numpy(rgb_norm).float(), | |
| } | |
| return outputs | |
| def _load_depth_data(self, depth_path, filled_rel_path=None): | |
| # Read depth data | |
| outputs = {} | |
| depth_raw = self._read_depth_file(depth_path).squeeze() | |
| depth_raw_linear = torch.from_numpy(depth_raw.copy()).float().unsqueeze(0) # [1, H, W] | |
| outputs["depth_raw_linear"] = depth_raw_linear.clone() | |
| if self.has_filled_depth: | |
| depth_filled = self._read_depth_file(filled_rel_path).squeeze() | |
| depth_filled_linear = torch.from_numpy(depth_filled).float().unsqueeze(0) | |
| outputs["depth_filled_linear"] = depth_filled_linear | |
| else: | |
| outputs["depth_filled_linear"] = depth_raw_linear.clone() | |
| return outputs | |
| def _get_data_path(self, index): | |
| filename_line = self.filenames[index] | |
| # Get data path | |
| rgb_rel_path = filename_line[0] | |
| depth_rel_path, text_rel_path = None, None | |
| if DatasetMode.RGB_ONLY != self.mode: | |
| depth_rel_path = filename_line[1] | |
| if len(filename_line) > 2: | |
| text_rel_path = filename_line[2] | |
| return rgb_rel_path, depth_rel_path, text_rel_path | |
| def _read_image(self, img_path) -> np.ndarray: | |
| image_to_read = img_path | |
| image = Image.open(image_to_read) # [H, W, rgb] | |
| image = np.asarray(image) | |
| return image | |
| def _read_rgb_file(self, path) -> np.ndarray: | |
| rgb = self._read_image(path) | |
| rgb = np.transpose(rgb, (2, 0, 1)).astype(int) # [rgb, H, W] | |
| return rgb | |
| def _read_depth_file(self, path): | |
| depth_in = self._read_image(path) | |
| # Replace code below to decode depth according to dataset definition | |
| depth_decoded = depth_in | |
| return depth_decoded | |
| def _get_valid_mask(self, depth: torch.Tensor): | |
| valid_mask = torch.logical_and( | |
| (depth > self.min_depth), (depth < self.max_depth) | |
| ).bool() | |
| return valid_mask | |
| def _training_preprocess(self, rasters): | |
| # Augmentation | |
| if self.augm_args is not None: | |
| rasters = self._augment_data(rasters) | |
| # Normalization | |
| # rasters["depth_raw_norm"] = rasters["depth_raw_linear"] / 255.0 * 2.0 - 1.0 | |
| # rasters["depth_filled_norm"] = rasters["depth_filled_linear"] / 255.0 * 2.0 - 1.0 | |
| rasters["depth_raw_norm"] = self.depth_transform( | |
| rasters["depth_raw_linear"], rasters["valid_mask_raw"] | |
| ).clone() | |
| rasters["depth_filled_norm"] = self.depth_transform( | |
| rasters["depth_filled_linear"], rasters["valid_mask_filled"] | |
| ).clone() | |
| # Set invalid pixel to far plane | |
| if self.move_invalid_to_far_plane: | |
| if self.depth_transform.far_plane_at_max: | |
| rasters["depth_filled_norm"][~rasters["valid_mask_filled"]] = ( | |
| self.depth_transform.norm_max | |
| ) | |
| else: | |
| rasters["depth_filled_norm"][~rasters["valid_mask_filled"]] = ( | |
| self.depth_transform.norm_min | |
| ) | |
| # Resize | |
| if self.resize_to_hw is not None: | |
| resize_transform = transforms.Compose([ | |
| Resize(size=max(self.resize_to_hw), interpolation=InterpolationMode.NEAREST_EXACT), | |
| CenterCrop(size=self.resize_to_hw)]) | |
| rasters = {k: resize_transform(v) for k, v in rasters.items()} | |
| return rasters | |
| def _augment_data(self, rasters_dict): | |
| # lr flipping | |
| lr_flip_p = self.augm_args.lr_flip_p | |
| if random.random() < lr_flip_p: | |
| rasters_dict = {k: v.flip(-1) for k, v in rasters_dict.items()} | |
| return rasters_dict | |
| def __del__(self): | |
| if hasattr(self, "tar_obj") and self.tar_obj is not None: | |
| self.tar_obj.close() | |
| self.tar_obj = None | |
| def get_pred_name(rgb_basename, name_mode, suffix=".png"): | |
| if DepthFileNameMode.rgb_id == name_mode: | |
| pred_basename = "pred_" + rgb_basename.split("_")[1] | |
| elif DepthFileNameMode.i_d_rgb == name_mode: | |
| pred_basename = rgb_basename.replace("_rgb.", "_pred.") | |
| elif DepthFileNameMode.id == name_mode: | |
| pred_basename = "pred_" + rgb_basename | |
| elif DepthFileNameMode.rgb_i_d == name_mode: | |
| pred_basename = "pred_" + "_".join(rgb_basename.split("_")[1:]) | |
| else: | |
| raise NotImplementedError | |
| # change suffix | |
| pred_basename = os.path.splitext(pred_basename)[0] + suffix | |
| return pred_basename | |