jamino30's picture
Upload folder using huggingface_hub
ecf0440 verified
import torch
import torch.nn as nn
import torch.nn.functional as F
def init_weight(layer):
nn.init.xavier_uniform_(layer.weight)
if layer.bias is not None:
nn.init.constant_(layer.bias, 0)
class ConvBlock(nn.Module):
def __init__(self, in_channel, out_channel, dilation=1, dropout_rate=0.3):
super(ConvBlock, self).__init__()
self.conv = nn.Conv2d(in_channel, out_channel, kernel_size=3, stride=1, padding=dilation, dilation=dilation)
self.bn = nn.BatchNorm2d(out_channel)
self.relu = nn.ReLU(inplace=True)
self.dropout = nn.Dropout2d(p=dropout_rate) # custom - add dropout layer
init_weight(self.conv)
def forward(self, x):
x = self.conv(x)
x = self.bn(x)
x = self.relu(x)
self.dropout(x)
return x
class RSU(nn.Module):
def __init__(self, L, C_in, C_out, M):
super(RSU, self).__init__()
self.conv = ConvBlock(C_in, C_out)
self.enc = nn.ModuleList([ConvBlock(C_out, M)])
for _ in range(L-2):
self.enc.append(ConvBlock(M, M))
self.mid = ConvBlock(M, M, dilation=2)
self.dec = nn.ModuleList([ConvBlock(2*M, M) for _ in range(L-2)])
self.dec.append(ConvBlock(2*M, C_out))
self.downsample = nn.MaxPool2d(2, stride=2)
self.upsample = nn.Upsample(scale_factor=2, mode='bilinear')
def forward(self, x):
x = self.conv(x)
out = []
for i, enc in enumerate(self.enc):
if i == 0: out.append(enc(x))
else: out.append(enc(self.downsample(out[i-1])))
y = self.mid(out[-1])
for i, dec in enumerate(self.dec):
if i > 0: y = self.upsample(y)
y = dec(torch.cat((out[len(self.dec)-i-1], y), dim=1))
return x + y
class RSU4F(nn.Module):
def __init__(self, C_in, C_out, M):
super(RSU4F, self).__init__()
self.conv = ConvBlock(C_in, C_out)
self.enc = nn.ModuleList([
ConvBlock(C_out, M),
ConvBlock(M, M, dilation=2),
ConvBlock(M, M, dilation=4)
])
self.mid = ConvBlock(M, M, dilation=8)
self.dec = nn.ModuleList([
ConvBlock(2*M, M, dilation=4),
ConvBlock(2*M, M, dilation=2),
ConvBlock(2*M, C_out)
])
def forward(self, x):
x = self.conv(x)
out = []
for i, enc in enumerate(self.enc):
if i == 0: out.append(enc(x))
else: out.append(enc(out[i-1]))
y = self.mid(out[-1])
for i, dec in enumerate(self.dec):
y = dec(torch.cat((out[len(self.dec)-i-1], y), dim=1))
return x + y
class U2Net(nn.Module):
def __init__(self, dropout_rate=0.3):
super(U2Net, self).__init__()
self.enc = nn.ModuleList([
RSU(L=7, C_in=3, C_out=64, M=32),
RSU(L=6, C_in=64, C_out=128, M=32),
RSU(L=5, C_in=128, C_out=256, M=64),
RSU(L=4, C_in=256, C_out=512, M=128),
RSU4F(C_in=512, C_out=512, M=256),
RSU4F(C_in=512, C_out=512, M=256)
])
self.dec = nn.ModuleList([
RSU4F(C_in=1024, C_out=512, M=256),
RSU(L=4, C_in=1024, C_out=256, M=128),
RSU(L=5, C_in=512, C_out=128, M=64),
RSU(L=6, C_in=256, C_out=64, M=32),
RSU(L=7, C_in=128, C_out=64, M=16)
])
self.convs = nn.ModuleList([
nn.Conv2d(64, 1, 3, padding=1),
nn.Conv2d(64, 1, 3, padding=1),
nn.Conv2d(128, 1, 3, padding=1),
nn.Conv2d(256, 1, 3, padding=1),
nn.Conv2d(512, 1, 3, padding=1),
nn.Conv2d(512, 1, 3, padding=1)
])
self.lastconv = nn.Conv2d(6, 1, 1)
self.downsample = nn.MaxPool2d(2, stride=2)
self.dropout = nn.Dropout(p=dropout_rate) # custom - add dropout layer
init_weight(self.lastconv)
for conv in self.convs:
init_weight(conv)
def upsample(self, x, target):
return F.interpolate(x, size=target.shape[2:], mode='bilinear')
def forward(self, x):
enc_out = []
for i, enc in enumerate(self.enc):
if i == 0: enc_out.append(enc(x))
else: enc_out.append(enc(self.downsample(enc_out[i-1])))
dec_out = [enc_out[-1]]
for i, dec in enumerate(self.dec):
dec_out.append(dec(torch.cat((self.upsample(dec_out[i], enc_out[4-i]), enc_out[4-i]), dim=1)))
side_out = []
for i, conv in enumerate(self.convs):
if i == 0: side_out.append(self.dropout(conv(dec_out[5])))
else: side_out.append(self.upsample(self.dropout(conv(dec_out[5-i])), side_out[0]))
side_out.append(self.lastconv(torch.cat(side_out, dim=1)))
# logits (no sigmoid)
return [s.squeeze(1) for s in side_out]