欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > 图像生成-ICCV2019-SinGAN: Learning a Generative Model from a Single Natural Image

图像生成-ICCV2019-SinGAN: Learning a Generative Model from a Single Natural Image

2025/3/9 14:37:50 来源:https://blog.csdn.net/sgr011215/article/details/146021225  浏览:    关键词:图像生成-ICCV2019-SinGAN: Learning a Generative Model from a Single Natural Image

图像生成-ICCV2019-SinGAN: Learning a Generative Model from a Single Natural Image

文章目录

      • 图像生成-ICCV2019-SinGAN: Learning a Generative Model from a Single Natural Image
        • 主要创新点
        • 模型架构图
        • 生成器
          • 生成器源码
        • 判别器
          • 判别器源码
        • 损失函数
        • 需要源码讲解的私信我

SinGAN 通过多尺度全卷积 GAN 金字塔结构,从单张自然图像中学习内部 patch 分布,无需条件输入即可生成多样化、高质量的新图像,并适用于广泛的图像处理任务。

论文链接:SinGAN: Learning a Generative Model from a Single Natural Image

源码链接:/tamarott/SinGAN

主要创新点
  1. 单图像内部统计学习:SinGAN 通过多尺度 patch-GAN 层次结构,从单张图像中学习其内部统计信息,而不是依赖于整个数据库中的图像样本
  2. 多尺度结构捕获图像特征:每个 patch-GAN 负责捕获图像在不同尺度下的 patch 分布,能够同时学习全局结构(如大物体的排列)和细节纹理信息。
  3. 突破传统纹理生成:与传统的纹理生成方法不同,SinGAN 不仅局限于生成纹理图像,而是处理更复杂的自然图像结构,能够生成具有全局一致性和细节多样性的高质量图像。
  4. 多尺度生成器金字塔: SinGAN 使用多尺度生成器金字塔 {G0, ..., GN},每个生成器在不同尺度上生成与对应下采样版本图像相符的真实图像样本,通过对抗训练实现生成器和判别器的博弈。生成过程从粗糙尺度开始,逐步通过各生成器添加细节,并通过上采样前一尺度的生成图像细化全局结构,同时确保噪声在每个尺度上得到充分利用。
模型架构图

主要由一下几部分组成:

  1. 生成器:对于生成器是由下往上训练的,生成器采用五个全卷积层来实现,对于不同层次生成器接收到的东西也随着层数递增也不一样的,不同层次输入的图像大小也不一样,其实就是和StyleGan的原理是一样的,对应于StyleGan的潜在向量空间latent。
  2. 判别器:判别器和生成器一样的, 根据尺度不一样而一一对应,判别器就是要把生成器生成的判别为假,真的判别为真
  3. 多层次噪声优化 : 对于生成器会随机初始化一个噪声输入到生成器的中,噪声对于图像的影响也会很大,通常的做法是统计整个数据集的一些特征来对噪声进行初始化,本文中是对于下一层次生成的图像和噪声来拼接生成,来补充噪声的信息。

在这里插入图片描述

生成器

多尺度生成器金字塔:模型包含一个由生成器组成的金字塔 {G0, …, GN},每个生成器 Gn 对应于图像的一个尺度 xn,其中 xn 是通过因子 rn 对原始图像 x 进行下采样得到的。生成器 Gn 的任务是生成与图像 xn 中的 patch 分布相符的真实图像样本。

生成过程:图像生成从最粗的尺度(GN)开始,并通过每个生成器逐步到达最精细的尺度。在每个尺度上,生成器 Gn 通过与对应尺度的判别器 Dn 进行对抗训练,学习生成与训练图像 xn 中的 patch 区分不出的样本。

细节添加:在生成过程中,每个生成器不仅生成新的细节,还将前一个尺度的生成图像 ̃xn+1 上采样到当前尺度后,与当前的噪声 zn 一起输入到卷积层中。这个操作确保了每个尺度上的细节添加和图像的结构细化。

噪声和图像合成:每个生成器的输入包括随机噪声 zn 和上采样后的前一尺度图像 ̃xn+1。生成器通过卷积层进行残差学习,生成缺失的细节,最终得到当前尺度的图像输出 ̃xn。

自适应生成大小:由于生成器是全卷积的,它们能够在测试时生成任意大小和纵横比的图像,只需调整噪声图的维度。

在这里插入图片描述

生成器源码
class GeneratorConcatSkip2CleanAdd(nn.Module):def __init__(self, opt):super(GeneratorConcatSkip2CleanAdd, self).__init__()self.is_cuda = torch.cuda.is_available()  # 判断是否有 GPUN = opt.nfc  # 初始化卷积层输出通道数# 定义头部卷积层,处理输入图像self.head = ConvBlock(opt.nc_im, N, opt.ker_size, opt.padd_size, 1)  self.body = nn.Sequential()  # 存储中间卷积层# 构建中间层for i in range(opt.num_layer - 2):N = int(opt.nfc / pow(2, (i + 1)))  # 每层输出通道数逐步减少block = ConvBlock(max(2 * N, opt.min_nfc), max(N, opt.min_nfc), opt.ker_size, opt.padd_size, 1)self.body.add_module('block%d' % (i + 1), block)  # 添加到 body 中# 定义尾部卷积层,用于输出最终图像self.tail = nn.Sequential(nn.Conv2d(max(N, opt.min_nfc), opt.nc_im, kernel_size=opt.ker_size, stride=1, padding=opt.padd_size),nn.Tanh()  # 使用 Tanh 激活函数输出图像)def forward(self, x, y):# 经过头部卷积层处理输入 xx = self.head(x)# 通过中间卷积层x = self.body(x)# 通过尾部卷积层生成图像x = self.tail(x)# 根据 y 和 x 的尺寸差值进行裁剪,确保两者尺寸相同ind = int((y.shape[2] - x.shape[2]) / 2)y = y[:, :, ind:(y.shape[2] - ind), ind:(y.shape[3] - ind)]# 将生成的图像与输入 y 相加return x + y
判别器

判别器与生成器的关系

  • 每个生成器 Gn 都配有一个对应的判别器 Dn,目的是通过对比生成图像与真实图像之间的差异,指导生成器改进生成的图像。
  • 判别器 Dn 的目标是判别每个输入图像块是“真实”图像块(来自原始图像 xn)还是“伪造”图像块(由生成器生成的图像块)。
  • 损失函数
    • 判别器使用 WGAN-GP 损失(Wasserstein GAN with Gradient Penalty)来训练,以确保训练过程的稳定性。通过计算生成样本和真实图像样本在各自图像块上的判别结果,最终得出一个平均的判别分数。
    • 判别器的损失不仅针对单个图像块,还针对整个图像进行定义,这有助于学习整个图像的结构,特别是边界条件,而不仅仅是关注图像的局部区域。
判别器源码
class WDiscriminator(nn.Module):def __init__(self, opt):super(WDiscriminator, self).__init__()self.is_cuda = torch.cuda.is_available()  # 检查是否有可用的GPUN = int(opt.nfc)  # 初始通道数self.head = ConvBlock(opt.nc_im, N, opt.ker_size, opt.padd_size, 1)  # 第一层卷积块self.body = nn.Sequential()  # 中间层,包含多个卷积块for i in range(opt.num_layer - 2):  # 添加多层卷积块,num_layer指定总层数N = int(opt.nfc / pow(2, (i + 1)))  # 根据层数逐渐减少通道数block = ConvBlock(max(2 * N, opt.min_nfc), max(N, opt.min_nfc), opt.ker_size, opt.padd_size, 1)  # 创建每一层卷积块self.body.add_module('block%d' % (i + 1), block)  # 添加每一层卷积块到序列self.tail = nn.Conv2d(max(N, opt.min_nfc), 1, kernel_size=opt.ker_size, stride=1, padding=opt.padd_size)  # 输出层,1个输出通道def forward(self, x):x = self.head(x)  # 通过第一层卷积块x = self.body(x)  # 通过中间层的多个卷积块x = self.tail(x)  # 通过输出层return x  # 返回最终的输出
损失函数

在这里插入图片描述

在这里插入图片描述

需要源码讲解的私信我

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词