-
Notifications
You must be signed in to change notification settings - Fork 72
/
mask.py
87 lines (62 loc) · 2.59 KB
/
mask.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import numpy as np
import torch
class Masker():
"""Object for masking and demasking"""
def __init__(self, width=3, mode='zero', infer_single_pass=False, include_mask_as_input=False):
self.grid_size = width
self.n_masks = width ** 2
self.mode = mode
self.infer_single_pass = infer_single_pass
self.include_mask_as_input = include_mask_as_input
def mask(self, X, i):
phasex = i % self.grid_size
phasey = (i // self.grid_size) % self.grid_size
mask = pixel_grid_mask(X[0, 0].shape, self.grid_size, phasex, phasey)
mask = mask.to(X.device)
mask_inv = torch.ones(mask.shape).to(X.device) - mask
if self.mode == 'interpolate':
masked = interpolate_mask(X, mask, mask_inv)
elif self.mode == 'zero':
masked = X * mask_inv
else:
raise NotImplementedError
if self.include_mask_as_input:
net_input = torch.cat((masked, mask.repeat(X.shape[0], 1, 1, 1)), dim=1)
else:
net_input = masked
return net_input, mask
def __len__(self):
return self.n_masks
def infer_full_image(self, X, model):
if self.infer_single_pass:
if self.include_mask_as_input:
net_input = torch.cat((X, torch.zeros(X[:, 0:1].shape).to(X.device)), dim=1)
else:
net_input = X
net_output = model(net_input)
return net_output
else:
net_input, mask = self.mask(X, 0)
net_output = model(net_input)
acc_tensor = torch.zeros(net_output.shape).cpu()
for i in range(self.n_masks):
net_input, mask = self.mask(X, i)
net_output = model(net_input)
acc_tensor = acc_tensor + (net_output * mask).cpu()
return acc_tensor
def pixel_grid_mask(shape, patch_size, phase_x, phase_y):
A = torch.zeros(shape[-2:])
for i in range(shape[-2]):
for j in range(shape[-1]):
if (i % patch_size == phase_x and j % patch_size == phase_y):
A[i, j] = 1
return torch.Tensor(A)
def interpolate_mask(tensor, mask, mask_inv):
device = tensor.device
mask = mask.to(device)
kernel = np.array([[0.5, 1.0, 0.5], [1.0, 0.0, 1.0], (0.5, 1.0, 0.5)])
kernel = kernel[np.newaxis, np.newaxis, :, :]
kernel = torch.Tensor(kernel).to(device)
kernel = kernel / kernel.sum()
filtered_tensor = torch.nn.functional.conv2d(tensor, kernel, stride=1, padding=1)
return filtered_tensor * mask + tensor * mask_inv