【百战GAN】SRGAN人脸低分辨率老照片修复代码实战

基于GAN对抗网进行图像修复 定义了初始化函数init_weights,用于初始化卷积层、反卷积层和批归一化层的权重。同时,还定义梯度更新函数set_params,用于设置模型参数是否需要梯度更新。ResDown模块用于下采样操作,它包含三个卷积层和一个激活函数。输入x经过卷积和批归一化操作得到特征图x,然后通过上采样得到特征图skip。最后将特征图x与特征图skip相加,并经过激活函数得到输出特征图。ResUp模块用于上采样操作,它也包含三个卷积层和一个激活函数。输入x经过上采样得到特征图x,然后通过卷积和批归一化操作得到特征图x。 阅读详情

大家好,欢迎来到专栏《百战GAN》,在这个专栏里,我们会进行算法的核心思想讲解,代码的详解,模型的训练和测试等内容。

作者&编辑 | 言有三

adbb298f53df0493d32ce202f7792662.jpeg

本文资源与生成结果展示

本文篇幅:7000字

背景要求:会使用Python和Pytorch

附带资料:参考论文和项目

1 项目背景

了解GAN的同学都知道,GAN擅长于捕捉概率分布,因此非常适合图像生成类任务。我们在图片视频拍摄以及传输过程中,经常会进行图像的压缩,导致图像分辨率过低,另外早些年的设备拍摄出来的照片也存在分辨率过低的问题,比如10年前的320*240分辨率。

9f42034b99037836dab0de7f369856e1.jpeg

要解决此问题,需要使用到图像超分辩技术。

2 原理简介

图像超分辩任务输入是一张低分辨率的图像,输出是一张对它进行分辨率增大的图片,下面是一个常用的框架示意图[1]:

c7c36b7600b7b20657ceae3b800e7d64.png

该框架首先对输入图使用插值方法进行上采样,然后使用卷积层对输入进行学习,这种框架的劣势是计算代价比较大,因为整个网络是对高分辨率图操作。

随后研究者提出在网络的后端进行分辨率放大,通过扩充通道数,然后将其重新分布来获得高分辨率图,这套操作被称为(PixShuffle)[2],这样整个网络大部分计算量是对低分辨率图操作,如下图:

58aa1ff43651b74e7e0bdae5839a8dfb.png

对于维度为H×W×C的图像,标准反卷积操作输出的特征图维度为rH×rW×C,其中r就是需要放大的倍数,而从图中可以看出,亚像素卷积层的输出特征图维度为H×W×C×r×r,即特征图与输入图片的尺寸保持一致,但是通道数被扩充为原来的r×r倍,然后再进行重新排列得到高分辨率的结果。

整个流程因为使用了更小的图像输入,从而可以使用更小的卷积核获取较大的感受野,这既使得输入图片中邻域像素点的信息得到有效利用,还避免了计算复杂度的增加,是一种将空间上采样问题转换为通道上采样问题的思路,被大多数主流超分模型采用为上采样模块。

以上构成了图像超分辨的基本思路,之后Twitter的研究者们使用ResNet作为生成器结构,使用VGG作为判别器结构,提出了SRGAN[3]模型,模型结构示意图如下图:

004e06e3edd992d660fa86fcbadda928.png

图中生成器结构包含了若干个不改变特征分辨率的残差模块和多个基于亚像素卷积的后上采样模块。

判别器结构则包含了若干个通道数不断增加的卷积层,每次特征通道数增加一倍时,特征分辨率降低为原来的一半。

SRGAN模型基于VGG网络特征构建内容损失函数(content loss),代替了之前的MSE损失函数,通过生成器和判别器的对抗学习取得了视觉感知上更好的重建结果。

3 模型训练

大多数超分重建任务的数据集都是通过从高分辨率图像进行下采样获得,论文中往往选择ImageNet数据集,由于我们这里打算专门对人脸进行清晰度恢复,因此选择了一个常用的高清人脸数据集,CelebA-HQ,它发布于 2019 年,包含30000张不同属性的高清人脸图,其中图像大小均为1024×1024,预览如下。

e02f41bf462f2c151eb006b02f18ec71.jpeg

接下来我们对代码进行解读:

3.1 数据预处理

图像超分辨数据集往往都是从高分辨率图进行采样得到低分辨率图,然后组成训练用的图像对,下面是对训练集和验证集中数据处理的核心代码:

from os import listdir

from os.path import join

import numpy as np

from PIL import Image

from torch.utils.data.dataset import Dataset

from torchvision.transforms import Compose, RandomCrop, ToTensor, ToPILImage, CenterCrop, Resize

import imgaug.augmenters as iaa

aug = iaa.JpegCompression(compression=(0, 50))

## 基于上采样因子对裁剪尺寸进行调整,使其为upscale_factor的整数倍

def calculate_valid_crop_size(crop_size, upscale_factor):

return crop_size - (crop_size % upscale_factor)

## 训练集高分辨率图预处理函数

def train_hr_transform(crop_size):

    return Compose([

        RandomCrop(crop_size),

        ToTensor(),

])

## 训练集低分辨率图预处理函数

def train_lr_transform(crop_size, upscale_factor):

    return Compose([

        ToPILImage(),

        Resize(crop_size // upscale_factor, interpolation=Image.BICUBIC),

        ToTensor()

    ])

## 训练数据集类

class TrainDatasetFromFolder(Dataset):

    def __init__(self, dataset_dir, crop_size, upscale_factor):

        super(TrainDatasetFromFolder, self).__init__()

        self.image_filenames = [join(dataset_dir, x) for x in listdir(dataset_dir) if is_image_file(x)] ##获得所有图像

crop_size = calculate_valid_crop_size(crop_size, upscale_factor)##获得裁剪尺寸

        self.hr_transform = train_hr_transform(crop_size) ##高分辨率图预处理函数

        self.lr_transform = train_lr_transform(crop_size, upscale_factor) ##低分辨率图预处理函数

##数据集迭代指针

    def __getitem__(self, index): 

        hr_image = self.hr_transform(Image.open(self.image_filenames[index])) ##随机裁剪获得高分辨率图

        lr_image = self.lr_transform(hr_image) ##获得低分辨率图

img = np.array(lr_image)

image_aug = aug(image=img)

lr_image = Image.fromarray(image_aug.astype('uint8')).convert('RGB') 

        return ToTensor()(lr_image), hr_image

    def __len__(self):

        return len(self.image_filenames)

## 验证数据集类

class ValDatasetFromFolder(Dataset):

    def __init__(self, dataset_dir, upscale_factor):

        super(ValDatasetFromFolder, self).__init__()

        self.upscale_factor = upscale_factor

        self.image_filenames = [join(dataset_dir, x) for x in listdir(dataset_dir) if is_image_file(x)]

    def __getitem__(self, index):

        hr_image = Image.open(self.image_filenames[index])

##获得图像窄边获得裁剪尺寸

        w, h = hr_image.size

        crop_size = calculate_valid_crop_size(min(w, h), self.upscale_factor)

        lr_scale = Resize(crop_size // self.upscale_factor, interpolation=Image.BICUBIC)

        hr_scale = Resize(crop_size, interpolation=Image.BICUBIC)

        hr_image = CenterCrop(crop_size)(hr_image) ##中心裁剪获得高分辨率图

        lr_image = lr_scale(hr_image) ##获得低分辨率图

img = np.array(lr_image)

image_aug = aug(image=img)

lr_image = Image.fromarray(image_aug.astype('uint8')).convert('RGB') 

        hr_restore_img = hr_scale(lr_image)

        return ToTensor()(lr_image), ToTensor()(hr_image)

    def __len__(self):

        return len(self.image_filenames)

从上述代码可以看出,包含了两个预处理函数接口,分别是train_hr_transform,train_lr_transform。train_hr_transform包含的操作主要是随机裁剪,而train_lr_transform包含的操作主要是缩放。

另外还有一个函数calculate_valid_crop_size,对于训练集来说,它用于当配置的图像尺寸crop_size不能整除上采样因子upscale_factor时对crop_size进行调整,我们在使用的时候应该避免这一点,即配置crop_size让它等于upscale_factor的整数倍。对于验证集,图像的窄边min(w, h)会被用于crop_size的初始化,所以该函数的作用是当图像的窄边不能整除上采样因子upscale_factor时对crop_size进行调整。

训练集类TrainDatasetFromFolder包含了若干操作,它使用train_hr_transform从原图像中随机裁剪大小为裁剪尺寸的正方形的图像,使用train_lr_transform获得对应的低分辨率图。而验证集类ValDatasetFromFolder则将图像按照调整后的crop_size进行中心裁剪,然后使用train_lr_transform获得对应的低分辨率图。

在这里我们使用了随机裁剪和JPEG噪声压缩作为训练时的数据增强操作,JPEG噪声的添加使用了imaaug库,其项目地址为https://github.com/aleju/imgaug,下图展示了对一些样本添加不同幅度的JPEG噪声的图像。

f2accff34ed4443cd897f3d3b6314d1f.png

第1行为分辨率512×512大小的原图,第2行是缩放为128×128大小,不添加JPEG压缩噪声的图,第3行和第4行分别是缩放为128×128大小,并且用imgaug库添加幅度为30%和90%的JPEG压缩噪声的图像。可以看出JPEG噪声对图像质量影响很大,尤其是当噪声幅度很大时,斑块效应非常明显。我们在后面会比较添加不同幅度的JPEG噪声与不添加JPEG噪声的模型结果对比,验证对于真实的图像超分辨任务,更接近真实退化过程的数据增强操作是必要的。

3.2 生成器网络

生成器是一个基于残差模块的上采样模型,它的定义包括残差模块,上采样模块以及主干模型,如下。

## 残差模块

class ResidualBlock(nn.Module):

    def __init__(self, channels):

        super(ResidualBlock, self).__init__()

        ## 两个卷积层,卷积核大小为3×3,通道数不变

        self.conv1 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)

        self.bn1 = nn.BatchNorm2d(channels)

        self.prelu = nn.PReLU()

        self.conv2 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)

        self.bn2 = nn.BatchNorm2d(channels)

    def forward(self, x):

        residual = self.conv1(x)

        residual = self.bn1(residual)

        residual = self.prelu(residual)

        residual = self.conv2(residual)

        residual = self.bn2(residual)

        return x + residual

## 上采样模块,每一个恢复分辨率为2

class UpsampleBLock(nn.Module):

    def __init__(self, in_channels, up_scale):

        super(UpsampleBLock, self).__init__()

        ## 卷积层,输入通道数为in_channels,输出通道数为in_channels * up_scale ** 2

        self.conv = nn.Conv2d(in_channels, in_channels * up_scale ** 2, kernel_size=3, padding=1)

        ## PixelShuffle上采样层,来自于后上采样结构

        self.pixel_shuffle = nn.PixelShuffle(up_scale)

        self.prelu = nn.PReLU()

    def forward(self, x):

        x = self.conv(x)

        x = self.pixel_shuffle(x)

        x = self.prelu(x)

        return x

## 生成模型

class Generator(nn.Module):

    def __init__(self, scale_factor):

        upsample_block_num = int(math.log(scale_factor, 2))

        super(Generator, self).__init__()

        ## 第一个卷积层,卷积核大小为9×9,输入通道数为3,输出通道数为64

        self.block1 = nn.Sequential(

            nn.Conv2d(3, 64, kernel_size=9, padding=4),

            nn.PReLU()

        )

        ## 6个残差模块

        self.block2 = ResidualBlock(64)

        self.block3 = ResidualBlock(64)

        self.block4 = ResidualBlock(64)

        self.block5 = ResidualBlock(64)

        self.block6 = ResidualBlock(64)

        self.block7 = nn.Sequential(

            nn.Conv2d(64, 64, kernel_size=3, padding=1),

            nn.BatchNorm2d(64)

        )

        ## upsample_block_num个上采样模块,每一个上采样模块恢复2倍的上采样倍率

        block8 = [UpsampleBLock(64, 2) for _ in range(upsample_block_num)]

        ## 最后一个卷积层,卷积核大小为9×9,输入通道数为64,输出通道数为3

        block8.append(nn.Conv2d(64, 3, kernel_size=9, padding=4))

        self.block8 = nn.Sequential(*block8)

    def forward(self, x):

        block1 = self.block1(x)

        block2 = self.block2(block1)

        block3 = self.block3(block2)

        block4 = self.block4(block3)

        block5 = self.block5(block4)

        block6 = self.block6(block5)

        block7 = self.block7(block6)

        block8 = self.block8(block1 + block7)

        return (torch.tanh(block8) + 1) / 2

在上述的生成器定义中,调用了nn.PixelShuffle模块来实现上采样,它的具体原理就是上面提到的pixelshuffle。

3.3 判别器定义

判别器是一个普通的类似于VGG的CNN模型:

## 残差模块

class Discriminator(nn.Module):

    def __init__(self):

        super(Discriminator, self).__init__()

        self.net = nn.Sequential(

            nn.Conv2d(3, 64, kernel_size=3, padding=1),

            nn.LeakyReLU(0.2),

            nn.Conv2d(64, 64, kernel_size=3, stride=2, padding=1),

            nn.BatchNorm2d(64),

            nn.LeakyReLU(0.2),

            nn.Conv2d(64, 128, kernel_size=3, padding=1),

            nn.BatchNorm2d(128),

            nn.LeakyReLU(0.2),

            nn.Conv2d(128, 128, kernel_size=3, stride=2, padding=1),

            nn.BatchNorm2d(128),

            nn.LeakyReLU(0.2),

            nn.Conv2d(128, 256, kernel_size=3, padding=1),

            nn.BatchNorm2d(256),

            nn.LeakyReLU(0.2),

            nn.Conv2d(256, 256, kernel_size=3, stride=2, padding=1),

            nn.BatchNorm2d(256),

            nn.LeakyReLU(0.2),

            nn.Conv2d(256, 512, kernel_size=3, padding=1),

            nn.BatchNorm2d(512),

            nn.LeakyReLU(0.2),

            nn.Conv2d(512, 512, kernel_size=3, stride=2, padding=1),

            nn.BatchNorm2d(512),

            nn.LeakyReLU(0.2),

            nn.AdaptiveAvgPool2d(1),

            ## 两个全连接层,使用卷积实现

            nn.Conv2d(512, 1024, kernel_size=1),

            nn.LeakyReLU(0.2),

            nn.Conv2d(1024, 1, kernel_size=1)

        )

    def forward(self, x):

        batch_size = x.size(0)

        return torch.sigmoid(self.net(x).view(batch_size))

3.4 损失函数定义

损失函数的定义是框架中的重点,下面主要看生成器的损失,因为判别器就是一个分类损失。

## 生成器损失定义

class GeneratorLoss(nn.Module):

    def __init__(self):

        super(GeneratorLoss, self).__init__()

        vgg = vgg16(pretrained=True)

        loss_network = nn.Sequential(*list(vgg.features)[:31]).eval()

        for param in loss_network.parameters():

            param.requires_grad = False

        self.loss_network = loss_network

        self.mse_loss = nn.MSELoss() ##MSE损失

        self.tv_loss = TVLoss() ##TV平滑损失

    def forward(self, out_labels, out_images, target_images):

        # 对抗损失

        adversarial_loss = torch.mean(1 - out_labels)

        # 感知损失

        perception_loss = self.mse_loss(self.loss_network(out_images), self.loss_network(target_images))

        # 图像MSE损失

        image_loss = self.mse_loss(out_images, target_images)

        # TV平滑损失

        tv_loss = self.tv_loss(out_images)

        return image_loss + 0.001 * adversarial_loss + 0.006 * perception_loss + 2e-8 * tv_loss

## TV平滑损失

class TVLoss(nn.Module):

    def __init__(self, tv_loss_weight=1):

        super(TVLoss, self).__init__()

        self.tv_loss_weight = tv_loss_weight

    def forward(self, x):

        batch_size = x.size()[0]

        h_x = x.size()[2]

        w_x = x.size()[3]

        count_h = self.tensor_size(x[:, :, 1:, :])

        count_w = self.tensor_size(x[:, :, :, 1:])

        h_tv = torch.pow((x[:, :, 1:, :] - x[:, :, :h_x - 1, :]), 2).sum()

        w_tv = torch.pow((x[:, :, :, 1:] - x[:, :, :, :w_x - 1]), 2).sum()

        return self.tv_loss_weight * 2 * (h_tv / count_h + w_tv / count_w) / batch_size

    @staticmethod

    def tensor_size(t):

        return t.size()[1] * t.size()[2] * t.size()[3]

上述代码中定义了对抗网络损失,逐像素的图像MSE损失,基于VGG模型的感知损失,用于约束图像平滑的TV平滑损失。

至此就完成了工程中核心代码的解读。

4 模型训练与测试

接下来我们对模型进行训练和测试。

4.1 模型训练

模型训练就是完成模型定义,数据载入,可视化以及存储等工作,核心代码如下:

## 参数解释器

parser = argparse.ArgumentParser(description='Train Super Resolution Models')

## 裁剪尺寸,即训练尺度

parser.add_argument('--crop_size', default=240, type=int, help='training images crop size')

## 超分上采样倍率

parser.add_argument('--upscale_factor', default=4, type=int, choices=[2, 4, 8],

                    help='super resolution upscale factor')

##训练主代码

if __name__ == '__main__':

    opt = parser.parse_args()

    CROP_SIZE = opt.crop_size

    UPSCALE_FACTOR = opt.upscale_factor

    NUM_EPOCHS = opt.num_epochs

    ## 获取训练集/验证集

    train_set = TrainDatasetFromFolder('data/train', crop_size=CROP_SIZE, upscale_factor=UPSCALE_FACTOR)

    val_set = ValDatasetFromFolder('data/val', upscale_factor=UPSCALE_FACTOR)

    train_loader = DataLoader(dataset=train_set, num_workers=4, batch_size=64, shuffle=True)

    val_loader = DataLoader(dataset=val_set, num_workers=4, batch_size=1, shuffle=False)

    netG = Generator(UPSCALE_FACTOR) ##生成器定义

    netD = Discriminator() ##判别器定义

    generator_criterion = GeneratorLoss() ##生成器优化目标

    ## 是否使用GPU

    if torch.cuda.is_available():

        netG.cuda()

        netD.cuda()

        generator_criterion.cuda()

    ##生成器和判别器优化器

    optimizerG = optim.Adam(netG.parameters())

    optimizerD = optim.Adam(netD.parameters())

    ## epoch迭代

    for epoch in range(1, NUM_EPOCHS + 1):

        train_bar = tqdm(train_loader)

        running_results = {'batch_sizes': 0, 'd_loss': 0, 'g_loss': 0, 'd_score': 0, 'g_score': 0} ##结果变量

        netG.train() ##生成器训练

        netD.train() ##判别器训练

        ## 每一个epoch的数据迭代

        for data, target in train_bar:

            g_update_first = True

            batch_size = data.size(0)

            running_results['batch_sizes'] += batch_size

            ## 优化判别器,最大化D(x)-1-D(G(z))

            real_img = Variable(target)

            if torch.cuda.is_available():

                real_img = real_img.cuda()

            z = Variable(data)

            if torch.cuda.is_available():

                z = z.cuda()

            fake_img = netG(z) ##获取生成结果

            netD.zero_grad()

            real_out = netD(real_img).mean()

            fake_out = netD(fake_img).mean()

            d_loss = 1 - real_out + fake_out

            d_loss.backward(retain_graph=True)

            optimizerD.step() ##优化判别器

            ## 优化生成器 最小化1-D(G(z)) + Perception Loss + Image Loss + TV Loss

            netG.zero_grad()

            g_loss = generator_criterion(fake_out, fake_img, real_img)

            g_loss.backward()

            fake_img = netG(z)

            fake_out = netD(fake_img).mean()

            optimizerG.step()

以上就是训练中的代码,训练时采用的crop_size为240×240,训练时我们将所有图缩放为320×320,使用的优化器为Adam,添加了变量缓存的完整代码请看下文的完整工程项目。

图中jpeg0对应的曲线表示不添加JPEG压缩噪声,jpeg0-50,jpeg30-70对应的曲线分别表示添加0~50%幅度的压缩噪声,添加30~70%幅度的压缩噪声的训练结果。可以看出,模型已经基本收敛,添加噪声幅度越大,则最终的PSNR指标和SSIM指标也会越低。

b0441565d917b081f3446c2a4ea364d9.png

下图从左至右分别是有噪声原图,无噪声原图,去噪声图。

b9f7e029f3f75db822fdf098d89bb0c1.jpeg

4.2 模型推理

实际用的时候,我们希望使用自己的图片来完成推理,完整的代码如下:

import torch

from PIL import Image

from torch.autograd import Variable

from torchvision.transforms import ToTensor, ToPILImage

from model import Generator

UPSCALE_FACTOR = 4 ##上采样倍率

TEST_MODE = True ## 使用GPU进行测试

IMAGE_NAME = sys.argv[1] ##图像路径

RESULT_NAME = sys.argv[1] ##结果图路径

MODEL_NAME = 'netG.pth' ##模型路径

model = Generator(UPSCALE_FACTOR).eval() ##设置验证模式

if TEST_MODE:

    model.cuda()

    model.load_state_dict(torch.load(MODEL_NAME))

else:

    model.load_state_dict(torch.load(MODEL_NAME, map_location=lambda storage, loc: storage))

image = Image.open(IMAGE_NAME) ##读取图片

image = Variable(ToTensor()(image), volatile=True).unsqueeze(0) ##图像预处理

if TEST_MODE:

    image = image.cuda()

out = model(image)

out_img = ToPILImage()(out[0].data.cpu())

out_img.save(RESULT_NAME)

下图展示了一张真人图的超分辨结果,输入图是从512×512的大小缩放为128×128大小,然后分别使用opencv的imwrite函数存储为JPEG和PNG格式,前者使用opencv库默认的JPEG压缩率。

6ff77a63f6fc3c9658fc4653a6fd348c.png

真人图像的SRGAN超分结果

图中第1列为原图,其中两行分别是JPEG格式和PNG格式,显示时使用双线性插值进行上采样。第2列为不添加JPEG噪声数据增强进行训练后的4倍超分结果,第3列为添加0~50%随机幅度的JPEG噪声数据增强进行训练后的超分结果,第4列为添加30~70%随机幅度的JPEG噪声数据增强进行训练后的超分结果。

比较第1行和第2行,可以看出,对于JPEG压缩的图像,如果没有添加噪声数据增强,则结果图会放大原图中的噪声,其中第2列结果非常明显。不过,噪声的幅度也不能过大,否则重建结果会失真,比较第4列结果和第3列结果,虽然第4列有更强的噪声抑制能力,但是人脸图已经开始出现失真,如皮肤过于平滑,眼睛失真明显,因此不能一味得增加噪声幅度。

虽然我们的训练数据集是真人图,但是模型也可以泛化到其他域的人脸图像。

本文参考的文献如下:

‍

[1] Ledig C, Theis L, Huszár F, et al. Photo-realistic single image super-resolution using a generative adversarial networ k[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2017: 4681-4690.

本文视频讲解和代码,请大家移步:

【项目实战课】基于Pytorch的SRGAN图像超分辨实战

b95069b31e0488278ccb9c87e617b838.gif

1fea70699061fc962a6ed4b14dd66454.jpeg

总结

本次我们使用SRGAN完成了图像超分辨率任务,SRGAN是最经典的基于GAN的图像超分辨率框架,值得所有从事GAN相关领域工作的朋友掌握,欢迎大家以后持续关注《百战GAN专栏》。

如何系统性地学习生成对抗网络GAN

欢迎大家关注有三AI-CV秋季划GAN小组,可以系统性学习GAN相关的内容,包括GAN的基础理论,《深度学习之图像生成GAN:理论与实践篇》,《深度学习之图像翻译GAN:理论与实践篇》以及各类GAN任务的实战。

介绍如下:【CV秋季划】生成对抗网络GAN有哪些研究和应用,如何循序渐进地学习好(2022年言有三一对一辅导)?

2e42f657a581a01f57b84b1b5dd913bf.png

转载文章请后台联系

侵权必究

e7a2ceee09739aa8e022590f81c3ee0b.gif

a407cdab4153a65a6d74c984782b0965.png

7836fff07a38eccf1e089be3e4a0956d.png

SRGAN——使用与超分辨率重建的GAN   SRGAN数据GAN理论在超分辨率重建(SR)方面的应用。 一、超分辨率技术 1.SR技术介绍   SR技术,是指从观测到的低分辨率图像重建出相对应的高分辨率图像,在监控设备、卫星图像和医学影像等领域都有重要的应用价值,也可以应用于马赛克图片的恢复应用场景。   SR可分为两类:从多张低分辨率图像重建出高分辨率图像;从单张低分辨率图像重建出高分辨率图像。基于深度学习的SR,主要是基于单张低分辨率的重建方法,即Single Image Super-Resolution(SISR)。   SISR是一个逆问 阅读详情

相关推荐

SRGAN的原理解析&实现

主要是对[https://github.com/sgrvinod/a-PyTorch-Tutorial-to-Super-Resolution?tab=readme-ov-file]大佬的教程的理解及其翻译,添加了很多自己的东西,个人认为更新手友好一点。

mrpig13的博客 4903

深度学习计划(4)SRGan简析

SRGAN 一种用于图像超分辨率(SR)的生成对抗网络(GAN) 超分辨率:从低分辨率(LR)图像来估计其对应高分辨率(HR)图像的高挑战性任务被称作超分辨率(SR) 问题: 重建的SR图像中通常缺少纹理细节。有监督SR算法的优化目标通常是最小化恢复的HR图像和真实图像之间的均方差(MSE)。最小化MSE即最大化峰值信噪比(PSNR)是方便的,这是用来评估和比较SR算法的常用方法。 补充: PSNR是最普遍和使用最为广泛的一种图像客观评价指标,然而它是基于对应像素点间的误差,即基于误差敏感的

weixin_42625806的博客 5905

文献阅读笔记--深度学习图像修复方法综述

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mar

weixin_44023830的博客 3008

深度学习之超分辨率算法——SRGAN

更新版本 实现了生成对抗网络在超分辨率上的使用 更新了损失函数,增加先验函数 SRresnet实现 import torch import torchvision from torch import nn class ConvBlock(nn.Module): def __init__(self, kernel_size=3, stride=1, n_inchannels=64): super(ConvBlock, self).__init__() self.sequ..

swpucwf的博客 3275

图像修复方法研究综述----论文笔记

图像修复方法研究综述对象移除修复图像图片修饰文字移除“根 据修复思想的不同,它可以被分为基于偏微分方程 (Partial Differential Equation,PDE)的图像修复方法 和基于样本的图像修复方法。”(1)基于偏微分方程的方法“利用数学或物理学中的偏微分方 程,将图像已知区域像素平滑传播到缺失区域中以 修复破损图像。” (2)基于样本的图像修复方法“基于样本的图像修复方法通过计算并搜索破 损图像缺失区域与已知区域相似度最高的样本,并 将其复制粘贴到缺失区域内以修复破损图像。” “依据生成

番茄炒蛋三分糖 4080

SRGAN图像超分重建算法Python实现(含数据集代码)

本文介绍深度学习的SRGAN图像超分重建算法,使用Python以及Pytorch框架实现,包含完整训练、测试代码,以及训练数据集文件。博文介绍图像超分算法的原理,包括生成对抗网络和SRGAN模型原理和实现的代码,同时结合具体内容进行解释说明,完整代码资源文件请转至文末的下载链接。

思绪无限的博客 1万+

【总结】从视频到图文,代码实战,有三AI-GAN学习资料汇总!

GAN无疑是这几年深度学习领域里最酷的技术,不管是理论的研究,还是GAN在图像生成,图像翻译,语音图像等基础领域的应用,都非常的丰富。我们公众号输出过非常多的GAN相关资源,本次做一个简单...

hacker_long的专栏 934

超分辨率重建SRGAN代码(包括将SRGAN生成器单独拿出来做残差网络)

超分辨率重建SRGAN代码(包括将SRGAN生成器单独拿出来做残差网络)

【总结】有三AI所有原创GAN相关的学习资料汇总(2022年12月)

GAN的研究和应用在这几年发展可以说是非常迅猛,无疑是这几年深度学习计算机视觉领域里落地性最酷的技术之一,包括图像与视频生成,数据仿真与增强,各种各样的图像风格化任务,人脸与人体图像编辑,图像质量提升等。GAN最早期也是最经典的任务,就是高质量图像生成,当前已经可以生成1024分辨率以上的高清逼真图像,如下图生成了一些假明星脸。图像翻译与风格化则是另外一个应用极其广泛的领域,因为从图像到图像的任务...

hacker_long的专栏 1040

AOT-GAN-for-Inpainting:用于高分辨率图像修补的AOT-GAN(图像修补的代码库)

AOT-GAN用于高分辨率图像修复 | AOT-GAN:用于高分辨率图像修复的聚合上下文转换,,,。 引文 如果我们的论文和代码中的任何部分对您的工作有所帮助,请慷慨地引用我们并加注星标 :face_blowing_a_kiss: :face_blowing_a_kiss: :face_blowing_a_kiss: ! @inproceedings{yan2021agg, author = {Zeng, Yanhong and Fu, Jianlong and Chao, Hongyang and Guo, Baining}, title = {Aggregated Contextual Transformations for High-Resolution Image Inpainting}, booktitle = {Arxiv}, pages={-}, year = {2020} } 介绍 尽管取得了一些令人鼓舞的结果,但是对于现有的图像修复方法来填充高分辨率图像(例如5

Windows下Anaconda换清华镜像源最全指南(含常见问题解决)

本文提供了一份详尽的Windows系统下Anaconda配置清华镜像源的完整指南。针对网络下载缓慢的痛点,文章详细对比了命令行添加与直接编辑配置文件两种主流方法,并重点解决了配置过程中常见的文件缺失、安装失败、环境求解缓慢等疑难问题,帮助用户一劳永逸地提升包管理效率。

brandy的博客 337

【杂谈】GAN最成功的3个商业化落地领域,你是否了解过?

2015年的时候笔者开始关注GAN,公众号早期的文章中就有GAN的综述,这些年GAN的相关研究也是持续井喷。这一次咱们学术上的研究撇开不讲,这么多年过去了,GAN有哪些最成功的商业化落地领域? 图像生成与编辑领域 GAN的诞生之初,就是做数据生成,如今在一些领域可以说是非常的成熟了,其中尤其是StyleGAN为代表的高清人脸生成领域。 StyleGAN结合独创的mapping network和在图像风格化领域中通用的AdaIN技术,将人脸特征进行了分层表达,其生成结果已经达到了普通用户难以辨认的水

喜欢打酱油的老鸟 740

避开ego_planner仿真的第一个坑:深度相机、点云与odom话题配置全指南

本文详细解析了ego_planner仿真中深度相机、点云与odom话题配置的关键问题,帮助开发者避开常见陷阱。从数据流架构到具体配置细节,包括深度相机的内外参匹配、点云数据规范要求以及odom话题的验证方法,提供了全面的实战指南和优化建议。

weixin_30335575的博客 493

【总结】超100期经典GAN模型的解读,从结构设计到应用,你不动心吗?

GAN无疑是这几年深度学习领域里最酷的技术,不管是理论的研究,还是GAN在图像生成,图像翻译,语音图像等基础领域的应用,都非常的丰富。我们公众号输出过非常多的GAN相关资源,本次做一个简单...

hacker_long的专栏 1959

NX二次开发(python)-坯料尺寸(一)

一般在产品制造过程中,往往要判断一个模型在出模方向上的最小包容盒尺寸,在NX中可以用坯料尺寸命令实现,当然也有相应的代码实现,这或许可以帮助我们实现一些产品的坯料尺寸批量输出,节省人力。

dasfanfan的博客 823

高速电路的信号完整性分析

摘要:介绍了高速PCB设计中的信号完整性概念以及破坏信号完整性的原因,从理论和计算的层面上分析了高速电路设计中反射和串扰的形成原因,并介绍了IBIS仿真。 关键词:信号完整性 反射 串扰 IBIS仿真 随着半导体技术和深压微米工艺的不断发展,IC的开关速度目前已经从几十MHz增加到几百MHz,甚至达到几GHz。在高速PCB设计中,工程师经常会碰到误触发、阻尼振荡、过冲、欠冲、串...

bh_wang的专栏 1432

人脸修复祛马赛克算法CodeFormer——C++与Python模型部署

CodeFormer是一种基于AI技术深度学习的人脸复原模型,有人脸超分,人脸祛除马赛克,人脸修复,人脸上色C++和python部署。

知来者逆的博客 1万+

人形机器人开源资源大盘点(四):硬件开源平台

开源人形机器人平台推动技术民主化 本期聚焦四大开源人形机器人平台:斯坦福的ToddlerBot以6000美元低成本实现30自由度运动,支持仿真到现实的零样本迁移;法国Reachy2被HuggingFace收购,融合开源AI与硬件,适配医疗、工业等场景;国内OriginMan基于ROS2全开源,集成大模型能力,支持深度改造;OAN框架则为经典NAO机器人注入开源活力,扩展交互功能。这些平台通过不同路径降低研发门槛,推动人形机器人技术走向开放共享的未来。

Studying…… 370

python 学习笔记18 GFPGAN人脸(图片)修复

老实说这个和学习没啥关系,就是一个python解决方案的实践。 觉得有趣就试了一下,先上链接: 官方:https://github.com/TencentARC/GFPGAN/blob/master/README.md 这是个高分项目,用于人脸(在逐渐拓展到其他图像类别,如背景)图像修复。如下图: 腾讯 AI 的研究人员提出了他们的新GFP-GAN 模型,以在一次前向传递中实现真实性和保真度的良好平衡。该模型由退化去除模块和预先训练的人脸生成器组成。它们通过直接潜在代码映射连接到使用 CS SFT

wzhang1987的博客 9172

【网络安全】Python代码审计高危函数与安全审计建议

Python 灵活且动态的特性使得开发便捷,但同时也带来了严重安全隐患。如果开发者缺乏安全意识,极易引入命令执行、反序列化漏洞及模板注入漏洞。本文总结了 Python 中常见的高危函数、模块和第三方库,并给出对应的审计建议及其原理解析,供安全研究人员和开发者参考。

等风来 418

北斗导航 | 基于LSTM-KF融合的北斗卫星定位算法研究框架

针对北斗卫星导航系统在复杂环境下存在的多路径效应、非视距传播等问题,提出一种基于长短期记忆网络(LSTM)与卡尔曼滤波(KF)的组合定位算法。通过LSTM网络建模定位误差的非线性特征,结合卡尔曼滤波实现动态噪声抑制,构建"粗定位-LSTM校正-卡尔曼滤波优化"的三级处理架构。实验表明,融合算法较传统方法定位精度提升42.7%,均方根误差降低至1.2米。

尘世冰封的专栏 923

【超分辨率】【深度学习】SRGAN pytorch代码(附详细注释和数据集链接)

SRGAN主要改进: 1. 断点恢复(参考train.py的75行) 2. 注释部分代码(提高训练速度,参考train.py的182行) 3. VGG计算特征损失部分(参考Loss.py的注解)

zhanjuex的博客 8916

AI编程工具深度对比:Cursor、Copilot、Trae与Claude Code,2025年开发者该如何选择?

2025年AI编程工具市场已形成四大主力阵营:Cursor(AI原生IDE)、GitHub Copilot(行业标准)、Trae(中国免费方案)和Claude Code(终端交互)。核心差异体现在技术能力(代码生成准确率85%-95%)、智能体协作程度和上下文处理能力(8K-200K tokens)。用户体验方面,Trae对中文支持最佳且免费,Copilot企业集成强,Cursor平衡易用与功能,Claude Code适合高阶开发者。实际测试显示,不同工具在原型开发、算法实现等场景各有优势

fudaihb的博客 6500

图像修复:使用pytorch实现context encoders

图像修复:使用pytorch实现context encoders

A_Pathfinder的博客 4620

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

基于深度学习的图像超分辨重建算法的实现

一张低分辨率的图像要想放大为更高尺寸的图像,需要对确实的细节进行插值,常见的线性插值方法利用相邻像素的信息进行补充,但放大后图像模糊、质量低下的问题仍然存在。图像的超分辨率重建技术指的是将给定的低分辨率图像通过特定的算法恢复成相应的高分辨率图像。简单来理解超分辨率重建就是将小尺寸图像变为大尺寸图像,使图像更加“清晰”,但放大时通过了深度学习的技术补充了更多细节。

1万+

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

上一篇: 【百战GAN】适合所有人的第一个GAN项目:DCGAN图像生成代码实战
下一篇: 【百战GAN】定制属于二次元宅们的专属动漫头像,这款GAN正好!
言有三
言有三 领域专家: 人工智能技术领域 领域专家: 人工智能技术领域
博客等级 码龄15年 3635粉丝 976原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

言有三

三人行必有AI

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

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

打赏作者

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

抵扣说明:

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

余额充值