ECON / lib /dataset /NormalDataset.py
Yuliang's picture
Support TEXTure
487ee6d
raw
history blame
5.43 kB
# -*- coding: utf-8 -*-
# Max-Planck-Gesellschaft zur Förderung der Wissenschaften e.V. (MPG) is
# holder of all proprietary rights on this computer program.
# You can only use this computer program if you have closed
# a license agreement with MPG or you get the right to use the computer
# program from someone who is authorized to grant you that right.
# Any use of the computer program without a valid license is prohibited and
# liable to prosecution.
#
# Copyright©2019 Max-Planck-Gesellschaft zur Förderung
# der Wissenschaften e.V. (MPG). acting on behalf of its Max Planck Institute
# for Intelligent Systems. All rights reserved.
#
# Contact: ps-license@tuebingen.mpg.de
import os.path as osp
import kornia
import numpy as np
import torchvision.transforms as transforms
from PIL import Image
from termcolor import colored
class NormalDataset:
def __init__(self, cfg, split="train"):
self.split = split
self.root = cfg.root
self.bsize = cfg.batch_size
self.opt = cfg.dataset
self.datasets = self.opt.types
self.input_size = self.opt.input_size
self.scales = self.opt.scales
# input data types and dimensions
self.in_nml = [item[0] for item in cfg.net.in_nml]
self.in_nml_dim = [item[1] for item in cfg.net.in_nml]
self.in_total = self.in_nml + ["normal_F", "normal_B"]
self.in_total_dim = self.in_nml_dim + [3, 3]
if self.split != "train":
self.rotations = range(0, 360, 120)
else:
self.rotations = np.arange(0, 360, 360 // self.opt.rotation_num).astype(np.int)
self.datasets_dict = {}
for dataset_id, dataset in enumerate(self.datasets):
dataset_dir = osp.join(self.root, dataset)
self.datasets_dict[dataset] = {
"subjects": np.loadtxt(osp.join(dataset_dir, "all.txt"), dtype=str),
"scale": self.scales[dataset_id],
}
self.subject_list = self.get_subject_list(split)
# PIL to tensor
self.image_to_tensor = transforms.Compose([
transforms.Resize(self.input_size),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
])
# PIL to tensor
self.mask_to_tensor = transforms.Compose([
transforms.Resize(self.input_size),
transforms.ToTensor(),
transforms.Normalize((0.0, ), (1.0, )),
])
def get_subject_list(self, split):
subject_list = []
for dataset in self.datasets:
split_txt = osp.join(self.root, dataset, f"{split}.txt")
if osp.exists(split_txt) and osp.getsize(split_txt) > 0:
print(f"load from {split_txt}")
subject_list += np.loadtxt(split_txt, dtype=str).tolist()
if self.split != "test":
subject_list += subject_list[:self.bsize - len(subject_list) % self.bsize]
print(colored(f"total: {len(subject_list)}", "yellow"))
bug_list = sorted(np.loadtxt(osp.join(self.root, 'bug.txt'), dtype=str).tolist())
subject_list = [subject for subject in subject_list if (subject not in bug_list)]
# subject_list = ["thuman2/0008"]
return subject_list
def __len__(self):
return len(self.subject_list) * len(self.rotations)
def __getitem__(self, index):
rid = index % len(self.rotations)
mid = index // len(self.rotations)
rotation = self.rotations[rid]
subject = self.subject_list[mid].split("/")[1]
dataset = self.subject_list[mid].split("/")[0]
render_folder = "/".join([dataset + f"_{self.opt.rotation_num}views", subject])
if not osp.exists(osp.join(self.root, render_folder)):
render_folder = "/".join([dataset + f"_36views", subject])
# setup paths
data_dict = {
"dataset": dataset,
"subject": subject,
"rotation": rotation,
"scale": self.datasets_dict[dataset]["scale"],
"image_path": osp.join(self.root, render_folder, "render", f"{rotation:03d}.png"),
}
# image/normal/depth loader
for name, channel in zip(self.in_total, self.in_total_dim):
if f"{name}_path" not in data_dict.keys():
data_dict.update({
f"{name}_path":
osp.join(self.root, render_folder, name, f"{rotation:03d}.png")
})
data_dict.update({
name:
self.imagepath2tensor(data_dict[f"{name}_path"], channel, inv=False, erasing=False)
})
path_keys = [key for key in data_dict.keys() if "_path" in key or "_dir" in key]
for key in path_keys:
del data_dict[key]
return data_dict
def imagepath2tensor(self, path, channel=3, inv=False, erasing=False):
rgba = Image.open(path).convert("RGBA")
mask = rgba.split()[-1]
image = rgba.convert("RGB")
image = self.image_to_tensor(image)
mask = self.mask_to_tensor(mask)
# simulate occlusion
if erasing:
mask = kornia.augmentation.RandomErasing(
p=0.2, scale=(0.01, 0.2), ratio=(0.3, 3.3), keepdim=True
)(mask)
image = (image * mask)[:channel]
return (image * (0.5 - inv) * 2.0).float()