umairahmad1789's picture
initial commit
efd5df3 verified
import torch
import torch.nn as nn
class ResidualConvBlock(nn.Module):
def __init__(self, in_channels, out_channels):
super(ResidualConvBlock, self).__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1)
self.in1 = nn.InstanceNorm2d(out_channels)
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)
self.in2 = nn.InstanceNorm2d(out_channels)
self.relu = nn.LeakyReLU(inplace=True)
self.downsample = nn.Conv2d(in_channels, out_channels, kernel_size=1) if in_channels != out_channels else None
def forward(self, x):
residual = x
out = self.relu(self.in1(self.conv1(x)))
out = self.in2(self.conv2(out))
if self.downsample:
residual = self.downsample(x)
out += residual
return self.relu(out)
class AttentionGate(nn.Module):
def __init__(self, F_g, F_l, F_int):
super(AttentionGate, self).__init__()
self.W_g = nn.Sequential(
nn.Conv2d(F_g, F_int, kernel_size=1, stride=1, padding=0, bias=True),
nn.InstanceNorm2d(F_int)
)
self.W_x = nn.Sequential(
nn.Conv2d(F_l, F_int, kernel_size=1, stride=1, padding=0, bias=True),
nn.InstanceNorm2d(F_int)
)
self.psi = nn.Sequential(
nn.Conv2d(F_int, 1, kernel_size=1, stride=1, padding=0, bias=True),
nn.InstanceNorm2d(1),
nn.Sigmoid()
)
self.relu = nn.LeakyReLU(inplace=True)
def forward(self, g, x):
g1 = self.W_g(g)
x1 = self.W_x(x)
psi = self.relu(g1 + x1)
psi = self.psi(psi)
return x * psi
class EnhancedUNet(nn.Module):
def __init__(self, n_channels, n_classes):
super(EnhancedUNet, self).__init__()
self.n_channels = n_channels
self.n_classes = n_classes
self.inc = ResidualConvBlock(n_channels, 64)
self.down1 = nn.Sequential(nn.MaxPool2d(2), ResidualConvBlock(64, 128))
self.down2 = nn.Sequential(nn.MaxPool2d(2), ResidualConvBlock(128, 256))
self.down3 = nn.Sequential(nn.MaxPool2d(2), ResidualConvBlock(256, 512))
self.down4 = nn.Sequential(nn.MaxPool2d(2), ResidualConvBlock(512, 1024))
self.dilation = nn.Sequential(
nn.Conv2d(1024, 1024, kernel_size=3, padding=2, dilation=2),
nn.InstanceNorm2d(1024),
nn.LeakyReLU(inplace=True),
nn.Conv2d(1024, 1024, kernel_size=3, padding=4, dilation=4),
nn.InstanceNorm2d(1024),
nn.LeakyReLU(inplace=True)
)
self.up4 = nn.ConvTranspose2d(1024, 512, kernel_size=2, stride=2)
self.att4 = AttentionGate(F_g=512, F_l=512, F_int=256)
self.up_conv4 = ResidualConvBlock(1024, 512)
self.up3 = nn.ConvTranspose2d(512, 256, kernel_size=2, stride=2)
self.att3 = AttentionGate(F_g=256, F_l=256, F_int=128)
self.up_conv3 = ResidualConvBlock(512, 256)
self.up2 = nn.ConvTranspose2d(256, 128, kernel_size=2, stride=2)
self.att2 = AttentionGate(F_g=128, F_l=128, F_int=64)
self.up_conv2 = ResidualConvBlock(256, 128)
self.up1 = nn.ConvTranspose2d(128, 64, kernel_size=2, stride=2)
self.att1 = AttentionGate(F_g=64, F_l=64, F_int=32)
self.up_conv1 = ResidualConvBlock(128, 64)
self.outc = nn.Conv2d(64, n_classes, kernel_size=1)
self.dropout = nn.Dropout(0.5)
def forward(self, x):
x1 = self.inc(x)
x2 = self.down1(x1)
x2 = self.dropout(x2)
x3 = self.down2(x2)
x3 = self.dropout(x3)
x4 = self.down3(x3)
x4 = self.dropout(x4)
x5 = self.down4(x4)
x5 = self.dilation(x5)
x5 = self.dropout(x5)
x = self.up4(x5)
x4 = self.att4(g=x, x=x4)
x = torch.cat([x4, x], dim=1)
x = self.up_conv4(x)
x = self.dropout(x)
x = self.up3(x)
x3 = self.att3(g=x, x=x3)
x = torch.cat([x3, x], dim=1)
x = self.up_conv3(x)
x = self.dropout(x)
x = self.up2(x)
x2 = self.att2(g=x, x=x2)
x = torch.cat([x2, x], dim=1)
x = self.up_conv2(x)
x = self.dropout(x)
x = self.up1(x)
x1 = self.att1(g=x, x=x1)
x = torch.cat([x1, x], dim=1)
x = self.up_conv1(x)
logits = self.outc(x)
return logits