整合去雾网页工具
This commit is contained in:
93
RefineDNet/data/__init__.py
Normal file
93
RefineDNet/data/__init__.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""This package includes all the modules related to data loading and preprocessing
|
||||
|
||||
To add a custom dataset class called 'dummy', you need to add a file called 'dummy_dataset.py' and define a subclass 'DummyDataset' inherited from BaseDataset.
|
||||
You need to implement four functions:
|
||||
-- <__init__>: initialize the class, first call BaseDataset.__init__(self, opt).
|
||||
-- <__len__>: return the size of dataset.
|
||||
-- <__getitem__>: get a data point from data loader.
|
||||
-- <modify_commandline_options>: (optionally) add dataset-specific options and set default options.
|
||||
|
||||
Now you can use the dataset class by specifying flag '--dataset_mode dummy'.
|
||||
See our template dataset class 'template_dataset.py' for more details.
|
||||
"""
|
||||
import importlib
|
||||
import torch.utils.data
|
||||
from data.base_dataset import BaseDataset
|
||||
|
||||
|
||||
def find_dataset_using_name(dataset_name):
|
||||
"""Import the module "data/[dataset_name]_dataset.py".
|
||||
|
||||
In the file, the class called DatasetNameDataset() will
|
||||
be instantiated. It has to be a subclass of BaseDataset,
|
||||
and it is case-insensitive.
|
||||
"""
|
||||
dataset_filename = "data." + dataset_name + "_dataset"
|
||||
datasetlib = importlib.import_module(dataset_filename)
|
||||
|
||||
dataset = None
|
||||
target_dataset_name = dataset_name.replace('_', '') + 'dataset'
|
||||
for name, cls in datasetlib.__dict__.items():
|
||||
if name.lower() == target_dataset_name.lower() \
|
||||
and issubclass(cls, BaseDataset):
|
||||
dataset = cls
|
||||
|
||||
if dataset is None:
|
||||
raise NotImplementedError("In %s.py, there should be a subclass of BaseDataset with class name that matches %s in lowercase." % (dataset_filename, target_dataset_name))
|
||||
|
||||
return dataset
|
||||
|
||||
|
||||
def get_option_setter(dataset_name):
|
||||
"""Return the static method <modify_commandline_options> of the dataset class."""
|
||||
dataset_class = find_dataset_using_name(dataset_name)
|
||||
return dataset_class.modify_commandline_options
|
||||
|
||||
|
||||
def create_dataset(opt):
|
||||
"""Create a dataset given the option.
|
||||
|
||||
This function wraps the class CustomDatasetDataLoader.
|
||||
This is the main interface between this package and 'train.py'/'test.py'
|
||||
|
||||
Example:
|
||||
>>> from data import create_dataset
|
||||
>>> dataset = create_dataset(opt)
|
||||
"""
|
||||
data_loader = CustomDatasetDataLoader(opt)
|
||||
dataset = data_loader.load_data()
|
||||
return dataset
|
||||
|
||||
|
||||
class CustomDatasetDataLoader():
|
||||
"""Wrapper class of Dataset class that performs multi-threaded data loading"""
|
||||
|
||||
def __init__(self, opt):
|
||||
"""Initialize this class
|
||||
|
||||
Step 1: create a dataset instance given the name [dataset_mode]
|
||||
Step 2: create a multi-threaded data loader.
|
||||
"""
|
||||
self.opt = opt
|
||||
dataset_class = find_dataset_using_name(opt.dataset_mode)
|
||||
self.dataset = dataset_class(opt)
|
||||
print("dataset [%s] was created" % type(self.dataset).__name__)
|
||||
self.dataloader = torch.utils.data.DataLoader(
|
||||
self.dataset,
|
||||
batch_size=opt.batch_size,
|
||||
shuffle=not opt.serial_batches,
|
||||
num_workers=int(opt.num_threads))
|
||||
|
||||
def load_data(self):
|
||||
return self
|
||||
|
||||
def __len__(self):
|
||||
"""Return the number of data in the dataset"""
|
||||
return min(len(self.dataset), self.opt.max_dataset_size)
|
||||
|
||||
def __iter__(self):
|
||||
"""Return a batch of data"""
|
||||
for i, data in enumerate(self.dataloader):
|
||||
if i * self.opt.batch_size >= self.opt.max_dataset_size:
|
||||
break
|
||||
yield data
|
||||
60
RefineDNet/data/aligned_dataset.py
Normal file
60
RefineDNet/data/aligned_dataset.py
Normal file
@@ -0,0 +1,60 @@
|
||||
import os.path
|
||||
from data.base_dataset import BaseDataset, get_params, get_transform
|
||||
from data.image_folder import make_dataset
|
||||
from PIL import Image
|
||||
|
||||
|
||||
class AlignedDataset(BaseDataset):
|
||||
"""A dataset class for paired image dataset.
|
||||
|
||||
It assumes that the directory '/path/to/data/train' contains image pairs in the form of {A,B}.
|
||||
During test time, you need to prepare a directory '/path/to/data/test'.
|
||||
"""
|
||||
|
||||
def __init__(self, opt):
|
||||
"""Initialize this dataset class.
|
||||
|
||||
Parameters:
|
||||
opt (Option class) -- stores all the experiment flags; needs to be a subclass of BaseOptions
|
||||
"""
|
||||
BaseDataset.__init__(self, opt)
|
||||
self.dir_AB = os.path.join(opt.dataroot, opt.phase) # get the image directory
|
||||
self.AB_paths = sorted(make_dataset(self.dir_AB, opt.max_dataset_size)) # get image paths
|
||||
assert(self.opt.load_size >= self.opt.crop_size) # crop_size should be smaller than the size of loaded image
|
||||
self.input_nc = self.opt.output_nc if self.opt.direction == 'BtoA' else self.opt.input_nc
|
||||
self.output_nc = self.opt.input_nc if self.opt.direction == 'BtoA' else self.opt.output_nc
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Return a data point and its metadata information.
|
||||
|
||||
Parameters:
|
||||
index - - a random integer for data indexing
|
||||
|
||||
Returns a dictionary that contains A, B, A_paths and B_paths
|
||||
A (tensor) - - an image in the input domain
|
||||
B (tensor) - - its corresponding image in the target domain
|
||||
A_paths (str) - - image paths
|
||||
B_paths (str) - - image paths (same as A_paths)
|
||||
"""
|
||||
# read a image given a random integer index
|
||||
AB_path = self.AB_paths[index]
|
||||
AB = Image.open(AB_path).convert('RGB')
|
||||
# split AB image into A and B
|
||||
w, h = AB.size
|
||||
w2 = int(w / 2)
|
||||
A = AB.crop((0, 0, w2, h))
|
||||
B = AB.crop((w2, 0, w, h))
|
||||
|
||||
# apply the same transform to both A and B
|
||||
transform_params = get_params(self.opt, A.size)
|
||||
A_transform = get_transform(self.opt, transform_params, grayscale=(self.input_nc == 1))
|
||||
B_transform = get_transform(self.opt, transform_params, grayscale=(self.output_nc == 1))
|
||||
|
||||
A = A_transform(A)
|
||||
B = B_transform(B)
|
||||
|
||||
return {'A': A, 'B': B, 'A_paths': AB_path, 'B_paths': AB_path}
|
||||
|
||||
def __len__(self):
|
||||
"""Return the total number of images in the dataset."""
|
||||
return len(self.AB_paths)
|
||||
177
RefineDNet/data/base_dataset.py
Normal file
177
RefineDNet/data/base_dataset.py
Normal file
@@ -0,0 +1,177 @@
|
||||
"""This module implements an abstract base class (ABC) 'BaseDataset' for datasets.
|
||||
|
||||
It also includes common transformation functions (e.g., get_transform, __scale_width), which can be later used in subclasses.
|
||||
"""
|
||||
import random
|
||||
import numpy as np
|
||||
import torch.utils.data as data
|
||||
from PIL import Image
|
||||
import torchvision.transforms as transforms
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class BaseDataset(data.Dataset, ABC):
|
||||
"""This class is an abstract base class (ABC) for datasets.
|
||||
|
||||
To create a subclass, you need to implement the following four functions:
|
||||
-- <__init__>: initialize the class, first call BaseDataset.__init__(self, opt).
|
||||
-- <__len__>: return the size of dataset.
|
||||
-- <__getitem__>: get a data point.
|
||||
-- <modify_commandline_options>: (optionally) add dataset-specific options and set default options.
|
||||
"""
|
||||
|
||||
def __init__(self, opt):
|
||||
"""Initialize the class; save the options in the class
|
||||
|
||||
Parameters:
|
||||
opt (Option class)-- stores all the experiment flags; needs to be a subclass of BaseOptions
|
||||
"""
|
||||
self.opt = opt
|
||||
self.root = opt.dataroot
|
||||
|
||||
@staticmethod
|
||||
def modify_commandline_options(parser, is_train):
|
||||
"""Add new dataset-specific options, and rewrite default values for existing options.
|
||||
|
||||
Parameters:
|
||||
parser -- original option parser
|
||||
is_train (bool) -- whether training phase or test phase. You can use this flag to add training-specific or test-specific options.
|
||||
|
||||
Returns:
|
||||
the modified parser.
|
||||
"""
|
||||
return parser
|
||||
|
||||
@abstractmethod
|
||||
def __len__(self):
|
||||
"""Return the total number of images in the dataset."""
|
||||
return 0
|
||||
|
||||
@abstractmethod
|
||||
def __getitem__(self, index):
|
||||
"""Return a data point and its metadata information.
|
||||
|
||||
Parameters:
|
||||
index - - a random integer for data indexing
|
||||
|
||||
Returns:
|
||||
a dictionary of data with their names. It ususally contains the data itself and its metadata information.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def get_params(opt, size):
|
||||
w, h = size
|
||||
new_h = h
|
||||
new_w = w
|
||||
if opt.preprocess == 'resize_and_crop':
|
||||
new_h = new_w = opt.load_size
|
||||
elif opt.preprocess == 'scale_width_and_crop':
|
||||
new_w = opt.load_size
|
||||
new_h = opt.load_size * h // w
|
||||
elif opt.preprocess == 'scale_min_and_crop':
|
||||
if w <= h:
|
||||
new_w = opt.load_size
|
||||
new_h = opt.load_size * h // w
|
||||
else:
|
||||
new_w = opt.load_size * w // h
|
||||
new_h = opt.load_size
|
||||
|
||||
x = random.randint(0, np.maximum(0, new_w - opt.crop_size))
|
||||
y = random.randint(0, np.maximum(0, new_h - opt.crop_size))
|
||||
|
||||
flip = random.random() > 0.5
|
||||
|
||||
return {'crop_pos': (x, y), 'flip': flip}
|
||||
|
||||
|
||||
def get_transform(opt, params=None, grayscale=False, method=Image.BICUBIC, convert=True):
|
||||
transform_list = []
|
||||
if grayscale:
|
||||
transform_list.append(transforms.Grayscale(1))
|
||||
if 'resize' in opt.preprocess:
|
||||
osize = [opt.load_size, opt.load_size]
|
||||
transform_list.append(transforms.Resize(osize, method))
|
||||
elif 'scale_width' in opt.preprocess:
|
||||
transform_list.append(transforms.Lambda(lambda img: __scale_width(img, opt.load_size, method)))
|
||||
elif 'scale_min' in opt.preprocess:
|
||||
transform_list.append(transforms.Lambda(lambda img: __scale_min(img, opt.load_size, method)))
|
||||
|
||||
if 'crop' in opt.preprocess:
|
||||
if params is None:
|
||||
transform_list.append(transforms.RandomCrop(opt.crop_size))
|
||||
else:
|
||||
transform_list.append(transforms.Lambda(lambda img: __crop(img, params['crop_pos'], opt.crop_size)))
|
||||
|
||||
if opt.preprocess == 'none':
|
||||
transform_list.append(transforms.Lambda(lambda img: __make_power_2(img, base=4, method=method)))
|
||||
|
||||
if not opt.no_flip:
|
||||
if params is None:
|
||||
transform_list.append(transforms.RandomHorizontalFlip())
|
||||
elif params['flip']:
|
||||
transform_list.append(transforms.Lambda(lambda img: __flip(img, params['flip'])))
|
||||
|
||||
if convert:
|
||||
transform_list += [transforms.ToTensor()]
|
||||
if grayscale:
|
||||
transform_list += [transforms.Normalize((0.5,), (0.5,))]
|
||||
else:
|
||||
transform_list += [transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]
|
||||
return transforms.Compose(transform_list)
|
||||
|
||||
|
||||
def __make_power_2(img, base, method=Image.BICUBIC):
|
||||
ow, oh = img.size
|
||||
h = int(round(oh / base) * base)
|
||||
w = int(round(ow / base) * base)
|
||||
if (h == oh) and (w == ow):
|
||||
return img
|
||||
|
||||
__print_size_warning(ow, oh, w, h)
|
||||
return img.resize((w, h), method)
|
||||
|
||||
|
||||
def __scale_width(img, target_width, method=Image.BICUBIC):
|
||||
ow, oh = img.size
|
||||
if (ow == target_width):
|
||||
return img
|
||||
w = target_width
|
||||
h = int(target_width * oh / ow)
|
||||
return img.resize((w, h), method)
|
||||
|
||||
def __scale_min(img, target_min, method=Image.BICUBIC):
|
||||
ow, oh = img.size
|
||||
if ow <= oh:
|
||||
return __scale_width(img, target_min, method)
|
||||
else:
|
||||
if (oh == target_min):
|
||||
return img
|
||||
w = int(target_min * ow/oh)
|
||||
h = target_min
|
||||
return img.resize((w, h), method)
|
||||
|
||||
|
||||
def __crop(img, pos, size):
|
||||
ow, oh = img.size
|
||||
x1, y1 = pos
|
||||
tw = th = size
|
||||
if (ow > tw or oh > th):
|
||||
return img.crop((x1, y1, x1 + tw, y1 + th))
|
||||
return img
|
||||
|
||||
|
||||
def __flip(img, flip):
|
||||
if flip:
|
||||
return img.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
return img
|
||||
|
||||
|
||||
def __print_size_warning(ow, oh, w, h):
|
||||
"""Print warning information about image size(only print once)"""
|
||||
if not hasattr(__print_size_warning, 'has_printed'):
|
||||
print("The image size needs to be a multiple of 4. "
|
||||
"The loaded image size was (%d, %d), so it was adjusted to "
|
||||
"(%d, %d). This adjustment will be done to all images "
|
||||
"whose sizes are not multiples of 4" % (ow, oh, w, h))
|
||||
__print_size_warning.has_printed = True
|
||||
68
RefineDNet/data/colorization_dataset.py
Normal file
68
RefineDNet/data/colorization_dataset.py
Normal file
@@ -0,0 +1,68 @@
|
||||
import os.path
|
||||
from data.base_dataset import BaseDataset, get_transform
|
||||
from data.image_folder import make_dataset
|
||||
from skimage import color # require skimage
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
import torchvision.transforms as transforms
|
||||
|
||||
|
||||
class ColorizationDataset(BaseDataset):
|
||||
"""This dataset class can load a set of natural images in RGB, and convert RGB format into (L, ab) pairs in Lab color space.
|
||||
|
||||
This dataset is required by pix2pix-based colorization model ('--model colorization')
|
||||
"""
|
||||
@staticmethod
|
||||
def modify_commandline_options(parser, is_train):
|
||||
"""Add new dataset-specific options, and rewrite default values for existing options.
|
||||
|
||||
Parameters:
|
||||
parser -- original option parser
|
||||
is_train (bool) -- whether training phase or test phase. You can use this flag to add training-specific or test-specific options.
|
||||
|
||||
Returns:
|
||||
the modified parser.
|
||||
|
||||
By default, the number of channels for input image is 1 (L) and
|
||||
the nubmer of channels for output image is 2 (ab). The direction is from A to B
|
||||
"""
|
||||
parser.set_defaults(input_nc=1, output_nc=2, direction='AtoB')
|
||||
return parser
|
||||
|
||||
def __init__(self, opt):
|
||||
"""Initialize this dataset class.
|
||||
|
||||
Parameters:
|
||||
opt (Option class) -- stores all the experiment flags; needs to be a subclass of BaseOptions
|
||||
"""
|
||||
BaseDataset.__init__(self, opt)
|
||||
self.dir = os.path.join(opt.dataroot, opt.phase)
|
||||
self.AB_paths = sorted(make_dataset(self.dir, opt.max_dataset_size))
|
||||
assert(opt.input_nc == 1 and opt.output_nc == 2 and opt.direction == 'AtoB')
|
||||
self.transform = get_transform(self.opt, convert=False)
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Return a data point and its metadata information.
|
||||
|
||||
Parameters:
|
||||
index - - a random integer for data indexing
|
||||
|
||||
Returns a dictionary that contains A, B, A_paths and B_paths
|
||||
A (tensor) - - the L channel of an image
|
||||
B (tensor) - - the ab channels of the same image
|
||||
A_paths (str) - - image paths
|
||||
B_paths (str) - - image paths (same as A_paths)
|
||||
"""
|
||||
path = self.AB_paths[index]
|
||||
im = Image.open(path).convert('RGB')
|
||||
im = self.transform(im)
|
||||
im = np.array(im)
|
||||
lab = color.rgb2lab(im).astype(np.float32)
|
||||
lab_t = transforms.ToTensor()(lab)
|
||||
A = lab_t[[0], ...] / 50.0 - 1.0
|
||||
B = lab_t[[1, 2], ...] / 110.0
|
||||
return {'A': A, 'B': B, 'A_paths': path, 'B_paths': path}
|
||||
|
||||
def __len__(self):
|
||||
"""Return the total number of images in the dataset."""
|
||||
return len(self.AB_paths)
|
||||
66
RefineDNet/data/image_folder.py
Normal file
66
RefineDNet/data/image_folder.py
Normal file
@@ -0,0 +1,66 @@
|
||||
"""A modified image folder class
|
||||
|
||||
We modify the official PyTorch image folder (https://github.com/pytorch/vision/blob/master/torchvision/datasets/folder.py)
|
||||
so that this class can load images from both current directory and its subdirectories.
|
||||
"""
|
||||
|
||||
import torch.utils.data as data
|
||||
|
||||
from PIL import Image
|
||||
import os
|
||||
import os.path
|
||||
|
||||
IMG_EXTENSIONS = [
|
||||
'.jpg', '.JPG', '.jpeg', '.JPEG',
|
||||
'.png', '.PNG', '.ppm', '.PPM', '.bmp', '.BMP',
|
||||
]
|
||||
|
||||
|
||||
def is_image_file(filename):
|
||||
return any(filename.endswith(extension) for extension in IMG_EXTENSIONS)
|
||||
|
||||
|
||||
def make_dataset(dir, max_dataset_size=float("inf")):
|
||||
images = []
|
||||
assert os.path.isdir(dir), '%s is not a valid directory' % dir
|
||||
|
||||
for root, _, fnames in sorted(os.walk(dir)):
|
||||
for fname in fnames:
|
||||
if is_image_file(fname):
|
||||
path = os.path.join(root, fname)
|
||||
images.append(path)
|
||||
return images[:min(max_dataset_size, len(images))]
|
||||
|
||||
|
||||
def default_loader(path):
|
||||
return Image.open(path).convert('RGB')
|
||||
|
||||
|
||||
class ImageFolder(data.Dataset):
|
||||
|
||||
def __init__(self, root, transform=None, return_paths=False,
|
||||
loader=default_loader):
|
||||
imgs = make_dataset(root)
|
||||
if len(imgs) == 0:
|
||||
raise(RuntimeError("Found 0 images in: " + root + "\n"
|
||||
"Supported image extensions are: " +
|
||||
",".join(IMG_EXTENSIONS)))
|
||||
|
||||
self.root = root
|
||||
self.imgs = imgs
|
||||
self.transform = transform
|
||||
self.return_paths = return_paths
|
||||
self.loader = loader
|
||||
|
||||
def __getitem__(self, index):
|
||||
path = self.imgs[index]
|
||||
img = self.loader(path)
|
||||
if self.transform is not None:
|
||||
img = self.transform(img)
|
||||
if self.return_paths:
|
||||
return img, path
|
||||
else:
|
||||
return img
|
||||
|
||||
def __len__(self):
|
||||
return len(self.imgs)
|
||||
112
RefineDNet/data/paired_dataset.py
Normal file
112
RefineDNet/data/paired_dataset.py
Normal file
@@ -0,0 +1,112 @@
|
||||
import os
|
||||
import ntpath
|
||||
from data.base_dataset import BaseDataset, get_transform
|
||||
from data.image_folder import make_dataset
|
||||
from PIL import Image
|
||||
import random
|
||||
|
||||
import torch.nn.functional as F
|
||||
import torchvision.transforms as transforms
|
||||
import numpy as np
|
||||
|
||||
class PairedDataset(BaseDataset):
|
||||
"""
|
||||
This dataset class can load paired datasets.
|
||||
|
||||
It requires two directories to host training images from domain A '/path/to/data/trainA'
|
||||
and from domain B '/path/to/data/trainB' respectively.
|
||||
You can train the model with the dataset flag '--dataroot /path/to/data'.
|
||||
Similarly, you need to prepare two directories:
|
||||
'/path/to/data/testA' and '/path/to/data/testB' during test time.
|
||||
"""
|
||||
@staticmethod
|
||||
def modify_commandline_options(parser, is_train):
|
||||
"""Add new dataset-specific options, and rewrite default values for existing options.
|
||||
|
||||
Parameters:
|
||||
parser -- original option parser
|
||||
is_train (bool) -- whether training phase or test phase. You can use this flag to add training-specific or test-specific options.
|
||||
|
||||
Returns:
|
||||
the modified parser.
|
||||
"""
|
||||
parser.add_argument('--gt_prefix', type=str, default='', help='name of the used prior')
|
||||
return parser
|
||||
|
||||
def __init__(self, opt):
|
||||
"""Initialize this dataset class.
|
||||
|
||||
Parameters:
|
||||
opt (Option class) -- stores all the experiment flags; needs to be a subclass of BaseOptions
|
||||
"""
|
||||
BaseDataset.__init__(self, opt)
|
||||
self.dir_A = os.path.join(opt.dataroot, opt.phase + 'A') # create a path '/path/to/data/trainA'
|
||||
self.dir_B = os.path.join(opt.dataroot, opt.phase + 'B') # create a path '/path/to/data/trainB'
|
||||
|
||||
self.A_paths = sorted(make_dataset(self.dir_A, opt.max_dataset_size)) # load images from '/path/to/data/trainA'
|
||||
# self.B_paths = sorted(make_dataset(self.dir_B, opt.max_dataset_size)) # load images from '/path/to/data/trainB'
|
||||
self.A_size = len(self.A_paths) # get the size of dataset A
|
||||
# self.B_size = len(self.B_paths) # get the size of dataset B
|
||||
|
||||
# btoA = self.opt.direction == 'BtoA'
|
||||
# input_nc = self.opt.output_nc if btoA else self.opt.input_nc # get the number of channels of input image
|
||||
# output_nc = self.opt.input_nc if btoA else self.opt.output_nc # get the number of channels of output image
|
||||
self.transform = get_transform(self.opt, grayscale=(self.opt.input_nc == 1))
|
||||
self.toTensor = transforms.ToTensor()
|
||||
# self.transform_B = get_transform(self.opt, grayscale=(output_nc == 1))
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Return a data point and its metadata information.
|
||||
|
||||
Parameters:
|
||||
index (int) -- a random integer for data indexing
|
||||
|
||||
Returns a dictionary that contains A, B, A_paths and B_paths
|
||||
A (tensor) -- an image in the input domain
|
||||
B (tensor) -- its corresponding image in the target domain
|
||||
A_paths (str) -- image paths
|
||||
B_paths (str) -- image paths
|
||||
"""
|
||||
A_path = self.A_paths[index] # make sure index is within then range
|
||||
|
||||
A_name = os.path.splitext(ntpath.basename(A_path))[0]
|
||||
B_shortPath = '%s%s.png'%('_'.join(A_name.split('_')[:-1]), self.opt.gt_prefix) # '%s.png'%A_name.split('_')[0]
|
||||
B_path = os.path.join(self.dir_B, B_shortPath)
|
||||
|
||||
A_img = Image.open(A_path).convert('RGB')
|
||||
|
||||
if os.path.exists(B_path):
|
||||
B_img = Image.open(B_path).convert('RGB')
|
||||
else:
|
||||
print('file [%s] not exist!'%B_path)
|
||||
B_img = A_img
|
||||
|
||||
if A_img.size != B_img.size:
|
||||
B_img = self.cropImage(B_img, A_img.size)
|
||||
|
||||
# apply image transformation
|
||||
A = self.transform(A_img)
|
||||
# B = self.toTensor(B_img)
|
||||
B = self.transform(B_img)
|
||||
|
||||
# return {'A': A, 'B': B, 'A_paths': A_path, 'B_paths': B_path}
|
||||
return {'A': A, 'B': B, 'A_paths': A_path, 'B_paths': B_path,
|
||||
'clear': B, 'paths': A_path}
|
||||
|
||||
def __len__(self):
|
||||
"""Return the total number of images in the dataset.
|
||||
|
||||
As we have two datasets with potentially different number of images,
|
||||
we take a maximum of
|
||||
"""
|
||||
return self.A_size
|
||||
|
||||
def cropImage(self, img, target_size):
|
||||
ow, oh = img.size
|
||||
tw, th = target_size
|
||||
|
||||
if (ow > tw or oh > th):
|
||||
x1 = np.floor((ow - tw)/2)
|
||||
y1 = np.floor((oh - th)/2)
|
||||
return img.crop((x1, y1, x1 + tw, y1 + th))
|
||||
return img
|
||||
73
RefineDNet/data/simple_bedde_dataset.py
Normal file
73
RefineDNet/data/simple_bedde_dataset.py
Normal file
@@ -0,0 +1,73 @@
|
||||
### Copyright (C) 2017 NVIDIA Corporation. All rights reserved.
|
||||
### Licensed under the CC BY-NC-SA 4.0 license (https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
|
||||
import os, ntpath
|
||||
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
import scipy.io as sio
|
||||
import torchvision.transforms as transforms
|
||||
|
||||
from data.base_dataset import BaseDataset, get_params, get_transform
|
||||
# from data.image_folder import make_dataset,
|
||||
|
||||
class SimpleBeDDEDataset(BaseDataset):
|
||||
|
||||
@staticmethod
|
||||
def modify_commandline_options(parser, is_train):
|
||||
"""Add new dataset-specific options, and rewrite default values for existing options.
|
||||
|
||||
Parameters:
|
||||
parser -- original option parser
|
||||
is_train (bool) -- whether training phase or test phase. You can use this flag to add training-specific or test-specific options.
|
||||
|
||||
Returns:
|
||||
the modified parser.
|
||||
"""
|
||||
parser.add_argument('--bedde_list', required=True, type=str, help='image list of BeDDE')
|
||||
return parser
|
||||
|
||||
def __init__(self, opt):
|
||||
BaseDataset.__init__(self, opt)
|
||||
self.data_list_file = opt.bedde_list
|
||||
|
||||
listFile = open(self.data_list_file, 'r')
|
||||
self.imagePaths = listFile.read().split()
|
||||
listFile.close()
|
||||
|
||||
self.I_size = len(self.imagePaths)
|
||||
|
||||
self.transform = get_transform(self.opt, grayscale=(self.opt.input_nc == 1))
|
||||
self.toTensor = transforms.ToTensor()
|
||||
|
||||
def __getitem__(self, index):
|
||||
### input A (label maps)
|
||||
# print('bedde id %d'%index)
|
||||
I_path = self.imagePaths[index]
|
||||
I_img = Image.open(I_path).convert('RGB')
|
||||
params = get_params(self.opt, I_img.size)
|
||||
|
||||
I_name = os.path.splitext(ntpath.basename(I_path))[0]
|
||||
cityName = I_name.split('_')[0]
|
||||
|
||||
I_dir = ntpath.dirname(I_path)
|
||||
base_dir = ntpath.dirname(I_dir)
|
||||
|
||||
J_path = os.path.join(base_dir, 'gt', '%s_clear.png'%cityName)
|
||||
J_img = Image.open(J_path).convert('RGB')
|
||||
|
||||
base_dir = ntpath.dirname(I_dir)
|
||||
mask_path = os.path.join(base_dir, 'mask', '%s_mask.mat'%I_name)
|
||||
mask_info = sio.loadmat(mask_path)
|
||||
|
||||
J_root = ntpath.dirname(ntpath.dirname(I_path))
|
||||
|
||||
# apply image transformation
|
||||
real_I = self.transform(I_img)
|
||||
real_J = (self.toTensor(J_img) - 0.5) / 0.5
|
||||
|
||||
return {'haze': real_I, 'clear': real_J, 'mask': mask_info['mask'],
|
||||
'city': cityName, 'paths': I_path}
|
||||
# return {'haze': real_I , 'city': cityName, 'paths': curPath}
|
||||
|
||||
def __len__(self):
|
||||
return self.I_size
|
||||
110
RefineDNet/data/simple_paired_dataset.py
Normal file
110
RefineDNet/data/simple_paired_dataset.py
Normal file
@@ -0,0 +1,110 @@
|
||||
import os
|
||||
import ntpath
|
||||
from data.base_dataset import BaseDataset, get_transform
|
||||
from data.image_folder import make_dataset
|
||||
from PIL import Image
|
||||
import random
|
||||
|
||||
import torch.nn.functional as F
|
||||
import torchvision.transforms as transforms
|
||||
import numpy as np
|
||||
|
||||
class SimplePairedDataset(BaseDataset):
|
||||
"""
|
||||
This dataset class can load paired datasets.
|
||||
|
||||
It requires two directories to host training images from domain A '/path/to/data/trainA'
|
||||
and from domain B '/path/to/data/trainB' respectively.
|
||||
You can train the model with the dataset flag '--dataroot /path/to/data'.
|
||||
Similarly, you need to prepare two directories:
|
||||
'/path/to/data/testA' and '/path/to/data/testB' during test time.
|
||||
"""
|
||||
@staticmethod
|
||||
def modify_commandline_options(parser, is_train):
|
||||
"""Add new dataset-specific options, and rewrite default values for existing options.
|
||||
|
||||
Parameters:
|
||||
parser -- original option parser
|
||||
is_train (bool) -- whether training phase or test phase. You can use this flag to add training-specific or test-specific options.
|
||||
|
||||
Returns:
|
||||
the modified parser.
|
||||
"""
|
||||
parser.add_argument('--gt_prefix', type=str, default='', help='name of the used prior')
|
||||
return parser
|
||||
|
||||
def __init__(self, opt):
|
||||
"""Initialize this dataset class.
|
||||
|
||||
Parameters:
|
||||
opt (Option class) -- stores all the experiment flags; needs to be a subclass of BaseOptions
|
||||
"""
|
||||
BaseDataset.__init__(self, opt)
|
||||
self.dir_A = os.path.join(opt.dataroot, opt.phase + 'A') # create a path '/path/to/data/trainA'
|
||||
self.dir_B = os.path.join(opt.dataroot, opt.phase + 'B') # create a path '/path/to/data/trainB'
|
||||
|
||||
self.A_paths = sorted(make_dataset(self.dir_A, opt.max_dataset_size)) # load images from '/path/to/data/trainA'
|
||||
# self.B_paths = sorted(make_dataset(self.dir_B, opt.max_dataset_size)) # load images from '/path/to/data/trainB'
|
||||
self.A_size = len(self.A_paths) # get the size of dataset A
|
||||
# self.B_size = len(self.B_paths) # get the size of dataset B
|
||||
|
||||
# btoA = self.opt.direction == 'BtoA'
|
||||
# input_nc = self.opt.output_nc if btoA else self.opt.input_nc # get the number of channels of input image
|
||||
# output_nc = self.opt.input_nc if btoA else self.opt.output_nc # get the number of channels of output image
|
||||
self.transform = get_transform(self.opt, grayscale=(self.opt.input_nc == 1))
|
||||
self.toTensor = transforms.ToTensor()
|
||||
# self.transform_B = get_transform(self.opt, grayscale=(output_nc == 1))
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Return a data point and its metadata information.
|
||||
|
||||
Parameters:
|
||||
index (int) -- a random integer for data indexing
|
||||
|
||||
Returns a dictionary that contains A, B, A_paths and B_paths
|
||||
A (tensor) -- an image in the input domain
|
||||
B (tensor) -- its corresponding image in the target domain
|
||||
A_paths (str) -- image paths
|
||||
B_paths (str) -- image paths
|
||||
"""
|
||||
A_path = self.A_paths[index] # make sure index is within then range
|
||||
|
||||
A_name = os.path.splitext(ntpath.basename(A_path))[0]
|
||||
B_shortPath = '%s%s.png'%('_'.join(A_name.split('_')[:-1]), self.opt.gt_prefix) # '%s.png'%A_name.split('_')[0]
|
||||
B_path = os.path.join(self.dir_B, B_shortPath)
|
||||
|
||||
A_img = Image.open(A_path).convert('RGB')
|
||||
|
||||
if os.path.exists(B_path):
|
||||
B_img = Image.open(B_path).convert('RGB')
|
||||
else:
|
||||
print('file [%s] not exist!'%B_path)
|
||||
B_img = A_img
|
||||
|
||||
if A_img.size != B_img.size:
|
||||
B_img = self.cropImage(B_img, A_img.size)
|
||||
|
||||
# apply image transformation
|
||||
A = self.transform(A_img)
|
||||
B = (self.toTensor(B_img) - 0.5) / 0.5
|
||||
# B = self.transform(B_img)
|
||||
|
||||
return {'haze': A, 'clear': B, 'paths': A_path, 'B_paths': B_path}
|
||||
|
||||
def __len__(self):
|
||||
"""Return the total number of images in the dataset.
|
||||
|
||||
As we have two datasets with potentially different number of images,
|
||||
we take a maximum of
|
||||
"""
|
||||
return self.A_size
|
||||
|
||||
def cropImage(self, img, target_size):
|
||||
ow, oh = img.size
|
||||
tw, th = target_size
|
||||
|
||||
if (ow > tw or oh > th):
|
||||
x1 = np.floor((ow - tw)/2)
|
||||
y1 = np.floor((oh - th)/2)
|
||||
return img.crop((x1, y1, x1 + tw, y1 + th))
|
||||
return img
|
||||
45
RefineDNet/data/single_dataset.py
Normal file
45
RefineDNet/data/single_dataset.py
Normal file
@@ -0,0 +1,45 @@
|
||||
import os
|
||||
|
||||
from data.base_dataset import BaseDataset, get_transform
|
||||
from data.image_folder import make_dataset
|
||||
from PIL import Image
|
||||
|
||||
|
||||
class SingleDataset(BaseDataset):
|
||||
"""This dataset class can load a set of images specified by the path --dataroot /path/to/data.
|
||||
|
||||
It can be used for generating CycleGAN results only for one side with the model option '-model test'.
|
||||
"""
|
||||
|
||||
def __init__(self, opt):
|
||||
"""Initialize this dataset class.
|
||||
|
||||
Parameters:
|
||||
opt (Option class) -- stores all the experiment flags; needs to be a subclass of BaseOptions
|
||||
"""
|
||||
BaseDataset.__init__(self, opt)
|
||||
self.dir_A = os.path.join(opt.dataroot, opt.phase) # create a path '/path/to/data/testA'
|
||||
|
||||
self.A_paths = sorted(make_dataset(self.dir_A, opt.max_dataset_size))
|
||||
input_nc = self.opt.output_nc if self.opt.direction == 'BtoA' else self.opt.input_nc
|
||||
self.transform = get_transform(opt, grayscale=(input_nc == 1))
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Return a data point and its metadata information.
|
||||
|
||||
Parameters:
|
||||
index - - a random integer for data indexing
|
||||
|
||||
Returns a dictionary that contains A and A_paths
|
||||
A(tensor) - - an image in one domain
|
||||
A_paths(str) - - the path of the image
|
||||
"""
|
||||
A_path = self.A_paths[index]
|
||||
A_img = Image.open(A_path).convert('RGB')
|
||||
A = self.transform(A_img)
|
||||
# return {'A': A, 'A_paths': A_path}
|
||||
return {'haze': A, 'paths': A_path}
|
||||
|
||||
def __len__(self):
|
||||
"""Return the total number of images in the dataset."""
|
||||
return len(self.A_paths)
|
||||
75
RefineDNet/data/template_dataset.py
Normal file
75
RefineDNet/data/template_dataset.py
Normal file
@@ -0,0 +1,75 @@
|
||||
"""Dataset class template
|
||||
|
||||
This module provides a template for users to implement custom datasets.
|
||||
You can specify '--dataset_mode template' to use this dataset.
|
||||
The class name should be consistent with both the filename and its dataset_mode option.
|
||||
The filename should be <dataset_mode>_dataset.py
|
||||
The class name should be <Dataset_mode>Dataset.py
|
||||
You need to implement the following functions:
|
||||
-- <modify_commandline_options>: Add dataset-specific options and rewrite default values for existing options.
|
||||
-- <__init__>: Initialize this dataset class.
|
||||
-- <__getitem__>: Return a data point and its metadata information.
|
||||
-- <__len__>: Return the number of images.
|
||||
"""
|
||||
from data.base_dataset import BaseDataset, get_transform
|
||||
# from data.image_folder import make_dataset
|
||||
# from PIL import Image
|
||||
|
||||
|
||||
class TemplateDataset(BaseDataset):
|
||||
"""A template dataset class for you to implement custom datasets."""
|
||||
@staticmethod
|
||||
def modify_commandline_options(parser, is_train):
|
||||
"""Add new dataset-specific options, and rewrite default values for existing options.
|
||||
|
||||
Parameters:
|
||||
parser -- original option parser
|
||||
is_train (bool) -- whether training phase or test phase. You can use this flag to add training-specific or test-specific options.
|
||||
|
||||
Returns:
|
||||
the modified parser.
|
||||
"""
|
||||
parser.add_argument('--new_dataset_option', type=float, default=1.0, help='new dataset option')
|
||||
parser.set_defaults(max_dataset_size=10, new_dataset_option=2.0) # specify dataset-specific default values
|
||||
return parser
|
||||
|
||||
def __init__(self, opt):
|
||||
"""Initialize this dataset class.
|
||||
|
||||
Parameters:
|
||||
opt (Option class) -- stores all the experiment flags; needs to be a subclass of BaseOptions
|
||||
|
||||
A few things can be done here.
|
||||
- save the options (have been done in BaseDataset)
|
||||
- get image paths and meta information of the dataset.
|
||||
- define the image transformation.
|
||||
"""
|
||||
# save the option and dataset root
|
||||
BaseDataset.__init__(self, opt)
|
||||
# get the image paths of your dataset;
|
||||
self.image_paths = [] # You can call sorted(make_dataset(self.root, opt.max_dataset_size)) to get all the image paths under the directory self.root
|
||||
# define the default transform function. You can use <base_dataset.get_transform>; You can also define your custom transform function
|
||||
self.transform = get_transform(opt)
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Return a data point and its metadata information.
|
||||
|
||||
Parameters:
|
||||
index -- a random integer for data indexing
|
||||
|
||||
Returns:
|
||||
a dictionary of data with their names. It usually contains the data itself and its metadata information.
|
||||
|
||||
Step 1: get a random image path: e.g., path = self.image_paths[index]
|
||||
Step 2: load your data from the disk: e.g., image = Image.open(path).convert('RGB').
|
||||
Step 3: convert your data to a PyTorch tensor. You can use helpder functions such as self.transform. e.g., data = self.transform(image)
|
||||
Step 4: return a data point as a dictionary.
|
||||
"""
|
||||
path = 'temp' # needs to be a string
|
||||
data_A = None # needs to be a tensor
|
||||
data_B = None # needs to be a tensor
|
||||
return {'data_A': data_A, 'data_B': data_B, 'path': path}
|
||||
|
||||
def __len__(self):
|
||||
"""Return the total number of images."""
|
||||
return len(self.image_paths)
|
||||
80
RefineDNet/data/unaligned_dataset.py
Normal file
80
RefineDNet/data/unaligned_dataset.py
Normal file
@@ -0,0 +1,80 @@
|
||||
import os.path
|
||||
from data.base_dataset import BaseDataset, get_transform, get_params
|
||||
from data.image_folder import make_dataset
|
||||
from PIL import Image
|
||||
import random
|
||||
|
||||
|
||||
class UnalignedDataset(BaseDataset):
|
||||
"""
|
||||
This dataset class can load unaligned/unpaired datasets.
|
||||
|
||||
It requires two directories to host training images from domain A '/path/to/data/trainA'
|
||||
and from domain B '/path/to/data/trainB' respectively.
|
||||
You can train the model with the dataset flag '--dataroot /path/to/data'.
|
||||
Similarly, you need to prepare two directories:
|
||||
'/path/to/data/testA' and '/path/to/data/testB' during test time.
|
||||
"""
|
||||
|
||||
def __init__(self, opt):
|
||||
"""Initialize this dataset class.
|
||||
|
||||
Parameters:
|
||||
opt (Option class) -- stores all the experiment flags; needs to be a subclass of BaseOptions
|
||||
"""
|
||||
BaseDataset.__init__(self, opt)
|
||||
self.dir_A = os.path.join(opt.dataroot, opt.phase + 'A') # create a path '/path/to/data/trainA'
|
||||
self.dir_B = os.path.join(opt.dataroot, opt.phase + 'B') # create a path '/path/to/data/trainB'
|
||||
|
||||
self.A_paths = sorted(make_dataset(self.dir_A, opt.max_dataset_size)) # load images from '/path/to/data/trainA'
|
||||
self.B_paths = sorted(make_dataset(self.dir_B, opt.max_dataset_size)) # load images from '/path/to/data/trainB'
|
||||
self.A_size = len(self.A_paths) # get the size of dataset A
|
||||
self.B_size = len(self.B_paths) # get the size of dataset B
|
||||
# btoA = self.opt.direction == 'BtoA'
|
||||
# input_nc = self.opt.output_nc if btoA else self.opt.input_nc # get the number of channels of input image
|
||||
# output_nc = self.opt.input_nc if btoA else self.opt.output_nc # get the number of channels of output image
|
||||
# self.transform_A = get_transform(self.opt, grayscale=(input_nc == 1))
|
||||
# self.transform_B = get_transform(self.opt, grayscale=(output_nc == 1))
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Return a data point and its metadata information.
|
||||
|
||||
Parameters:
|
||||
index (int) -- a random integer for data indexing
|
||||
|
||||
Returns a dictionary that contains A, B, A_paths and B_paths
|
||||
A (tensor) -- an image in the input domain
|
||||
B (tensor) -- its corresponding image in the target domain
|
||||
A_paths (str) -- image paths
|
||||
B_paths (str) -- image paths
|
||||
"""
|
||||
A_path = self.A_paths[index % self.A_size] # make sure index is within then range
|
||||
if self.opt.serial_batches: # make sure index is within then range
|
||||
index_B = index % self.B_size
|
||||
else: # randomize the index for domain B to avoid fixed pairs.
|
||||
index_B = random.randint(0, self.B_size - 1)
|
||||
B_path = self.B_paths[index_B]
|
||||
A_img = Image.open(A_path).convert('RGB')
|
||||
B_img = Image.open(B_path).convert('RGB')
|
||||
|
||||
params_A = get_params(self.opt, A_img.size)
|
||||
params_B = get_params(self.opt, B_img.size)
|
||||
|
||||
btoA = self.opt.direction == 'BtoA'
|
||||
input_nc = self.opt.output_nc if btoA else self.opt.input_nc # get the number of channels of input image
|
||||
output_nc = self.opt.input_nc if btoA else self.opt.output_nc # get the number of channels of output image
|
||||
transform_A = get_transform(self.opt, params=params_A, grayscale=(input_nc == 1))
|
||||
transform_B = get_transform(self.opt, params=params_B, grayscale=(output_nc == 1))
|
||||
# apply image transformation
|
||||
A = transform_A(A_img)
|
||||
B = transform_B(B_img)
|
||||
|
||||
return {'A': A, 'B': B, 'A_paths': A_path, 'B_paths': B_path}
|
||||
|
||||
def __len__(self):
|
||||
"""Return the total number of images in the dataset.
|
||||
|
||||
As we have two datasets with potentially different number of images,
|
||||
we take a maximum of
|
||||
"""
|
||||
return max(self.A_size, self.B_size)
|
||||
72
RefineDNet/data/unpaired_dataset.py
Normal file
72
RefineDNet/data/unpaired_dataset.py
Normal file
@@ -0,0 +1,72 @@
|
||||
import os.path
|
||||
from data.base_dataset import BaseDataset, get_transform, get_params
|
||||
from data.image_folder import make_dataset
|
||||
from PIL import Image
|
||||
import random
|
||||
|
||||
|
||||
class UnpairedDataset(BaseDataset):
|
||||
"""
|
||||
This dataset class can load unpaired datasets for dehazing.
|
||||
|
||||
It requires two directories to host training images from domain A '/path/to/data/trainA'
|
||||
and from domain B '/path/to/data/trainB' respectively.
|
||||
You can train the model with the dataset flag '--dataroot /path/to/data'.
|
||||
Similarly, you need to prepare two directories:
|
||||
'/path/to/data/testA' and '/path/to/data/testB' during test time.
|
||||
"""
|
||||
|
||||
def __init__(self, opt):
|
||||
"""Initialize this dataset class.
|
||||
|
||||
Parameters:
|
||||
opt (Option class) -- stores all the experiment flags; needs to be a subclass of BaseOptions
|
||||
"""
|
||||
BaseDataset.__init__(self, opt)
|
||||
self.dir_I = os.path.join(opt.dataroot, opt.phase + 'A') # create a path '/path/to/data/trainA'
|
||||
self.dir_J = os.path.join(opt.dataroot, opt.phase + 'B') # create a path '/path/to/data/trainB'
|
||||
|
||||
self.I_paths = sorted(make_dataset(self.dir_I, opt.max_dataset_size)) # load images from '/path/to/data/trainA'
|
||||
self.J_paths = sorted(make_dataset(self.dir_J, opt.max_dataset_size)) # load images from '/path/to/data/trainB'
|
||||
self.I_size = len(self.I_paths) # get the size of dataset A
|
||||
self.J_size = len(self.J_paths) # get the size of dataset B
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Return a data point and its metadata information.
|
||||
|
||||
Parameters:
|
||||
index (int) -- a random integer for data indexing
|
||||
|
||||
Returns a dictionary that contains haze, clear, paths and J_paths
|
||||
haze (tensor) -- hazy image
|
||||
clear (tensor) -- clear image
|
||||
paths (str) -- image paths
|
||||
J_paths (str) -- image paths
|
||||
"""
|
||||
I_path = self.I_paths[index % self.I_size] # make sure index is within then range
|
||||
if self.opt.serial_batches: # make sure index is within then range
|
||||
index_J = index % self.J_size
|
||||
else: # randomize the index for domain B to avoid fixed pairs.
|
||||
index_J = random.randint(0, self.J_size - 1)
|
||||
J_path = self.J_paths[index_J]
|
||||
I_img = Image.open(I_path).convert('RGB')
|
||||
J_img = Image.open(J_path).convert('RGB')
|
||||
|
||||
params_I = get_params(self.opt, I_img.size)
|
||||
params_J = get_params(self.opt, J_img.size)
|
||||
|
||||
transform_I = get_transform(self.opt, params=params_I, grayscale=(self.opt.input_nc == 1))
|
||||
transform_J = get_transform(self.opt, params=params_J, grayscale=(self.opt.output_nc == 1))
|
||||
# apply image transformation
|
||||
real_I = transform_I(I_img)
|
||||
real_J = transform_J(J_img)
|
||||
|
||||
return {'haze': real_I, 'clear': real_J, 'paths': I_path, 'J_paths': J_path}
|
||||
|
||||
def __len__(self):
|
||||
"""Return the total number of images in the dataset.
|
||||
|
||||
As we have two datasets with potentially different number of images,
|
||||
we take a maximum of
|
||||
"""
|
||||
return max(self.I_size, self.J_size)
|
||||
Reference in New Issue
Block a user