52Hz commited on
Commit
61098c4
1 Parent(s): a604a4f

Create SRMNet_SWFF.py

Browse files
Files changed (1) hide show
  1. model_arch/SRMNet_SWFF.py +265 -0
model_arch/SRMNet_SWFF.py ADDED
@@ -0,0 +1,265 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ from WT import DWT, IWT
4
+ ##---------- Basic Layers ----------
5
+ def conv3x3(in_chn, out_chn, bias=True):
6
+ layer = nn.Conv2d(in_chn, out_chn, kernel_size=3, stride=1, padding=1, bias=bias)
7
+ return layer
8
+
9
+ def conv(in_channels, out_channels, kernel_size, bias=False, stride=1):
10
+ return nn.Conv2d(
11
+ in_channels, out_channels, kernel_size,
12
+ padding=(kernel_size // 2), bias=bias, stride=stride)
13
+
14
+ def bili_resize(factor):
15
+ return nn.Upsample(scale_factor=factor, mode='bilinear', align_corners=False)
16
+
17
+ ##---------- Basic Blocks ----------
18
+ class UNetConvBlock(nn.Module):
19
+ def __init__(self, in_size, out_size, downsample):
20
+ super(UNetConvBlock, self).__init__()
21
+ self.downsample = downsample
22
+ self.block = SK_RDB(in_channels=in_size, growth_rate=out_size, num_layers=3)
23
+ if downsample:
24
+ self.downsample = PS_down(out_size, out_size, downscale=2)
25
+
26
+ def forward(self, x):
27
+ out = self.block(x)
28
+ if self.downsample:
29
+ out_down = self.downsample(out)
30
+ return out_down, out
31
+ else:
32
+ return out
33
+
34
+ class UNetUpBlock(nn.Module):
35
+ def __init__(self, in_size, out_size):
36
+ super(UNetUpBlock, self).__init__()
37
+ # self.up = nn.ConvTranspose2d(in_size, out_size, kernel_size=2, stride=2, bias=True)
38
+ self.up = PS_up(in_size, out_size, upscale=2)
39
+ self.conv_block = UNetConvBlock(in_size, out_size, False)
40
+
41
+ def forward(self, x, bridge):
42
+ up = self.up(x)
43
+ out = torch.cat([up, bridge], dim=1)
44
+ out = self.conv_block(out)
45
+ return out
46
+
47
+ ##---------- Resizing Modules (Pixel(Un)Shuffle) ----------
48
+ class PS_down(nn.Module):
49
+ def __init__(self, in_size, out_size, downscale):
50
+ super(PS_down, self).__init__()
51
+ self.UnPS = nn.PixelUnshuffle(downscale)
52
+ self.conv1 = nn.Conv2d((downscale**2) * in_size, out_size, 1, 1, 0)
53
+
54
+ def forward(self, x):
55
+ x = self.UnPS(x) # h/2, w/2, 4*c
56
+ x = self.conv1(x)
57
+ return x
58
+
59
+ class PS_up(nn.Module):
60
+ def __init__(self, in_size, out_size, upscale):
61
+ super(PS_up, self).__init__()
62
+
63
+ self.PS = nn.PixelShuffle(upscale)
64
+ self.conv1 = nn.Conv2d(in_size//(upscale**2), out_size, 1, 1, 0)
65
+
66
+ def forward(self, x):
67
+ x = self.PS(x) # h/2, w/2, 4*c
68
+ x = self.conv1(x)
69
+ return x
70
+
71
+ ##---------- Selective Kernel Feature Fusion (SKFF) ----------
72
+ class SKFF(nn.Module):
73
+ def __init__(self, in_channels, height=3, reduction=8, bias=False):
74
+ super(SKFF, self).__init__()
75
+
76
+ self.height = height
77
+ d = max(int(in_channels / reduction), 4)
78
+
79
+ self.avg_pool = nn.AdaptiveAvgPool2d(1)
80
+ self.conv_du = nn.Sequential(nn.Conv2d(in_channels, d, 1, padding=0, bias=bias), nn.PReLU())
81
+
82
+ self.fcs = nn.ModuleList([])
83
+ for i in range(self.height):
84
+ self.fcs.append(nn.Conv2d(d, in_channels, kernel_size=1, stride=1, bias=bias))
85
+
86
+ self.softmax = nn.Softmax(dim=1)
87
+
88
+ def forward(self, inp_feats):
89
+ batch_size, n_feats, H, W = inp_feats[1].shape
90
+
91
+ inp_feats = torch.cat(inp_feats, dim=1)
92
+ inp_feats = inp_feats.view(batch_size, self.height, n_feats, inp_feats.shape[2], inp_feats.shape[3])
93
+
94
+ feats_U = torch.sum(inp_feats, dim=1)
95
+ feats_S = self.avg_pool(feats_U)
96
+ feats_Z = self.conv_du(feats_S)
97
+
98
+ attention_vectors = [fc(feats_Z) for fc in self.fcs]
99
+ attention_vectors = torch.cat(attention_vectors, dim=1)
100
+ attention_vectors = attention_vectors.view(batch_size, self.height, n_feats, 1, 1)
101
+
102
+ attention_vectors = self.softmax(attention_vectors)
103
+ feats_V = torch.sum(inp_feats * attention_vectors, dim=1)
104
+
105
+ return feats_V
106
+
107
+ ##---------- Selective Wavelet Feature Fusion (SKFF) ----------
108
+ class SWFF(nn.Module):
109
+ def __init__(self, in_channels, height=3, reduction=8, bias=False):
110
+ super(SWFF, self).__init__()
111
+
112
+ self.height = height
113
+ d = max(int(in_channels / reduction), 4)
114
+
115
+ self.avg_pool = nn.AdaptiveAvgPool2d(1)
116
+ self.wav_conv_du = nn.Sequential(nn.Conv2d(4*in_channels, d, 1, padding=0, bias=bias), nn.PReLU())
117
+ self.dwt = DWT()
118
+ self.iwt = IWT()
119
+ self.fcs = nn.ModuleList([])
120
+ for i in range(self.height):
121
+ self.fcs.append(nn.Conv2d(d, in_channels*4, kernel_size=1, stride=1, bias=bias))
122
+
123
+ self.softmax = nn.Softmax(dim=1)
124
+
125
+ def forward(self, inp_feats):
126
+ batch_size, n_feats, H, W = inp_feats[0].shape
127
+ wavelet_rep = [(self.dwt(each)) for each in inp_feats]
128
+
129
+ wav_inp_feats = torch.cat(wavelet_rep, dim=1)
130
+ wav_inp_feats = wav_inp_feats.view(batch_size, self.height, n_feats*4, wav_inp_feats.shape[2], wav_inp_feats.shape[3])
131
+
132
+ inp_feats = torch.cat(inp_feats, dim=1)
133
+ inp_feats = inp_feats.view(batch_size, self.height, n_feats, inp_feats.shape[2], inp_feats.shape[3])
134
+
135
+ feats_U = torch.sum(wav_inp_feats, dim=1)
136
+ feats_S = self.avg_pool(feats_U)
137
+ feats_Z = self.wav_conv_du(feats_S)
138
+
139
+ attention_vectors = [self.avg_pool(self.iwt(fc(feats_Z))) for fc in self.fcs]
140
+ attention_vectors = torch.cat(attention_vectors, dim=1)
141
+ attention_vectors = attention_vectors.view(batch_size, self.height, n_feats, 1, 1)
142
+
143
+ attention_vectors = self.softmax(attention_vectors)
144
+ feats_V = torch.sum(inp_feats * attention_vectors, dim=1)
145
+
146
+ return feats_V
147
+
148
+ ##---------- Dense Block ----------
149
+ class DenseLayer(nn.Module):
150
+ def __init__(self, in_channels, out_channels, I):
151
+ super(DenseLayer, self).__init__()
152
+ self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=3 // 2)
153
+ self.relu = nn.ReLU(inplace=True)
154
+ self.sk = SKFF(out_channels, height=2, reduction=8, bias=False)
155
+
156
+ def forward(self, x):
157
+ x1 = self.relu(self.conv(x))
158
+ # output = torch.cat([x, x1], 1) # -> RDB
159
+ output = self.sk((x, x1))
160
+ return output
161
+
162
+ ##---------- Selective Kernel Residual Dense Block (SK-RDB) ----------
163
+ class SK_RDB(nn.Module):
164
+ def __init__(self, in_channels, growth_rate, num_layers):
165
+ super(SK_RDB, self).__init__()
166
+ self.identity = nn.Conv2d(in_channels, growth_rate, 1, 1, 0)
167
+ self.layers = nn.Sequential(
168
+ *[DenseLayer(in_channels, in_channels, I=i) for i in range(num_layers)]
169
+ )
170
+ self.lff = nn.Conv2d(in_channels, growth_rate, kernel_size=1)
171
+
172
+ def forward(self, x):
173
+ res = self.identity(x)
174
+ x = self.layers(x)
175
+ x = self.lff(x)
176
+ return res + x
177
+
178
+ ##---------- testNet ----------
179
+ class SRMNet_SWFF(nn.Module):
180
+ def __init__(self, in_chn=3, wf=96, depth=4):
181
+ super(SRMNet_SWFF, self).__init__()
182
+ self.depth = depth
183
+ self.down_path = nn.ModuleList()
184
+ self.bili_down = bili_resize(0.5)
185
+ self.conv_01 = nn.Conv2d(in_chn, wf, 3, 1, 1)
186
+
187
+ # encoder of UNet-64
188
+ prev_channels = 0
189
+ for i in range(depth): # 0,1,2,3
190
+ downsample = True if (i + 1) < depth else False
191
+ self.down_path.append(UNetConvBlock(prev_channels + wf, (2 ** i) * wf, downsample))
192
+ prev_channels = (2 ** i) * wf
193
+
194
+ # decoder of UNet-64
195
+ self.up_path = nn.ModuleList()
196
+ self.skip_conv = nn.ModuleList()
197
+ self.conv_up = nn.ModuleList()
198
+ self.bottom_conv = nn.Conv2d(prev_channels, wf, 3, 1, 1)
199
+ self.bottom_up = bili_resize(2 ** (depth-1))
200
+
201
+ for i in reversed(range(depth - 1)):
202
+ self.up_path.append(UNetUpBlock(prev_channels, (2 ** i) * wf))
203
+ self.skip_conv.append(nn.Conv2d((2 ** i) * wf, (2 ** i) * wf, 3, 1, 1))
204
+ self.conv_up.append(nn.Sequential(*[bili_resize(2 ** i), nn.Conv2d((2 ** i) * wf, wf, 3, 1, 1)]))
205
+ # *[nn.Conv2d((2 ** i) * wf, wf, 3, 1, 1), bili_resize(2 ** i)])
206
+ prev_channels = (2 ** i) * wf
207
+
208
+ self.final_ff = SKFF(in_channels=wf, height=depth)
209
+ self.last = conv3x3(prev_channels, in_chn, bias=True)
210
+
211
+ def forward(self, x):
212
+ img = x
213
+ scale_img = img
214
+
215
+ ##### shallow conv #####
216
+ x1 = self.conv_01(img)
217
+ encs = []
218
+ ######## UNet-64 ########
219
+ # Down-path (Encoder)
220
+ for i, down in enumerate(self.down_path):
221
+ if i == 0: # top layer
222
+ x1, x1_up = down(x1)
223
+ encs.append(x1_up)
224
+ elif (i + 1) < self.depth: # middle layer
225
+ scale_img = self.bili_down(scale_img)
226
+ left_bar = self.conv_01(scale_img)
227
+ x1 = torch.cat([x1, left_bar], dim=1)
228
+ x1, x1_up = down(x1)
229
+ encs.append(x1_up)
230
+ else: # lowest layer
231
+ scale_img = self.bili_down(scale_img)
232
+ left_bar = self.conv_01(scale_img)
233
+ x1 = torch.cat([x1, left_bar], dim=1)
234
+ x1 = down(x1)
235
+
236
+ # Up-path (Decoder)
237
+ ms_result = [self.bottom_up(self.bottom_conv(x1))]
238
+ for i, up in enumerate(self.up_path):
239
+ x1 = up(x1, self.skip_conv[i](encs[-i - 1]))
240
+ ms_result.append(self.conv_up[i](x1))
241
+
242
+ # Multi-scale selective feature fusion
243
+ msff_result = self.final_ff(ms_result)
244
+
245
+ ##### Reconstruct #####
246
+ out_1 = self.last(msff_result) + img
247
+
248
+ return out_1
249
+
250
+ if __name__ == "__main__":
251
+ from thop import profile
252
+ input = torch.ones(1, 3, 256, 256, dtype=torch.float, requires_grad=False)
253
+
254
+ model = SRMNet_SWFF(in_chn=3, wf=96, depth=4)
255
+ out = model(input)
256
+ flops, params = profile(model, inputs=(input,))
257
+
258
+ # RDBlayer = SK_RDB(in_channels=64, growth_rate=64, num_layers=3)
259
+ # print(RDBlayer)
260
+ # out = RDBlayer(input)
261
+ # flops, params = profile(RDBlayer, inputs=(input,))
262
+ print('input shape:', input.shape)
263
+ print('parameters:', params/1e6)
264
+ print('flops', flops/1e9)
265
+ print('output shape', out.shape)