Anonymous-123's picture
Add application file
ec0fdfd
import torch
import torch.nn.functional as F
import torchvision.transforms as transforms
import numpy as np
import cv2
from PIL import Image
import random
###################################################################
# random mask generation
###################################################################
def random_regular_mask(img):
"""Generate a random regular mask
:param img: original image size C*H*W
:return: mask
"""
mask = torch.ones_like(img)[0:1, :, :]
s = img.size()
N_mask = random.randint(1, 5)
lim_x = s[1] - s[1] / (N_mask + 1)
lim_y = s[2] - s[2] / (N_mask + 1)
for _ in range(N_mask):
x = random.randint(0, int(lim_x))
y = random.randint(0, int(lim_y))
range_x = x + random.randint(int(s[1] / (N_mask + 7)), min(int(s[1] - x), int(s[1] / 2)))
range_y = y + random.randint(int(s[2] / (N_mask + 7)), min(int(s[2] - y), int(s[2] / 2)))
mask[:, int(x) : int(range_x), int(y) : int(range_y)] = 0
return mask
def center_mask(img):
"""Generate a center hole with 1/4*W and 1/4*H
:param img: original image size C*H*W
:return: mask
"""
mask = torch.ones_like(img)[0:1, :, :]
s = img.size()
mask[:, int(s[1]/4):int(s[1]*3/4), int(s[2]/4):int(s[2]*3/4)] = 0
return mask
def random_irregular_mask(img):
"""Generate a random irregular mask with lines, circles and ellipses
:param img: original image size C*H*W
:return: mask
"""
transform = transforms.Compose([transforms.ToTensor()])
mask = torch.ones_like(img)[0:1, :, :]
s = mask.size()
img = np.zeros((s[1], s[2], 1), np.uint8)
max_width = int(min(s[1]/10, s[2]/10))
N_mask = random.randint(16, 64)
for _ in range(N_mask):
model = random.random()
if model < 0.2: # Draw random lines
x1, x2 = random.randint(1, s[1]), random.randint(1, s[1])
y1, y2 = random.randint(1, s[2]), random.randint(1, s[2])
thickness = random.randint(2, max_width)
cv2.line(img, (x1, y1), (x2, y2), (1, 1, 1), thickness)
elif (model > 0.2 and model < 0.5): # Draw random circles
x1, y1 = random.randint(1, s[1]), random.randint(1, s[2])
radius = random.randint(2, max_width)
cv2.circle(img, (x1, y1), radius, (1, 1, 1), -1)
else: # draw random ellipses
x1, y1 = random.randint(1, s[1]), random.randint(1, s[2])
s1, s2 = random.randint(1, s[1]), random.randint(1, s[2])
a1, a2, a3 = random.randint(3, 180), random.randint(3, 180), random.randint(3, 180)
thickness = random.randint(2, max_width)
cv2.ellipse(img, (x1, y1), (s1, s2), a1, a2, a3, (1, 1, 1), thickness)
img = img.reshape(s[2], s[1])
img = Image.fromarray(img*255)
img_mask = transform(img)
for j in range(s[0]):
mask[j, :, :] = img_mask
return mask
def scale_img(img, size):
h_ratio = img.size(-1) // size[-1]
w_ratio = img.size(-2) // size[-2]
scaled_img = F.avg_pool2d(img, kernel_size=(w_ratio, h_ratio), stride=(w_ratio, h_ratio))
return scaled_img
def scale_pyramid(img, num_scales):
scaled_imgs = [img]
for i in range(1, num_scales):
ratio = 2**i
scaled_img = F.avg_pool2d(img, kernel_size=ratio, stride=ratio)
scaled_imgs.append(scaled_img)
scaled_imgs.reverse()
return scaled_imgs
def jacobian(y, x, point=None, create_graph=True):
"""Calculate the jacobian matrix for given point"""
jac = []
flat_y = y.reshape(-1)
b, c, h, w = y.size()
if point is not None:
i = point[0] * h + point[1]
input_y = flat_y[i]
grad_x = torch.autograd.grad(input_y, x, retain_graph=True, grad_outputs=torch.ones(input_y.size()).to(x.device),
create_graph=create_graph, only_inputs=True)[0]
jac.append(grad_x.reshape(x.shape))
return jac
else:
for i in range(len(flat_y)):
input_y = flat_y[i]
grad_x = torch.autograd.grad(input_y, x, retain_graph=True, grad_outputs=torch.ones(input_y.size()).to(x.device),
create_graph=create_graph, only_inputs=True)[0]
jac.append(grad_x.reshape(x.shape))
return torch.stack(jac).reshape(y.shape + x.shape)