ming0531 commited on
Commit
783e8d2
·
verified ·
1 Parent(s): 57cc3c9

Remove renderer/method/blocks.py (replaced by the flashrefocus package)

Browse files
Files changed (1) hide show
  1. renderer/method/blocks.py +0 -228
renderer/method/blocks.py DELETED
@@ -1,228 +0,0 @@
1
- """Building blocks of the Stage II renderer: NAF blocks with condition maps for the U-Net, and the defocus-bias
2
- attention of the transformer bottleneck (axial attention biased by defocus differences, scaled by the strength K)."""
3
- from math import floor
4
-
5
- import torch
6
- import torch.nn.functional as F
7
- from timm.layers import DropPath
8
- from torch import nn
9
- from torch.autograd import Function
10
-
11
-
12
- class LayerNormFunction(Function):
13
- """Channel LayerNorm of NCHW tensors with an explicit backward (as in NAFNet)."""
14
-
15
- @staticmethod
16
- def forward(ctx, x, weight, bias, eps):
17
- ctx.eps = eps
18
- _, C, _, _ = x.size()
19
- mu = x.mean(1, keepdim=True)
20
- var = (x - mu).pow(2).mean(1, keepdim=True)
21
- y = (x - mu) / (var + eps).sqrt()
22
- ctx.save_for_backward(y, var, weight)
23
- return weight.view(1, C, 1, 1) * y + bias.view(1, C, 1, 1)
24
-
25
- @staticmethod
26
- def backward(ctx, grad_output):
27
- eps = ctx.eps
28
- _, C, _, _ = grad_output.size()
29
- y, var, weight = ctx.saved_tensors
30
- g = grad_output * weight.view(1, C, 1, 1)
31
- mean_g = g.mean(dim=1, keepdim=True)
32
- mean_gy = (g * y).mean(dim=1, keepdim=True)
33
- gx = 1.0 / torch.sqrt(var + eps) * (g - y * mean_gy - mean_g)
34
- # reduce over W, H, then N, in this order (it fixes the floating-point summation order)
35
- return gx, (grad_output * y).sum(dim=3).sum(dim=2).sum(dim=0), grad_output.sum(dim=3).sum(dim=2).sum(dim=0), None
36
-
37
-
38
- class LayerNorm2d(nn.Module):
39
- def __init__(self, channels, eps=1e-6):
40
- super().__init__()
41
- self.weight = nn.Parameter(torch.ones(channels))
42
- self.bias = nn.Parameter(torch.zeros(channels))
43
- self.eps = eps
44
-
45
- def forward(self, x):
46
- return LayerNormFunction.apply(x, self.weight, self.bias, self.eps)
47
-
48
-
49
- class InvertedConvolution(nn.Module):
50
- """1x1 convolution followed by a depthwise k x k convolution."""
51
-
52
- def __init__(self, in_channels, out_channels, kernel_size):
53
- super().__init__()
54
- self.conv1 = nn.Conv2d(in_channels, out_channels, 1)
55
- self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size, padding="same", groups=out_channels)
56
-
57
- def forward(self, x):
58
- return self.conv2(self.conv1(x))
59
-
60
-
61
- class ChannelAttention(nn.Module):
62
- def __init__(self, channels):
63
- super().__init__()
64
- self.model = nn.Sequential(
65
- nn.AdaptiveAvgPool2d(1),
66
- nn.Conv2d(channels, channels // 2, 1),
67
- nn.ReLU(inplace=True),
68
- nn.Conv2d(channels // 2, channels, 1),
69
- nn.Sigmoid(),
70
- )
71
-
72
- def forward(self, x):
73
- return self.model(x)
74
-
75
-
76
- class NAFBlock(nn.Module):
77
- """NAFNet block whose first convolution also reads the condition maps M_C (resized to the block's resolution)."""
78
-
79
- def __init__(self, channels, cond_channels, ffn_expand=2.0, kernel_size=3):
80
- super().__init__()
81
- self.norm1 = LayerNorm2d(channels)
82
- self.conv1 = InvertedConvolution(channels + cond_channels, channels, kernel_size)
83
- self.activation = nn.GELU()
84
- self.attention = ChannelAttention(channels)
85
- self.conv2 = nn.Conv2d(channels, channels, 1)
86
- ffn_channels = floor(ffn_expand * channels)
87
- self.norm2 = LayerNorm2d(channels)
88
- self.conv3 = nn.Conv2d(channels, ffn_channels, 1)
89
- self.conv4 = nn.Conv2d(ffn_channels, channels, 1)
90
- self.beta = nn.Parameter(torch.zeros((1, channels, 1, 1)))
91
- self.gamma = nn.Parameter(torch.zeros((1, channels, 1, 1)))
92
-
93
- def forward(self, x, cond):
94
- y = self.activation(self.conv1(torch.cat((self.norm1(x), cond), dim=1)))
95
- y = x + self.conv2(y * self.attention(y)) * self.beta
96
- return y + self.conv4(self.activation(self.conv3(self.norm2(y)))) * self.gamma
97
-
98
-
99
- class DWConv2d(nn.Module):
100
- """Depthwise convolution on channels-last (b, h, w, c) tensors."""
101
-
102
- def __init__(self, dim, kernel_size, padding):
103
- super().__init__()
104
- self.conv = nn.Conv2d(dim, dim, kernel_size, 1, padding, groups=dim)
105
-
106
- def forward(self, x):
107
- return self.conv(x.permute(0, 3, 1, 2)).permute(0, 2, 3, 1)
108
-
109
-
110
- class FeedForwardNetwork(nn.Module):
111
- def __init__(self, embed_dim, ffn_dim):
112
- super().__init__()
113
- self.fc1 = nn.Linear(embed_dim, ffn_dim)
114
- self.fc2 = nn.Linear(ffn_dim, embed_dim)
115
-
116
- def forward(self, x):
117
- return self.fc2(F.gelu(self.fc1(x)))
118
-
119
-
120
- class DefocusBiasAttention(nn.Module):
121
- """Defocus-bias attention (Sec. 3.2, Appendix C.1), axial: along each row, then along each column.
122
-
123
- A_ij = softmax_j(q_i^T k_j / sqrt(d) + gamma_b * alpha * B_ij), B_ij = -|T_D,i - T_D,j|, T_D = phi_D(M),
124
- where phi_D maps the defocus magnitude M to fixed log features at several scales and then, with a learned linear
125
- layer (defocus_head_proj), to one value per head; alpha (defocus_alpha) is learned per head and
126
- gamma_b = exp(clip(w_b K + c_b, -4, 4)) (aperture_scale_proj); gamma_K = gamma_b * alpha in the main paper.
127
- The output is W_o(sum_j A_ij v_j + LePE(V)_i), with LePE a depthwise 5x5 convolution of the values."""
128
-
129
- def __init__(self, embed_dim, num_heads):
130
- super().__init__()
131
- self.num_heads = num_heads
132
- self.key_dim = embed_dim // num_heads # d
133
- self.scaling = self.key_dim ** -0.5
134
- self.q_proj = nn.Linear(embed_dim, embed_dim) # W_q
135
- self.k_proj = nn.Linear(embed_dim, embed_dim) # W_k
136
- self.v_proj = nn.Linear(embed_dim, embed_dim) # W_v
137
- self.lepe = DWConv2d(embed_dim, 5, 2)
138
- self.out_proj = nn.Linear(embed_dim, embed_dim) # W_o
139
- self.num_log_features = max(embed_dim // 4, 1)
140
- self.defocus_head_proj = nn.Linear(self.num_log_features, num_heads) # linear layer of phi_D
141
- self.defocus_alpha = nn.Parameter(torch.ones(num_heads)) # alpha
142
- self.aperture_scale_proj = nn.Linear(1, num_heads) # w_b, c_b
143
-
144
- def _log_features(self, defocus):
145
- """M (b, 1, h, w) -> (b, h, w, n) features log(1 + M / s) / log(1 + 1 / s), scales s from 1/n to 1."""
146
- n = self.num_log_features
147
- min_scale = 1.0 / max(float(n), 16.0)
148
- scales = torch.logspace(torch.log10(defocus.new_tensor(min_scale)), torch.log10(defocus.new_tensor(1.0)),
149
- steps=n, dtype=defocus.dtype, device=defocus.device).view(1, n, 1, 1)
150
- features = torch.log1p(defocus.clamp(0.0, 1.0) / scales) / torch.log1p(1.0 / scales)
151
- return features.permute(0, 2, 3, 1).contiguous()
152
-
153
- def _defocus_bias(self, defocus):
154
- """B along rows (b, h, heads, w, w) and along columns (b, w, heads, h, h)."""
155
- t_d = self.defocus_head_proj(self._log_features(defocus)) # T_D = phi_D(M): b, h, w, heads
156
- t_rows = t_d.permute(0, 1, 3, 2).contiguous() # b, h, heads, w
157
- t_cols = t_d.permute(0, 2, 3, 1).contiguous() # b, w, heads, h
158
- return (-torch.abs(t_rows.unsqueeze(-1) - t_rows.unsqueeze(-2)),
159
- -torch.abs(t_cols.unsqueeze(-1) - t_cols.unsqueeze(-2)))
160
-
161
- def _gamma_b(self, x, strength):
162
- raw = self.aperture_scale_proj(strength.to(device=x.device, dtype=x.dtype))
163
- return torch.exp(torch.clamp(raw, min=-4.0, max=4.0)).view(x.size(0), 1, self.num_heads, 1, 1)
164
-
165
- def forward(self, x, defocus, strength):
166
- b, h, w, _ = x.size()
167
- q = self.q_proj(x)
168
- k = self.k_proj(x) * self.scaling
169
- v = self.v_proj(x)
170
- lepe = self.lepe(v)
171
- q = q.view(b, h, w, self.num_heads, self.key_dim).permute(0, 3, 1, 2, 4) # b, heads, h, w, d
172
- k = k.view(b, h, w, self.num_heads, self.key_dim).permute(0, 3, 1, 2, 4)
173
-
174
- bias_rows, bias_cols = self._defocus_bias(defocus)
175
- scale = self._gamma_b(x, strength) * self.defocus_alpha.view(1, 1, self.num_heads, 1, 1) # gamma_b * alpha
176
-
177
- v = v.reshape(b, h, w, self.num_heads, -1).permute(0, 1, 3, 2, 4) # b, h, heads, w, d
178
- attn = torch.softmax(q.transpose(1, 2) @ k.transpose(1, 2).transpose(-1, -2) + scale * bias_rows, dim=-1)
179
- v = (attn @ v).permute(0, 3, 2, 1, 4) # b, w, heads, h, d
180
- attn = torch.softmax(q.permute(0, 3, 1, 2, 4) @ k.permute(0, 3, 1, 2, 4).transpose(-1, -2)
181
- + scale * bias_cols, dim=-1)
182
- out = (attn @ v).permute(0, 3, 1, 2, 4).flatten(-2, -1) # b, h, w, c
183
- return self.out_proj(out + lepe)
184
-
185
-
186
- class DefocusAwareAttentionBlock(nn.Module):
187
- """Defocus-aware attention block (DAAB, Fig. 3C): depthwise positional convolution, defocus-bias attention, FFN."""
188
-
189
- def __init__(self, embed_dim, num_heads, ffn_dim, drop_path=0.0):
190
- super().__init__()
191
- self.pos = DWConv2d(embed_dim, 3, 1)
192
- self.attention_layer_norm = nn.LayerNorm(embed_dim, eps=1e-6)
193
- self.attention = DefocusBiasAttention(embed_dim, num_heads)
194
- self.final_layer_norm = nn.LayerNorm(embed_dim, eps=1e-6)
195
- self.ffn = FeedForwardNetwork(embed_dim, ffn_dim)
196
- self.drop_path = DropPath(drop_path)
197
-
198
- def forward(self, x, defocus, strength):
199
- x = x + self.pos(x)
200
- x = x + self.drop_path(self.attention(self.attention_layer_norm(x), defocus, strength))
201
- return x + self.drop_path(self.ffn(self.final_layer_norm(x)))
202
-
203
-
204
- class DAABStack(nn.Module):
205
- def __init__(self, embed_dim, depth, num_heads, ffn_dim, drop_path):
206
- super().__init__()
207
- self.blocks = nn.ModuleList(
208
- [DefocusAwareAttentionBlock(embed_dim, num_heads, ffn_dim, drop_path[i]) for i in range(depth)])
209
-
210
- def forward(self, x, defocus, strength):
211
- defocus = F.interpolate(defocus.to(x.dtype), size=x.shape[1:3], mode="bilinear", align_corners=False)
212
- for daab in self.blocks:
213
- x = daab(x, defocus, strength)
214
- return x
215
-
216
-
217
- class DefocusResidualGroup(nn.Module):
218
- """Defocus residual group (DRG, Fig. 3B): N DAABs, then a 3x3 convolution over the features and M_C, with a
219
- residual connection."""
220
-
221
- def __init__(self, embed_dim, cond_channels, depth, num_heads, ffn_dim, drop_path):
222
- super().__init__()
223
- self.residual_group = DAABStack(embed_dim, depth, num_heads, ffn_dim, drop_path)
224
- self.conv = nn.Conv2d(embed_dim + cond_channels, embed_dim, 3, 1, 1)
225
-
226
- def forward(self, x, cond, defocus, strength):
227
- y = self.residual_group(x, defocus, strength).permute(0, 3, 1, 2)
228
- return self.conv(torch.cat((y, cond), dim=1)).permute(0, 2, 3, 1) + x