update training code

This commit is contained in:
zhangmozhe
2020-12-21 23:17:29 +08:00
parent a93d050dd1
commit 875e222242
56 changed files with 6891 additions and 215 deletions
+348
View File
@@ -0,0 +1,348 @@
from __future__ import division
import collections
import numbers
import random
import torch
from PIL import Image
from skimage import color
import lib.functional as F
__all__ = [
"Compose",
"Concatenate",
"ToTensor",
"Normalize",
"Resize",
"Scale",
"CenterCrop",
"Pad",
"RandomCrop",
"RandomHorizontalFlip",
"RandomVerticalFlip",
"RandomResizedCrop",
"RandomSizedCrop",
"FiveCrop",
"TenCrop",
"RGB2Lab",
]
def CustomFunc(inputs, func, *args, **kwargs):
im_l = func(inputs[0], *args, **kwargs)
im_ab = func(inputs[1], *args, **kwargs)
warp_ba = func(inputs[2], *args, **kwargs)
warp_aba = func(inputs[3], *args, **kwargs)
im_gbl_ab = func(inputs[4], *args, **kwargs)
bgr_mc_im = func(inputs[5], *args, **kwargs)
layer_data = [im_l, im_ab, warp_ba, warp_aba, im_gbl_ab, bgr_mc_im]
for l in range(5):
layer = inputs[6 + l]
err_ba = func(layer[0], *args, **kwargs)
err_ab = func(layer[1], *args, **kwargs)
layer_data.append([err_ba, err_ab])
return layer_data
class Compose(object):
"""Composes several transforms together.
Args:
transforms (list of ``Transform`` objects): list of transforms to compose.
Example:
>>> transforms.Compose([
>>> transforms.CenterCrop(10),
>>> transforms.ToTensor(),
>>> ])
"""
def __init__(self, transforms):
self.transforms = transforms
def __call__(self, inputs):
for t in self.transforms:
inputs = t(inputs)
return inputs
class Concatenate(object):
"""
Input: [im_l, im_ab, inputs]
inputs = [warp_ba_l, warp_ba_ab, warp_aba, err_pm, err_aba]
Output:[im_l, err_pm, warp_ba, warp_aba, im_ab, err_aba]
"""
def __call__(self, inputs):
im_l = inputs[0]
im_ab = inputs[1]
warp_ba = inputs[2]
warp_aba = inputs[3]
im_glb_ab = inputs[4]
bgr_mc_im = inputs[5]
bgr_mc_im = bgr_mc_im[[2, 1, 0], ...]
err_ba = []
err_ab = []
for l in range(5):
layer = inputs[6 + l]
err_ba.append(layer[0])
err_ab.append(layer[1])
cerr_ba = torch.cat(err_ba, 0)
cerr_ab = torch.cat(err_ab, 0)
return (im_l, cerr_ba, warp_ba, warp_aba, im_glb_ab, bgr_mc_im, im_ab, cerr_ab)
class ToTensor(object):
"""Convert a ``PIL Image`` or ``numpy.ndarray`` to tensor.
Converts a PIL Image or numpy.ndarray (H x W x C) in the range
[0, 255] to a torch.FloatTensor of shape (C x H x W) in the range [0.0, 1.0].
"""
def __call__(self, inputs):
"""
Args:
pic (PIL Image or numpy.ndarray): Image to be converted to tensor.
Returns:
Tensor: Converted image.
"""
return CustomFunc(inputs, F.to_mytensor)
class Normalize(object):
"""Normalize an tensor image with mean and standard deviation.
Given mean: ``(M1,...,Mn)`` and std: ``(S1,..,Sn)`` for ``n`` channels, this transform
will normalize each channel of the input ``torch.*Tensor`` i.e.
``input[channel] = (input[channel] - mean[channel]) / std[channel]``
Args:
mean (sequence): Sequence of means for each channel.
std (sequence): Sequence of standard deviations for each channel.
"""
def __call__(self, inputs):
"""
Args:
tensor (Tensor): Tensor image of size (C, H, W) to be normalized.
Returns:
Tensor: Normalized Tensor image.
"""
im_l = F.normalize(inputs[0], 50, 1) # [0, 100]
im_ab = F.normalize(inputs[1], (0, 0), (1, 1)) # [-100, 100]
inputs[2][0:1, :, :] = F.normalize(inputs[2][0:1, :, :], 50, 1)
inputs[2][1:3, :, :] = F.normalize(inputs[2][1:3, :, :], (0, 0), (1, 1))
warp_ba = inputs[2]
inputs[3][0:1, :, :] = F.normalize(inputs[3][0:1, :, :], 50, 1)
inputs[3][1:3, :, :] = F.normalize(inputs[3][1:3, :, :], (0, 0), (1, 1))
warp_aba = inputs[3]
im_gbl_ab = F.normalize(inputs[4], (0, 0), (1, 1)) # [-100, 100]
bgr_mc_im = F.normalize(inputs[5], (123.68, 116.78, 103.938), (1, 1, 1))
layer_data = [im_l, im_ab, warp_ba, warp_aba, im_gbl_ab, bgr_mc_im]
for l in range(5):
layer = inputs[6 + l]
err_ba = F.normalize(layer[0], 127, 2) # [0, 255]
err_ab = F.normalize(layer[1], 127, 2) # [0, 255]
layer_data.append([err_ba, err_ab])
return layer_data
class Resize(object):
"""Resize the input PIL Image to the given size.
Args:
size (sequence or int): Desired output size. If size is a sequence like
(h, w), output size will be matched to this. If size is an int,
smaller edge of the image will be matched to this number.
i.e, if height > width, then image will be rescaled to
(size * height / width, size)
interpolation (int, optional): Desired interpolation. Default is
``PIL.Image.BILINEAR``
"""
def __init__(self, size, interpolation=Image.BILINEAR):
assert isinstance(size, int) or (isinstance(size, collections.Iterable) and len(size) == 2)
self.size = size
self.interpolation = interpolation
def __call__(self, inputs):
"""
Args:
img (PIL Image): Image to be scaled.
Returns:
PIL Image: Rescaled image.
"""
return CustomFunc(inputs, F.resize, self.size, self.interpolation)
class RandomCrop(object):
"""Crop the given PIL Image at a random location.
Args:
size (sequence or int): Desired output size of the crop. If size is an
int instead of sequence like (h, w), a square crop (size, size) is
made.
padding (int or sequence, optional): Optional padding on each border
of the image. Default is 0, i.e no padding. If a sequence of length
4 is provided, it is used to pad left, top, right, bottom borders
respectively.
"""
def __init__(self, size, padding=0):
if isinstance(size, numbers.Number):
self.size = (int(size), int(size))
else:
self.size = size
self.padding = padding
@staticmethod
def get_params(img, output_size):
"""Get parameters for ``crop`` for a random crop.
Args:
img (PIL Image): Image to be cropped.
output_size (tuple): Expected output size of the crop.
Returns:
tuple: params (i, j, h, w) to be passed to ``crop`` for random crop.
"""
w, h = img.size
th, tw = output_size
if w == tw and h == th:
return 0, 0, h, w
i = random.randint(0, h - th)
j = random.randint(0, w - tw)
return i, j, th, tw
def __call__(self, inputs):
"""
Args:
img (PIL Image): Image to be cropped.
Returns:
PIL Image: Cropped image.
"""
if self.padding > 0:
inputs = CustomFunc(inputs, F.pad, self.padding)
i, j, h, w = self.get_params(inputs[0], self.size)
return CustomFunc(inputs, F.crop, i, j, h, w)
class CenterCrop(object):
"""Crop the given PIL Image at a random location.
Args:
size (sequence or int): Desired output size of the crop. If size is an
int instead of sequence like (h, w), a square crop (size, size) is
made.
padding (int or sequence, optional): Optional padding on each border
of the image. Default is 0, i.e no padding. If a sequence of length
4 is provided, it is used to pad left, top, right, bottom borders
respectively.
"""
def __init__(self, size, padding=0):
if isinstance(size, numbers.Number):
self.size = (int(size), int(size))
else:
self.size = size
self.padding = padding
@staticmethod
def get_params(img, output_size):
"""Get parameters for ``crop`` for a random crop.
Args:
img (PIL Image): Image to be cropped.
output_size (tuple): Expected output size of the crop.
Returns:
tuple: params (i, j, h, w) to be passed to ``crop`` for random crop.
"""
w, h = img.size
th, tw = output_size
if w == tw and h == th:
return 0, 0, h, w
i = (h - th) // 2
j = (w - tw) // 2
return i, j, th, tw
def __call__(self, inputs):
"""
Args:
img (PIL Image): Image to be cropped.
Returns:
PIL Image: Cropped image.
"""
if self.padding > 0:
inputs = CustomFunc(inputs, F.pad, self.padding)
i, j, h, w = self.get_params(inputs[0], self.size)
return CustomFunc(inputs, F.crop, i, j, h, w)
class RandomHorizontalFlip(object):
"""Horizontally flip the given PIL Image randomly with a probability of 0.5."""
def __call__(self, inputs):
"""
Args:
img (PIL Image): Image to be flipped.
Returns:
PIL Image: Randomly flipped image.
"""
if random.random() < 0.5:
return CustomFunc(inputs, F.hflip)
return inputs
class RGB2Lab(object):
def __call__(self, inputs):
"""
Args:
img (PIL Image): Image to be flipped.
Returns:
PIL Image: Randomly flipped image.
"""
def __call__(self, inputs):
image_lab = color.rgb2lab(inputs[0])
warp_ba_lab = color.rgb2lab(inputs[2])
warp_aba_lab = color.rgb2lab(inputs[3])
im_gbl_lab = color.rgb2lab(inputs[4])
inputs[0] = image_lab[:, :, :1] # l channel
inputs[1] = image_lab[:, :, 1:] # ab channel
inputs[2] = warp_ba_lab # lab channel
inputs[3] = warp_aba_lab # lab channel
inputs[4] = im_gbl_lab[:, :, 1:] # ab channel
return inputs
+301
View File
@@ -0,0 +1,301 @@
import sys
sys.path.insert(0, "..")
import os
import random
import cv2
import numpy as np
import torch
import torchvision.utils as vutils
from PIL import Image
from skimage import color
from torch.autograd import Variable
from utils.flowlib import read_flow
from utils.util_distortion import CenterPad
import lib.functional as F
cv2.setNumThreads(0)
class RGB2Lab(object):
def __init__(self):
pass
def __call__(self, inputs):
return color.rgb2lab(inputs)
class Normalize(object):
def __init__(self):
pass
def __call__(self, inputs):
inputs[0:1, :, :] = F.normalize(inputs[0:1, :, :], 50, 1)
inputs[1:3, :, :] = F.normalize(inputs[1:3, :, :], (0, 0), (1, 1))
return inputs
class ToTensor(object):
def __init__(self):
pass
def __call__(self, inputs):
outputs = F.to_mytensor(inputs) # permute channel and transform to tensor
return outputs
class RandomErasing(object):
def __init__(self, probability=0.6, sl=0.05, sh=0.6):
self.probability = probability
self.sl = sl
self.sh = sh
def __call__(self, img):
img = np.array(img)
if random.uniform(0, 1) > self.probability:
return Image.fromarray(img)
area = img.shape[0] * img.shape[1]
h0 = img.shape[0]
w0 = img.shape[1]
channel = img.shape[2]
h = int(round(random.uniform(self.sl, self.sh) * h0))
w = int(round(random.uniform(self.sl, self.sh) * w0))
if w < img.shape[1] and h < img.shape[0]:
x1 = random.randint(0, img.shape[0] - h)
y1 = random.randint(0, img.shape[1] - w)
img[x1 : x1 + h, y1 : y1 + w, :] = np.random.rand(h, w, channel) * 255
return Image.fromarray(img)
return Image.fromarray(img)
class CenterCrop(object):
"""
center crop the numpy array
"""
def __init__(self, image_size):
self.h0, self.w0 = image_size
def __call__(self, input_numpy):
if input_numpy.ndim == 3:
h, w, channel = input_numpy.shape
output_numpy = np.zeros((self.h0, self.w0, channel))
output_numpy = input_numpy[
(h - self.h0) // 2 : (h - self.h0) // 2 + self.h0, (w - self.w0) // 2 : (w - self.w0) // 2 + self.w0, :
]
else:
h, w = input_numpy.shape
output_numpy = np.zeros((self.h0, self.w0))
output_numpy = input_numpy[
(h - self.h0) // 2 : (h - self.h0) // 2 + self.h0, (w - self.w0) // 2 : (w - self.w0) // 2 + self.w0
]
return output_numpy
def parse_images(data_root):
image_pairs = []
subdirs = sorted(os.listdir(data_root))
for subdir in subdirs:
path = os.path.join(data_root, subdir)
if not os.path.isdir(path):
continue
parse_file = os.path.join(path, "pairs_output_new.txt")
if os.path.exists(parse_file):
with open(parse_file, "r") as f:
lines = f.readlines()
for line in lines:
line = line.replace("\n", "")
(
image1_name,
image2_name,
reference_video_name,
reference_video_name1,
reference_name1,
reference_name2,
reference_name3,
reference_name4,
reference_name5,
reference_gt1,
reference_gt2,
reference_gt3,
) = line.split()
image1_name = image1_name.split(".")[0]
image2_name = image2_name.split(".")[0]
reference_video_name = reference_video_name.split(".")[0]
reference_video_name1 = reference_video_name1.split(".")[0]
reference_name1 = reference_name1.split(".")[0]
reference_name2 = reference_name2.split(".")[0]
reference_name3 = reference_name3.split(".")[0]
reference_name4 = reference_name4.split(".")[0]
reference_name5 = reference_name5.split(".")[0]
reference_gt1 = reference_gt1.split(".")[0]
reference_gt2 = reference_gt2.split(".")[0]
reference_gt3 = reference_gt3.split(".")[0]
flow_forward_name = image1_name + "_forward"
flow_backward_name = image1_name + "_backward"
mask_name = image1_name + "_mask"
item = (
image1_name + ".jpg",
image2_name + ".jpg",
reference_video_name + ".jpg",
reference_name1 + ".JPEG",
reference_name2 + ".JPEG",
reference_name3 + ".JPEG",
reference_name4 + ".JPEG",
reference_name5 + ".JPEG",
flow_forward_name + ".flo",
flow_backward_name + ".flo",
mask_name + ".pgm",
reference_gt1 + ".jpg",
reference_gt2 + ".jpg",
reference_gt3 + ".jpg",
path,
)
image_pairs.append(item)
else:
raise (RuntimeError("Error when parsing pair_output_count.txt in subfolders of: " + path + "\n"))
return image_pairs
class VideosDataset(torch.utils.data.Dataset):
def __init__(
self,
data_root,
epoch,
image_size,
image_transform=None,
use_google_reference=False,
real_reference_probability=1,
nonzero_placeholder_probability=0.5,
):
self.data_root = data_root
self.image_transform = image_transform
self.CenterPad = CenterPad(image_size)
self.ToTensor = ToTensor()
self.CenterCrop = CenterCrop(image_size)
assert len(self.data_root) > 0, "find no dataroot"
self.epoch = epoch
self.image_pairs = parse_images(self.data_root)
self.real_len = len(self.image_pairs)
print("##### parsing image pairs in %s: %d pairs #####" % (data_root, self.real_len))
self.image_pairs *= epoch
self.use_google_reference = use_google_reference
self.real_reference_probability = real_reference_probability
self.nonzero_placeholder_probability = nonzero_placeholder_probability
def __getitem__(self, index):
(
image1_name,
image2_name,
reference_video_name,
reference_name1,
reference_name2,
reference_name3,
reference_name4,
reference_name5,
flow_forward_name,
flow_backward_name,
mask_name,
reference_gt1,
reference_gt2,
reference_gt3,
path,
) = self.image_pairs[index]
try:
I1 = Image.open(os.path.join(path, "input_pad", image1_name))
I2 = Image.open(os.path.join(path, "input_pad", image2_name))
I_reference_video = Image.open(
os.path.join(path, "reference_gt", random.choice([reference_gt1, reference_gt2, reference_gt3]))
)
I_reference_video_real = Image.open(
os.path.join(
path,
"reference",
random.choice(
[reference_name1, reference_name2, reference_name3, reference_name4, reference_name5]
),
)
)
flow_forward = read_flow(os.path.join(path, "flow", flow_forward_name)) # numpy
flow_backward = read_flow(os.path.join(path, "flow", flow_backward_name)) # numpy
mask = Image.open(os.path.join(path, "mask", mask_name))
# binary mask
mask = np.array(mask)
mask[mask < 240] = 0
mask[mask >= 240] = 1
# transform
I1 = self.image_transform(I1)
I2 = self.image_transform(I2)
I_reference_video = self.image_transform(self.CenterPad(I_reference_video))
I_reference_video_real = self.image_transform(self.CenterPad(I_reference_video_real))
flow_forward = self.ToTensor(self.CenterCrop(flow_forward))
flow_backward = self.ToTensor(self.CenterCrop(flow_backward))
mask = self.ToTensor(self.CenterCrop(mask))
if np.random.random() < self.real_reference_probability:
I_reference_output = I_reference_video_real
placeholder = torch.zeros_like(I1)
self_ref_flag = torch.zeros_like(I1)
else:
I_reference_output = I_reference_video
placeholder = I2 if np.random.random() < self.nonzero_placeholder_probability else torch.zeros_like(I1)
self_ref_flag = torch.ones_like(I1)
outputs = [
I1,
I2,
I_reference_output,
flow_forward,
flow_backward,
mask,
placeholder,
self_ref_flag,
]
except Exception as e:
print("problem in, ", path)
print(e)
return self.__getitem__(np.random.randint(0, len(self.image_pairs)))
return outputs
def __len__(self):
return len(self.image_pairs)
def batch_lab2rgb_transpose_mc(img_l_mc, img_ab_mc, nrow=8):
if isinstance(img_l_mc, Variable):
img_l_mc = img_l_mc.data.cpu()
if isinstance(img_ab_mc, Variable):
img_ab_mc = img_ab_mc.data.cpu()
if img_l_mc.is_cuda:
img_l_mc = img_l_mc.cpu()
if img_ab_mc.is_cuda:
img_ab_mc = img_ab_mc.cpu()
assert img_l_mc.dim() == 4 and img_ab_mc.dim() == 4, "only for batch input"
l_norm, ab_norm = 1.0, 1.0
l_mean, ab_mean = 50.0, 0
img_l = img_l_mc * l_norm + l_mean
img_ab = img_ab_mc * ab_norm + ab_mean
pred_lab = torch.cat((img_l, img_ab), dim=1)
grid_lab = vutils.make_grid(pred_lab, nrow=nrow).numpy().astype("float64")
return (np.clip(color.lab2rgb(grid_lab.transpose((1, 2, 0))), 0, 1) * 255).astype("uint8")
+290
View File
@@ -0,0 +1,290 @@
import os
import os.path as osp
import struct
import cv2
import numpy as np
import torch
import torch.utils.data as data
import torchvision.transforms as transforms
from PIL import Image
from scipy.ndimage import map_coordinates
from scipy.ndimage.filters import gaussian_filter
from utils.util_distortion import CenterPadCrop_numpy, Distortion_with_flow, Normalize, RGB2Lab, ToTensor
cv2.setNumThreads(0)
def parse_images(dir, with_bad, with_mid):
print("dir is: ", dir)
dir = osp.expanduser(dir)
image_pairs = []
no_mid_cnt, no_bad_cnt = 0, 0
for target in sorted(os.listdir(dir)):
d = osp.join(dir, target)
if not osp.isdir(d):
continue
pair_file = osp.join(d, "pairs.txt")
if osp.exists(pair_file):
with open(pair_file, "r") as f:
lines = f.readlines()
for line in lines:
pair = line.strip().split(" ")
name0, postfix = pair[0].split(".")
name1, postfix = pair[1].split(".")
if float(pair[2]) > 0:
item0 = (dir, target, name0, name1, 2)
item1 = (dir, target, name1, name0, 2)
image_pairs.append(item0)
image_pairs.append(item1)
else:
raise (RuntimeError("Found no pair.txt in subfolders of: " + d + "\n"))
if with_mid:
pair_file = osp.join(d, "pairs_mid.txt")
if osp.exists(pair_file):
with open(pair_file, "r") as f:
for line in f:
pair = line.strip().split(" ")
name0, postfix = pair[0].split(".")
name1, postfix = pair[1].split(".")
item0 = (dir, target, name0, name1, 0)
item1 = (dir, target, name1, name0, 0)
image_pairs.append(item0)
image_pairs.append(item1)
else:
no_mid_cnt += 1
if with_bad:
pair_file = osp.join(d, "pairs_bad.txt")
if osp.exists(pair_file):
with open(pair_file, "r") as f:
for line in f:
pair = line.strip().split(" ")
name0, postfix = pair[0].split(".")
name1, postfix = pair[1].split(".")
item0 = (dir, target, name0, name1, -1)
item1 = (dir, target, name1, name0, -1)
image_pairs.append(item0)
image_pairs.append(item1)
else:
no_bad_cnt += 1
if no_bad_cnt > 0:
print("find no pairs_bad.txt in %d folders for dir: %s" % (no_bad_cnt, dir))
if no_mid_cnt > 0:
print("find no pairs_mid.txt in %d folders for dir: %s" % (no_mid_cnt, dir))
return image_pairs
def pil_loader(path):
with open(path, "rb") as f:
with Image.open(f) as img:
return img.convert("RGB")
def image_loader(path):
return pil_loader(path)
def combo5_loader(path, real_w, real_h):
with open(path, "rb") as f:
d = f.read(4)
im_sz = struct.unpack("i", d)
h = im_sz[0]
d = f.read(4)
im_sz = struct.unpack("i", d)
w = im_sz[0]
d = f.read(4)
im_sz = struct.unpack("i", d)
d = f.read(im_sz[0])
file_bytes = np.asarray(bytearray(d), dtype=np.uint8)
img_data_ndarray = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR)
img_data_ndarray = cv2.cvtColor(img_data_ndarray, cv2.COLOR_BGR2RGB)
warp_ba = Image.fromarray(img_data_ndarray)
img_data_ndarray = img_data_ndarray * 0
warp_aba = Image.fromarray(img_data_ndarray)
errs = []
empty_array = np.zeros([np.array(warp_ba).shape[0], np.array(warp_ba).shape[1]])
for _ in range(5):
err_ba = Image.fromarray(empty_array)
err_ab = Image.fromarray(empty_array)
errs.append([err_ba, err_ab])
return errs, warp_ba, warp_aba
class VideosDataset_ImageNet(data.Dataset):
def __init__(
self,
data_root,
epoch,
image_size,
with_bad=False,
with_mid=False,
transforms_imagenet=None,
distortion_level=3,
brightnessjitter=0,
nonzero_placeholder_probability=0.5,
extra_reference_transform=None,
real_reference_probability=1,
):
image_pairs = []
curr_image_pairs = parse_images(data_root, with_bad, with_mid)
image_pairs += curr_image_pairs
print("##### parsing image_a pairs in %s: %d pairs #####" % (data_root, len(curr_image_pairs)))
if not image_pairs:
raise RuntimeError("Found 0 image_a pairs in all the data_roots")
self.image_pairs = image_pairs
self.transforms_imagenet_raw = transforms_imagenet
self.extra_reference_transform = transforms.Compose(extra_reference_transform)
self.real_reference_probability = real_reference_probability
self.transforms_imagenet = transforms.Compose(transforms_imagenet)
self.epoch = epoch
self.image_size = image_size
self.real_len = len(self.image_pairs)
self.image_pairs *= epoch
self.distortion_level = distortion_level
self.distortion_transform = Distortion_with_flow()
self.brightnessjitter = brightnessjitter
self.flow_transform = transforms.Compose([CenterPadCrop_numpy(self.image_size), ToTensor()])
self.nonzero_placeholder_probability = nonzero_placeholder_probability
self.ToTensor = ToTensor()
self.Normalize = Normalize()
def __getitem__(self, index):
try:
image_id = 0
pair_id = index
combo_path = None
image_a_path = None
image_b_path = None
image_names = ["", ""]
dir_root, cls_dir, image_names[0], image_names[1], is_good = self.image_pairs[pair_id]
sub_dir = osp.join(dir_root, cls_dir)
if is_good >= 1:
image_a_path = osp.join(sub_dir, "input", "%s.JPEG" % image_names[image_id])
image_b_path = osp.join(sub_dir, "input", "%s.JPEG" % image_names[1 - image_id])
elif is_good == 0:
image_a_path = osp.join(sub_dir, "input_mid", "%s.JPEG" % image_names[image_id])
image_b_path = osp.join(sub_dir, "input_mid", "%s.JPEG" % image_names[1 - image_id])
else:
image_a_path = osp.join(sub_dir, "input_bad", "%s.JPEG" % image_names[image_id])
image_b_path = osp.join(sub_dir, "input_bad", "%s.JPEG" % image_names[1 - image_id])
if np.random.random() > 0.5:
image_a_path, image_b_path = image_b_path, image_a_path
I1 = image_loader(image_a_path)
I2 = I1
I_reference_video = I1
I_reference_video_real = image_loader(image_b_path)
## generate the flow
height, width = np.array(I2).shape[0], np.array(I2).shape[1]
alpha = np.random.rand() * self.distortion_level
distortion_range = 50
random_state = np.random.RandomState(None)
shape = self.image_size[0], self.image_size[1]
# dx: flow on the vertical direction; dy: flow on the horizontal direction
forward_dx = (
gaussian_filter((random_state.rand(*shape) * 2 - 1), distortion_range, mode="constant", cval=0)
* alpha
* 1000
)
forward_dy = (
gaussian_filter((random_state.rand(*shape) * 2 - 1), distortion_range, mode="constant", cval=0)
* alpha
* 1000
)
for transform in self.transforms_imagenet_raw:
if type(transform) is RGB2Lab:
I1_raw = I1
I1 = transform(I1)
for transform in self.transforms_imagenet_raw:
if type(transform) is RGB2Lab:
I2 = self.distortion_transform(I2, forward_dx, forward_dy)
I2_raw = I2
I2 = transform(I2)
I2[0:1, :, :] = I2[0:1, :, :] + torch.randn(1) * self.brightnessjitter
I_reference_video = self.extra_reference_transform(I_reference_video)
for transform in self.transforms_imagenet_raw:
I_reference_video = transform(I_reference_video)
I_reference_video_real = self.transforms_imagenet(I_reference_video_real)
flow_forward_raw = np.stack((forward_dy, forward_dx), axis=-1)
flow_backward_raw = np.zeros_like(flow_forward_raw)
flow_forward = self.flow_transform(flow_forward_raw)
flow_backward = self.flow_transform(flow_backward_raw)
# update the mask for the pixels on the border
grid_x, grid_y = np.meshgrid(np.arange(self.image_size[0]), np.arange(self.image_size[1]), indexing="ij")
grid = np.stack((grid_y, grid_x), axis=-1)
grid_warp = grid + flow_forward_raw
location_y = grid_warp[:, :, 0].flatten()
location_x = grid_warp[:, :, 1].flatten()
I2_raw = np.array(I2_raw).astype(float)
I21_r = map_coordinates(I2_raw[:, :, 0], np.stack((location_x, location_y)), cval=-1).reshape(
(self.image_size[0], self.image_size[1])
)
I21_g = map_coordinates(I2_raw[:, :, 1], np.stack((location_x, location_y)), cval=-1).reshape(
(self.image_size[0], self.image_size[1])
)
I21_b = map_coordinates(I2_raw[:, :, 2], np.stack((location_x, location_y)), cval=-1).reshape(
(self.image_size[0], self.image_size[1])
)
I21_raw = np.stack((I21_r, I21_g, I21_b), axis=2)
mask = np.ones((self.image_size[0], self.image_size[1]))
mask[(I21_raw[:, :, 0] == -1) & (I21_raw[:, :, 1] == -1) & (I21_raw[:, :, 2] == -1)] = 0
mask[abs(I21_raw - I1_raw).sum(axis=-1) > 50] = 0
mask = self.ToTensor(mask)
if np.random.random() < self.real_reference_probability:
I_reference_output = I_reference_video_real
placeholder = torch.zeros_like(I1)
self_ref_flag = torch.zeros_like(I1)
else:
I_reference_output = I_reference_video
placeholder = I2 if np.random.random() < self.nonzero_placeholder_probability else torch.zeros_like(I1)
self_ref_flag = torch.ones_like(I1)
outputs = [
I1,
I2,
I_reference_output,
flow_forward,
flow_backward,
mask,
placeholder,
self_ref_flag,
]
except Exception as e:
if combo_path is not None:
print("problem in ", combo_path)
print("problem in, ", image_a_path)
print(e)
return self.__getitem__(np.random.randint(0, len(self.image_pairs)))
return outputs
def __len__(self):
return len(self.image_pairs)