Files
2024-08-11 18:59:36 +07:00

197 lines
5.6 KiB
Python

import torch
import torch.nn as nn
import torch.nn.functional as F
from .layers import BasicConv, ResBlock
class EBlock(nn.Module):
def __init__(self, out_channel, num_res, data):
super(EBlock, self).__init__()
layers = [ResBlock(out_channel, out_channel, data) for _ in range(num_res - 1)]
layers.append(ResBlock(out_channel, out_channel, data, filter=True))
self.layers = nn.Sequential(*layers)
def forward(self, x):
return self.layers(x)
class DBlock(nn.Module):
def __init__(self, channel, num_res, data):
super(DBlock, self).__init__()
layers = [ResBlock(channel, channel, data) for _ in range(num_res - 1)]
layers.append(ResBlock(channel, channel, data, filter=True))
self.layers = nn.Sequential(*layers)
def forward(self, x):
return self.layers(x)
class SCM(nn.Module):
def __init__(self, out_plane):
super(SCM, self).__init__()
self.main = nn.Sequential(
BasicConv(3, out_plane // 4, kernel_size=3, stride=1, relu=True),
BasicConv(
out_plane // 4, out_plane // 2, kernel_size=1, stride=1, relu=True
),
BasicConv(
out_plane // 2, out_plane // 2, kernel_size=3, stride=1, relu=True
),
BasicConv(out_plane // 2, out_plane, kernel_size=1, stride=1, relu=False),
nn.InstanceNorm2d(out_plane, affine=True),
)
def forward(self, x):
x = self.main(x)
return x
class FAM(nn.Module):
def __init__(self, channel):
super(FAM, self).__init__()
self.merge = BasicConv(
channel * 2, channel, kernel_size=3, stride=1, relu=False
)
def forward(self, x1, x2):
return self.merge(torch.cat([x1, x2], dim=1))
class ConvIR(nn.Module):
def __init__(self, version, data):
super(ConvIR, self).__init__()
if version == "small":
num_res = 4
elif version == "base":
num_res = 8
elif version == "large":
num_res = 16
base_channel = 32
self.Encoder = nn.ModuleList(
[
EBlock(base_channel, num_res, data),
EBlock(base_channel * 2, num_res, data),
EBlock(base_channel * 4, num_res, data),
]
)
self.feat_extract = nn.ModuleList(
[
BasicConv(3, base_channel, kernel_size=3, relu=True, stride=1),
BasicConv(
base_channel, base_channel * 2, kernel_size=3, relu=True, stride=2
),
BasicConv(
base_channel * 2,
base_channel * 4,
kernel_size=3,
relu=True,
stride=2,
),
BasicConv(
base_channel * 4,
base_channel * 2,
kernel_size=4,
relu=True,
stride=2,
transpose=True,
),
BasicConv(
base_channel * 2,
base_channel,
kernel_size=4,
relu=True,
stride=2,
transpose=True,
),
BasicConv(base_channel, 3, kernel_size=3, relu=False, stride=1),
]
)
self.Decoder = nn.ModuleList(
[
DBlock(base_channel * 4, num_res, data),
DBlock(base_channel * 2, num_res, data),
DBlock(base_channel, num_res, data),
]
)
self.Convs = nn.ModuleList(
[
BasicConv(
base_channel * 4,
base_channel * 2,
kernel_size=1,
relu=True,
stride=1,
),
BasicConv(
base_channel * 2, base_channel, kernel_size=1, relu=True, stride=1
),
]
)
self.ConvsOut = nn.ModuleList(
[
BasicConv(base_channel * 4, 3, kernel_size=3, relu=False, stride=1),
BasicConv(base_channel * 2, 3, kernel_size=3, relu=False, stride=1),
]
)
self.FAM1 = FAM(base_channel * 4)
self.SCM1 = SCM(base_channel * 4)
self.FAM2 = FAM(base_channel * 2)
self.SCM2 = SCM(base_channel * 2)
def forward(self, x):
x_2 = F.interpolate(x, scale_factor=0.5)
x_4 = F.interpolate(x_2, scale_factor=0.5)
z2 = self.SCM2(x_2)
z4 = self.SCM1(x_4)
outputs = list()
# 256
x_ = self.feat_extract[0](x)
res1 = self.Encoder[0](x_)
# 128
z = self.feat_extract[1](res1)
z = self.FAM2(z, z2)
res2 = self.Encoder[1](z)
# 64
z = self.feat_extract[2](res2)
z = self.FAM1(z, z4)
z = self.Encoder[2](z)
z = self.Decoder[0](z)
z_ = self.ConvsOut[0](z)
# 128
z = self.feat_extract[3](z)
outputs.append(z_ + x_4)
z = torch.cat([z, res2], dim=1)
z = self.Convs[0](z)
z = self.Decoder[1](z)
z_ = self.ConvsOut[1](z)
# 256
z = self.feat_extract[4](z)
outputs.append(z_ + x_2)
z = torch.cat([z, res1], dim=1)
z = self.Convs[1](z)
z = self.Decoder[2](z)
z = self.feat_extract[5](z)
outputs.append(z + x)
return outputs
def build_net(version, data):
return ConvIR(version, data)