简介

DeOldify项目是一个黑白照片上色的AI项目

项目地址:https://github.com/jantic/DeOldify

NoGAN训练对于获得在DeOldify中的稳定和彩色图像至关重要。

NoGAN训练结合了GAN训练的好处(出色的色彩),同时消除了令人讨厌的副作用(例如视频中闪烁的物体)。视频是使用孤立的图像生成来渲染的,而无需进行任何时间建模。该过程执行一次30至60分钟的“ NoGAN”训练的GAN部分,一次使用1%到3%的imagenet数据。然后,与静止图像着色一样,在重建视频之前对各个帧进行“ DeOldify”处理。

WHAT IS NoGAN?

NoGAN是作者为了解决DeOldify之前模型中存在问题的一种新的GAN的训练方式。它提供了GAN训练的好处,但又只用了最少的时间来进行GAN的直接训练。取而代之的是,大部分训练时间都花在了通过更直接,更快速,更可靠的常规方法分别对生成器和注释器进行预训练。这里一个关键见解是,那些更常规的方法通常可以提供所需的大多数结果,GAN可以用于填合实际运用中的间阂。在实际非常短的GAN训练期间,生成器不仅获得了过去需要几天逐步调整训练的完整的逼真的着色功能,而且还没有产生太多的复杂附件。实际上,结果几乎可以消除故障和伪影。作者认为这是一种有效的新的技术。

具体的过程是这样的:首先以常规的方式来训练生成器,其中仅包括了特征损失。然后,从生成器生成图像,并训练判别器来实现基本的二分类任务。最后,在GAN的设置中一起训练生成器和判别器。(在这种情况下,从192px的目标尺寸开始)

接下来是较为特别的一部分,这里所有用到的GAN训练都只在很少的时间内进行。在拐点之后,训练结果在最佳线上波动,并可能以可预见的方式变差(皮肤变色,嘴唇过红等)。拐点之后似乎就没有建设性的训练了。拐点的出现在对Imagenet数据训练的1%到3%。这相当于以192px进行大约30~60分钟的训练。

困难的部分是找到这个一个拐点。作者通过每0.1%数据的迭代保存了效果不错的点。在那之后基本都是皮肤变黄,生成器出现毛刺和不一致,这特别不适用于视频。作者想要弄清楚的是这个拐点能自动被标注的明显标志是什么。但目前并没有明显的结果,只能说它是在损失变小的过程过出现的,而不是在曲线变平之前。

NoGAN训练的另一项关键在于,你可以在GAN的初始化训练后对生成器进行重复的预训练,然后以相同的方式训练GAN本身。这就是作者能够在“artistic”模型下获得更多色彩效果的方式,但这会有一定的代价,生成器的输出越来越不一致,且你必须尝试使用渲染分辨率来获得最佳结果。

作者认为他对NoGAN的过程的推论并不是完全严格,但他觉得现在绝对值得推向市场,因为这个方法非常有用,基本上解决了在之前DeOldify的模型中积累下的很多问题。

效果图

先看看项目给出的图片对比效果。

Image

Image 从给出的效果可以看出,上色后的图片对人物、景色、物品、环境等等都变得很生动。

安装

看一下项目的README中关于安装的部分。

使用anaconda安装环境。安装完成后看一下模型文件需要下载哪些。

仔细看看,文章给出了不同模型的区别。

从作者的描述中,可以看出前面2个主要是针对图像的模型,一个艺术一个稳定,等下使用的时候看看区别。

模型下载

三个模型如果比较难下载,可以从我的网盘下载,地址如下。

链接:https://pan.baidu.com/s/11VJoC3na9wzOuiwsb7gw9Q 提取码:TUAN

下载的3个模型文件放到项目根目录下models文件夹内,没有就创建models。

代码改造使用

作者在README中给出了docker快速启动以及api启动方式。有点麻烦,还是自己改一下。

先看一下app.py代码内容。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@app.route("/process", methods=["POST"])
def process_image():
 
    input_path = generate_random_filename(upload_directory,"jpeg")
    output_path = os.path.join(results_img_directory, os.path.basename(input_path))
 
    try:
        if 'file' in request.files:
            file = request.files['file']
            if allowed_file(file.filename):
                file.save(input_path)
            try:
                render_factor = request.form.getlist('render_factor')[0]
            except:
                render_factor = 30
            
        else:
            url = request.json["url"]
            download(url, input_path)
 
            try:
                render_factor = request.json["render_factor"]
            except:
                render_factor = 30
 
        result = None
 
        try:
            result = image_colorizer.get_transformed_image(input_path, render_factor=render_factor, post_process=True, watermarked=True)
        except:
            convertToJPG(input_path)
            result = image_colorizer.get_transformed_image(input_path, render_factor=render_factor, post_process=True, watermarked=True)
        finally:
            if result is not None:
                result.save(output_path, quality=95)
                result.close()
 
        callback = send_file(output_path, mimetype='image/jpeg')
        return callback, 200
 
    except:
        traceback.print_exc()
        return {'message': 'input error'}, 400
 
    finally:
        pass
        clean_all([
            input_path,
            output_path
            ])

可以看出该POST接口主要操作分为:获取文件流、根据参数调整渲染因子(默认为30)、通过image_colorizer对象进行染色操作、最终将文件流返回。按照这个方法我改造了一个直接使用的工具方法。

代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/user/bin/env python
# coding=utf-8
"""
@project : DeOldify
@author  : 剑客阿良_ALiang
@file   : test1.py
@ide    : PyCharm
@time   : 2022-06-17 16:37:13
"""
import os
from pathlib import Path
 
from app_utils import convertToJPG
from deoldify.visualize import ModelImageVisualizer, get_image_colorizer
 
 
def colorizer(input_path, output_dir):
    _output_path = os.path.join(output_dir, os.path.basename(input_path))
    _image_colorizer = get_image_colorizer(artistic=True)
    try:
        result = _image_colorizer.get_transformed_image(input_path, render_factor=30, post_process=True,
                                                        watermarked=True)
    except:
        convertToJPG(input_path)
        result = _image_colorizer.get_transformed_image(input_path, render_factor=30, post_process=True,
                                                        watermarked=True)
    finally:
        if result is not None:
            result.save(_output_path, quality=95)
            result.close()
 
 
if __name__ == '__main__':
    colorizer("./data/image/xxx1.jpg", "./data/result1")

一些异常情况我就不处理,如果需要的话,使用的时候加一些补充代码即可。

artistic参数作为是否使用艺术模型的bool参数。

看一下我准备的需要上色的照片。

选择Artistic模型的效果如下:

选择Stable模型的效果如下:

还是可以看出一些区别的,只是本人没啥艺术细菌,看不大出来怎么个艺术法。

注意

1、 上面的工具代码由于引入了项目中的几个方法,可能存在引入包缺失问题。补充安装如下:

1
2
3
4
5
pip install opencv-python -i https://pypi.douban.com/simple

pip install scikit-image -i https://pypi.douban.com/simple

pip install ffmpeg -i https://pypi.douban.com/simple

2、安装scikit-image的时候会安装Pillow最新版本,可能会导致执行错误,补充卸载安装Pillow如下:

1
2
3
pip uninstall Pillow

pip install Pillow==6.2.2