【毕业论文】| 基于生成对抗网络的图像风格动漫化迁移

📢写在前面

【简要介绍】新人第一篇分享!!本人是2024届(今年)毕业的江苏某中下211本科计算机科学与技术专业的一名女生,今年2024年9月打算前往香港城市大学留学,攻读数据科学硕士学位。
【分享目的】在今年的毕业论文环节,自己的毕业论文最终获得了校优秀论文,并且这篇论文也是自己很用心选题,完全自己独立完成。借此机会,想同csdn的大家一同分享下我的论文同时也相当于是对我毕业论文的一次复盘总结。
如果你也对图像风格动漫迁移,深度学习,生成对抗网络,制作一款图像/视频动漫化迁移系统感兴趣,那么就继续看下去吧~
在这里插入图片描述
在这里插入图片描述

摘 要

本文首先调研了近些年最为流行的基于生成对抗网络的图像风格迁移模型,选择了目前最合适的AnimeGANv2模型作为基线模型,在多种风格、内容数据集下进行了重新训练,深度研究了其网络架构。但生成的图像仍不是很理想,图像颜色损失较严重。因此,本文在AnimeGANv2模型的基线网络上进行了改良,在生成器网络中引入了CBAM注意力机制,同时在判别器网络里引入了自注意力机制。另外,本文还在生成器的总损失函数中加入了循环一致性损失函数以及新增了两种动漫风格数据集。在重新训练数据集后,得到了比原模型更好的风格迁移效果,图像的颜色效果得到了改善,图像的核心部分也得到重点关注。为了更好的可视化展示,本文还设计了一款图像动漫化迁移系统,界面基于PyQt5框架设计,界面美观,方便了用户操作,还另外加入了视频动漫化风格迁移功能。

关键词:图像风格迁移;生成对抗网络;AnimeGANv2;注意力机制;PyQt5

基线模型:基于 AnimeGANv2 图像动漫化风格迁移模型

【主要参考】:AnimeGANv2
AnimeGAN是由武汉大学和湖北工业大学的研究团队一起研究的图像风格迁移模型,旨在将现实生活中的图像转换为动漫风格的艺术作品,结合了神经风格转换和生成对抗网络(GAN)来完成该项任务。该网络新提出了几种,使生成的动漫化图像拥有更好的质量,分别是灰度风格损失函数、对抗损失函数和颜色重建损失函数,AnimeGAN训练过程中的网络相比于其他的生成对抗网络拥有更低的内存占用情况。而在训练数据集的选取方面,与其他的生成对抗网络不同,这里采用的是没有映射关系的未配对数据集。最终实验分析显示,AnimeGAN通过其特殊的网络设置,能够很好地从图像中捕获其深层特征,而深层特征中捕获的图像中隐藏的难以探寻的复杂信息帮助该网络最后在测试集上生成的图像取得了很好的风格外在特征和保存了原始的内在内容特征。

尽管AnimeGAN已经取得了很好的效果,但对比其生成的图像效果,从色彩和原图的还原度方面来看,效果还远远不够,进而在此模型基础上又改进并提出了一种新型网络,AnimeGANv2。AnimeGANv2在网络上做出了相关改进,在判别器网络中的归一化层由层归一化转换为了实例归一化。此外,还进一步缩小了生成器网络的参数规模,以实现更高效的动画风格转换。AnimeGANv2同大部分的生成对抗网络结构相似,主要由两个网络组成,即生成器网络G和判别器网络D,生成器网络接受真实图像输入经由网络提取其主要内在特征生成一张虚拟的生成图像,判别器网络接受动漫图像和灰度动漫图像作为输入,不断与生成图像进行分析比较更换相应损失函数的数值。具体的网络处理流程见下图。
在这里插入图片描述

网络架构

AnimeGANv2主要由三个卷积神经网络组成,这三个主要部分包括VGG19特征提取网络、生成器网络、判别器网络。VGG19特征提取网络主要用途是作为感知网络提取输入图像的主要高级语义特征。生成器网络主要用途是根据真实的场景、人像图片生成一个图片。判别器网络主要用途是判别生成器生成的图片是否与目标动漫场景、人像图相一致。

1 生成器网络

该生成器网络类似于一个图像翻译任务中的U-Net架构,该架构主要的流程类似一个编码和解码系统,首先对输入图像进行特征提取类似一个编码器,将图像看作一个个编码,按照一定顺序对提取的特征进行编排,随后将提取的特征映射到原始图像空间,类似一个解码器,对编码好的特征重新还原,总体类似构成一个编码-解码系统,能够实现端到端的图像生成。总体生成器网络主要由Conv2D二维卷积层、自定义卷积层、深度可分离卷积层、上采样模块、倒残差块、下采样模块、反卷积层等模块构成。
在这里插入图片描述

def __init__(self, inputs):

        with tf.variable_scope('G_MODEL'):

            with tf.variable_scope('A'):
                inputs = Conv2DNormLReLU(inputs, 32, 7)
                inputs = Conv2DNormLReLU(inputs, 64, strides=2)
                inputs = Conv2DNormLReLU(inputs, 64)

            with tf.variable_scope('B'):
                inputs = Conv2DNormLReLU(inputs, 128, strides=2)
                inputs = Conv2DNormLReLU(inputs, 128)

            with tf.variable_scope('C'):
                inputs = Conv2DNormLReLU(inputs, 128)
                inputs = self.InvertedRes_block(inputs, 2, 256, 1, 'r1')
                inputs = self.InvertedRes_block(inputs, 2, 256, 1, 'r2')
                inputs = self.InvertedRes_block(inputs, 2, 256, 1, 'r3')
                inputs = self.InvertedRes_block(inputs, 2, 256, 1, 'r4')
                inputs = Conv2DNormLReLU(inputs, 128)
                # 添加CBAM
                #inputs = self.add_cbam(inputs)


            with tf.variable_scope('D'):
                inputs = Unsample(inputs, 128)
                inputs = Conv2DNormLReLU(inputs, 128)

            with tf.variable_scope('E'):
                inputs = Unsample(inputs,64)
                inputs = Conv2DNormLReLU(inputs, 64)
                inputs = Conv2DNormLReLU(inputs, 32, 7)
            with tf.variable_scope('out_layer'):
                out = Conv2D(inputs, filters =3, kernel_size=1, strides=1)
                self.fake = tf.tanh(out)
2 判别器网络

判别器网络主要用于对输入图像进行真实或虚假的二分类,构建一个简单的卷积神经网络进行。该网络中有两个卷积块,每个卷积块有两个卷积层,在卷积操作中也使用了层归一化以及在判别器的主要网络模型中引用了激活函数Leaky ReLU。
在这里插入图片描述

def D_net(x_init,ch, n_dis,sn, scope, reuse):
    channel = ch // 2
    with tf.variable_scope(scope, reuse=reuse):
        x = conv(x_init, channel, kernel=3, stride=1, pad=1, use_bias=False, sn=sn, scope='conv_0')
        x = lrelu(x, 0.2)
        ####判别器的层数n_dis=3,这里会循环1到2层共两层
        for i in range(1, n_dis):
            x = conv(x, channel * 2, kernel=3, stride=2, pad=1, use_bias=False, sn=sn, scope='conv_s2_' + str(i))
            x = lrelu(x, 0.2)

            x = conv(x, channel * 4, kernel=3, stride=1, pad=1, use_bias=False, sn=sn, scope='conv_s1_' + str(i))
            x = layer_norm(x, scope='1_norm_' + str(i))
            x = lrelu(x, 0.2)

            channel = channel * 2

        x = conv(x, channel * 2, kernel=3, stride=1, pad=1, use_bias=False, sn=sn, scope='last_conv')
        x = layer_norm(x, scope='2_ins_norm')
        x = lrelu(x, 0.2)

        x = conv(x, channels=1, kernel=3, stride=1, pad=1, use_bias=False, sn=sn, scope='D_logit')

        return x
3 损失函数

AnimeGANv2网络的总损失函数由对抗损失函数、真实图像内容损失函数、动漫图像灰度风格损失函数、真实图像颜色损失函数这四个损失函数构成,总损失函数公式:
在这里插入图片描述

基线模型实验

实验配置

在本文的实验中,选择租用恒源云服务器来训练本文的深度学习项目,所租用的显卡为32G显存的V100显卡,实验项目代码是在python3.8的环境下使用TensorFlow1.15.0的深度学习框架下进行搭建的,而其中TensorFlow的配置是cuda 10.0.130,cudnn 7.6.0,系统盘20G,数据盘占50G。
注:这里跑训练租用了恒源云服务器,具体使用方法有需要后期介绍!!!
在这里插入图片描述
在这里插入图片描述

数据集介绍

在这里插入图片描述
在这里插入图片描述

基线模型实验结果
1 定量分析

定性评价主要关注于描述和理解被评估对象的特征、行为和性能,而不涉及具体的数
值或量化指标,一般包括主观判断、用户体验等等。

在这里插入图片描述
在这里插入图片描述

2 定性分析

定量评价通过数值化的指标来量化被评估对象的性能、效果或质量,提供客观的、可
重复的结果。本次实验通过三个经典的GAN图像评价指标FID、LPIPS、MS-SSIM来对生成的模型进行客观评价。
在这里插入图片描述
综上,结合三种指标来看,基于AnimeGANv2的本实验训练100轮的情况的生成图像质
量是最好的。

(论文创新点)模型改进

1 数据集改进

原先的AnimeGANv2项目的数据集主要是新海诚、宫崎骏、今敏三者动漫风格场景数
据集和真实场景数据集,考虑到实验应用多是人像数据的风格迁移,所以本次实验中新增了冰雪奇缘和京阿尼动漫风格人像数据集与真实人像数据集。

新增的两种动漫风格人像数据集是本人自行制作,基本原理是获取一部mp4格式的动
漫电影,每12帧获取一张电影帧的截图,利用动漫人像检测模型对截图进行检测,将截图中检测到的人像裁剪并保存为新的图片,新图片的分辨率设置为256×256,最终制作完成冰雪奇缘和京阿尼动漫风格人像数据集。

最终动漫化风格迁移后结果图:
在这里插入图片描述

2 网络架构改进

基于 CBAM 的生成器网络改进

改进后生成器网络:

在这里插入图片描述

####加入CBAM注意力机制----------------------------------------------------   

    def add_cbam(self, inputs):
        # 添加CBAM注意力模块
        with tf.variable_scope('cbam'):
            channel = self.channel_attention(inputs)
            spatial = self.spatial_attention(channel)
            return spatial

    def channel_attention(self, inputs, ratio=8):
        # 通道注意力
        with tf.variable_scope('channel_attention'):
            channels = inputs.get_shape().as_list()[-1]
            avg_pool = tf.reduce_mean(inputs, axis=[1, 2], keepdims=True)
            max_pool = tf.reduce_max(inputs, axis=[1, 2], keepdims=True)
            combined = tf.concat([avg_pool, max_pool], axis=-1)
            fc1 = tf.layers.dense(combined, units=channels // ratio, activation=tf.nn.relu)
            fc2 = tf.layers.dense(fc1, units=channels, activation=tf.nn.sigmoid)
            attention = tf.multiply(inputs, fc2)
            return attention

    def spatial_attention(self, inputs):
        # 空间注意力
        with tf.variable_scope('spatial_attention'):
            avg_pool = tf.reduce_mean(inputs, axis=-1, keepdims=True)
            max_pool = tf.reduce_max(inputs, axis=-1, keepdims=True)
            combined = tf.concat([avg_pool, max_pool], axis=-1)
            attention = tf.layers.conv2d(combined, filters=1, kernel_size=7, strides=1, padding='same', activation=tf.nn.sigmoid)
            return tf.multiply(inputs, attention)

基于自注意力机制的判别器网络改进

在这里插入图片描述

3 损失函数改进

尽管原先的总体损失函数设计已经十分完成,但生成的图像风格迁移效果仍存在不足,经过多次实验发现,原模型训练生成的图像的颜色都会随着不同风格的动漫图片改变,例如总体色彩都会偏向于某种颜色或者背景色彩会偏蓝或者偏白,并不能完美地保存原真实图像的色彩特征。考虑到这些问题,本文对此损失函数进行了改进并新增了一种损失函数,循环一致损失函数,公式如下:
在这里插入图片描述
总损失如下:
在这里插入图片描述

模型改进后实验

因为新增了循环一致损失到G_vgg变量中,与上一章实验的原网络模型损失相比较,
损失略有增大,但生成器和判别器的总体损失同样也是在100epoch时上下波动范围不大,可认为收敛。
在这里插入图片描述
网络改进前后对比图:
在这里插入图片描述
网络改进前后指标对比:
在这里插入图片描述

图像风格动漫化迁移系统设计

图像动漫化迁移系统是用PyCharm开发环境进行开发,借助PyQt5库完成界面的交互设计,同时利用云服务器实现后端运行项目代码来加载模型以及利用Python语言作为开发语言完成生成图像等一系列功能的实现。
系统搭建若有需要,后面单独开一期详细介绍!!!
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

import paramiko
from main_web import Ui_MainWindow
import sys,os

def link_load(fileName):
    ui=Ui_MainWindow()
    # 创建一个ssh的客户端,用来连接服务器
    ssh = paramiko.SSHClient()
    # 创建一个ssh的白名单
    know_host = paramiko.AutoAddPolicy()
    # 加载创建的白名单
    ssh.set_missing_host_key_policy(know_host)

    # 连接服务器
    print('连接服务器……')
    ssh.connect(
        hostname="i-1.gpushare.com",
        port= 填端口号,
        username="root",
        password="填密码"
    )


    print('上传图片文件……')
    sftp = paramiko.SFTPClient.from_transport(ssh.get_transport())
    sftp = ssh.open_sftp()
    ##这句很关键要指定文件名称
    #'gongqijun.jpg'
    file_name=os.path.basename(fileName)
    print("正在上传图片到服务器:",file_name)

    load_in='D:/university/face_anime/UI/'+file_name
    #上传的图片统一改名为target,确保文件夹里只有一张图片
    # 检查扩展名
    load_out = '/root/img_input/target.jpg'
    if file_name.lower().endswith('.mp4'):
        load_out='/root/img_input/target.mp4'
    sftp.put(load_in, load_out)

    print('上传完成')
    ssh.close()
 

📢写在最后

本次分享原文自制,未经允许不得转载,否则承担法律责任!
希望我的这次分享能够帮到大家,如果有需要部分代码的,可以点赞评论收藏,然后私信我,看到都会回。也欢迎大家交流,不喜勿喷哦~
最后,祝看到这里的大家都能够有美好的未来,未来可期

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值