import torch import cv2 import numpy as np from torchvision import transforms from torch.utils.data import Dataset from pathlib import Path class PatchesDataset(Dataset): """ HPatches dataset class. # Note: output_shape = (output_width, output_height) # Note: this returns Pytorch tensors, resized to output_shape (if specified) # Note: the homography will be adjusted according to output_shape. Parameters ---------- root_dir : str Path to the dataset use_color : bool Return color images or convert to grayscale. data_transform : Function Transformations applied to the sample output_shape: tuple If specified, the images and homographies will be resized to the desired shape. type: str Dataset subset to return from ['i', 'v', 'all']: i - illumination sequences v - viewpoint sequences all - all sequences """ def __init__( self, root_dir, use_color=True, data_transform=None, output_shape=None, type="all", ): super().__init__() self.type = type self.root_dir = root_dir self.data_transform = data_transform self.output_shape = output_shape self.use_color = use_color base_path = Path(root_dir) folder_paths = [x for x in base_path.iterdir() if x.is_dir()] image_paths = [] warped_image_paths = [] homographies = [] for path in folder_paths: if self.type == "i" and path.stem[0] != "i": continue if self.type == "v" and path.stem[0] != "v": continue num_images = 5 file_ext = ".ppm" for i in range(2, 2 + num_images): image_paths.append(str(Path(path, "1" + file_ext))) warped_image_paths.append(str(Path(path, str(i) + file_ext))) homographies.append(np.loadtxt(str(Path(path, "H_1_" + str(i))))) self.files = { "image_paths": image_paths, "warped_image_paths": warped_image_paths, "homography": homographies, } def scale_homography(self, homography, original_scale, new_scale, pre): scales = np.divide(new_scale, original_scale) if pre: s = np.diag(np.append(scales, 1.0)) homography = np.matmul(s, homography) else: sinv = np.diag(np.append(1.0 / scales, 1.0)) homography = np.matmul(homography, sinv) return homography def __len__(self): return len(self.files["image_paths"]) def __getitem__(self, idx): def _read_image(path): img = cv2.imread(path, cv2.IMREAD_COLOR) if self.use_color: return img gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) return gray image = _read_image(self.files["image_paths"][idx]) warped_image = _read_image(self.files["warped_image_paths"][idx]) homography = np.array(self.files["homography"][idx]) sample = { "image": image, "warped_image": warped_image, "homography": homography, "index": idx, } # Apply transformations if self.output_shape is not None: sample["homography"] = self.scale_homography( sample["homography"], sample["image"].shape[:2][::-1], self.output_shape, pre=False, ) sample["homography"] = self.scale_homography( sample["homography"], sample["warped_image"].shape[:2][::-1], self.output_shape, pre=True, ) for key in ["image", "warped_image"]: sample[key] = cv2.resize(sample[key], self.output_shape) if self.use_color is False: sample[key] = np.expand_dims(sample[key], axis=2) transform = transforms.ToTensor() for key in ["image", "warped_image"]: sample[key] = transform(sample[key]).type("torch.FloatTensor") return sample