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.)) homography = np.matmul(s, homography) else: sinv = np.diag(np.append(1. / scales, 1.)) 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