|
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, |
|
} |
|
|
|
|
|
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 |
|
|