深度学习单帧图像超分辨率重建算法【附代码】

✅博主简介:本人擅长建模仿真、数据分析、论文写作与指导,项目与课题经验交流。项目合作可私信或扫描文章底部二维码。


图像在人类生产生活中具有极大价值,而图像分辨率决定了其中存储的信息量。提高图像分辨率可改善信息量,图像超分辨率重建技术应运而生。近年来,基于深度学习的方法成为主流,但多数方法设计复杂网络结构以追求更好重建效果,这导致网络模型参数量和计算量较大,难以应用于计算资源有限的设备。同时,一些使用像素级损失训练的网络模型,重建图像往往过于平滑,缺乏纹理特征。

二、轻量级图像超分辨率重建网络 LMDFFN

  1. 核心轻量级特征提取块 LFEB

    • 利用通道划分将特征分组,这一方式能显著减少网络的参数量和计算量。通过将分组特征分别经过普通方形卷积和非对称卷积,可以提取不同形状的纹理特征。这样的设计使得网络在不增加过多计算负担的情况下,能够更好地捕捉图像中的各种纹理信息。
  2. 通道和空间注意力机制

    • 设计了一个更适用于图像超分辨率重建的通道和空间注意力机制。通道注意力有助于提取图像的纹理细节,能够让网络更加关注不同通道中对纹理表现重要的信息。空间注意力则可以关注不同特征图的不同空间位置,使得网络能够根据空间位置的重要性进行有针对性的处理。
  3. 深度可分离卷积在重建阶段的应用

    • 在模型的重建阶段,应用深度可分离卷积进一步降低模型的参数量。深度可分离卷积将传统卷积分解为深度卷积和逐点卷积,在保持相似性能的同时大大减少了计算量和参数量,使得模型更加轻量化,适合在资源受限的环境中运行。
     

    实验表明,LMDFFN 网络在具有较低模型参数量和计算量的情况下,在定量评价和视觉质量提升上都取得了优异的效果。它能够在不牺牲重建质量的前提下,降低对计算资源的需求,为图像超分辨率重建在各种设备上的应用提供了可能。

三、基于生成对抗网络的图像超分辨率重建算法 SRPGAN

  1. 生成模型的改进

    • 设计了双分支残差块代替传统的残差块。双分支分别为含有注意力机制的分支和无注意力机制的分支,这样的设计可以实现不同特征的组合。注意力机制分支能够突出重要特征,无注意力机制分支则可以提供更基础的特征信息,两者结合使得生成模型能够更好地捕捉图像的各种特征。
  2. 归一化方式的探索

    • 相对于传统的批量归一化层,使用更适合底层视觉问题的半实例归一化层。半实例归一化层在处理图像超分辨率重建等底层视觉问题时,能够更好地保留图像的细节和纹理信息,避免了批量归一化可能带来的一些问题,如对小批量数据不稳定性的影响。
  3. 判别模型的改进

    • 应用 PatchGAN 代替普通的 GAN。PatchGAN 能够加强对于局部纹理信息的改善,它通过对图像的局部区域进行判别,使得生成模型更加注重局部纹理的真实性和细节,从而提高重建图像的视觉质量。
import torch
import torch.nn as nn
import torch.optim as optim

# 定义轻量级特征提取块
class LFEB(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(LFEB, self).__init__()
        self.channel_split = in_channels // 2
        self.square_conv = nn.Conv2d(self.channel_split, out_channels // 2, kernel_size=3, padding=1)
        self.asymmetric_conv = nn.Conv2d(self.channel_split, out_channels // 2, kernel_size=(3, 1), padding=(1, 0))

    def forward(self, x):
        split_x = torch.split(x, self.channel_split, dim=1)
        square_out = self.square_conv(split_x[0])
        asymmetric_out = self.asymmetric_conv(split_x[1])
        return torch.cat([square_out, asymmetric_out], dim=1)

# 定义通道和空间注意力机制
class AttentionModule(nn.Module):
    def __init__(self, in_channels):
        super(AttentionModule, self).__init__()
        self.channel_att = nn.Sequential(
            nn.AdaptiveAvgPool2d(1),
            nn.Conv2d(in_channels, in_channels // 16, kernel_size=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(in_channels // 16, in_channels, kernel_size=1)
        )
        self.spatial_att = nn.Sequential(
            nn.Conv2d(in_channels, 1, kernel_size=1),
            nn.Sigmoid()
        )

    def forward(self, x):
        channel_att = self.channel_att(x)
        x = x * channel_att
        spatial_att = self.spatial_att(x)
        return x * spatial_att

# 定义轻量级图像超分辨率重建网络
class LMDFFN(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(LMDFFN, self).__init__()
        self.lfeb = LFEB(in_channels, 64)
        self.attention = AttentionModule(64)
        self.conv1 = nn.Conv2d(64, 64, kernel_size=3, padding=1)
        self.conv2 = nn.Conv2d(64, out_channels, kernel_size=3, padding=1)

    def forward(self, x):
        x = self.lfeb(x)
        x = self.attention(x)
        x = self.conv1(x)
        x = self.conv2(x)
        return x

# 定义生成模型中的双分支残差块
class DualBranchResidualBlock(nn.Module):
    def __init__(self, in_channels):
        super(DualBranchResidualBlock, self).__init__()
        self.branch1 = nn.Sequential(
            nn.Conv2d(in_channels, in_channels, kernel_size=3, padding=1),
            AttentionModule(in_channels),
            nn.ReLU(inplace=True),
            nn.Conv2d(in_channels, in_channels, kernel_size=3, padding=1)
        )
        self.branch2 = nn.Sequential(
            nn.Conv2d(in_channels, in_channels, kernel_size=3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(in_channels, in_channels, kernel_size=3, padding=1)
        )

    def forward(self, x):
        return x + self.branch1(x) + self.branch2(x)

# 定义生成模型
class Generator(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(Generator, self).__init__()
        self.conv1 = nn.Conv2d(in_channels, 64, kernel_size=9, padding=4)
        self.res_blocks = nn.Sequential(
            DualBranchResidualBlock(64),
            DualBranchResidualBlock(64),
            DualBranchResidualBlock(64),
            DualBranchResidualBlock(64),
            DualBranchResidualBlock(64),
            DualBranchResidualBlock(64)
        )
        self.conv2 = nn.Conv2d(64, out_channels, kernel_size=3, padding=1)

    def forward(self, x):
        x = self.conv1(x)
        x = self.res_blocks(x)
        return self.conv2(x)

# 定义判别模型
class Discriminator(nn.Module):
    def __init__(self, in_channels):
        super(Discriminator, self).__init__()
        self.conv1 = nn.Conv2d(in_channels, 64, kernel_size=4, stride=2, padding=1)
        self.conv2 = nn.Conv2d(64, 128, kernel_size=4, stride=2, padding=1)
        self.conv3 = nn.Conv2d(128, 256, kernel_size=4, stride=2, padding=1)
        self.conv4 = nn.Conv2d(256, 512, kernel_size=4, stride=1, padding=1)
        self.fc = nn.Linear(512 * 4 * 4, 1)

    def forward(self, x):
        x = nn.LeakyReLU(0.2)(self.conv1(x))
        x = nn.LeakyReLU(0.2)(self.conv2(x))
        x = nn.LeakyReLU(0.2)(self.conv3(x))
        x = nn.LeakyReLU(0.2)(self.conv4(x))
        x = x.view(x.size(0), -1)
        return torch.sigmoid(self.fc(x))

# 训练函数
def train(model, generator, discriminator, dataloader, optimizer, criterion):
    for epoch in range(num_epochs):
        for low_res, high_res in dataloader:
            optimizer.zero_grad()

            # 训练生成器
            generated_high_res = generator(low_res)
            g_loss = criterion(generated_high_res, high_res)
            g_loss.backward()
            optimizer.step()

            # 训练判别器
            real_labels = torch.ones_like(discriminator(high_res))
            fake_labels = torch.zeros_like(discriminator(generated_high_res.detach()))
            real_loss = criterion(discriminator(high_res), real_labels)
            fake_loss = criterion(discriminator(generated_high_res), fake_labels)
            d_loss = (real_loss + fake_loss) / 2
            discriminator.zero_grad()
            d_loss.backward()
            optimizer.step()

# 主函数
if __name__ == "__main__":
    in_channels = 3
    out_channels = 3
    num_epochs = 100
    batch_size = 16
    learning_rate = 0.0001

    model = LMDFFN(in_channels, out_channels)
    generator = Generator(in_channels, out_channels)
    discriminator = Discriminator(out_channels)
    optimizer = optim.Adam(list(model.parameters()) + list(generator.parameters()) + list(discriminator.parameters()), lr=learning_rate)
    criterion = nn.MSELoss()

    dataloader = # 创建数据加载器

    train(model, generator, discriminator, dataloader, optimizer, criterion)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坷拉博士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值