CV之NoGAN:利用图像增强技术(图片上色)实现对旧图像和电影片段进行着色和修复(爱因斯坦、鲁迅旧照/清末官员生活场景等案例)

本文涉及的产品
视觉智能开放平台,图像资源包5000点
视觉智能开放平台,分割抠图1万点
视觉智能开放平台,视频资源包5000点
简介: CV之NoGAN:利用图像增强技术(图片上色)实现对旧图像和电影片段进行着色和修复(爱因斯坦、鲁迅旧照/清末官员生活场景等案例)


目录

利用图像增强技术(图片上色)实现对旧图像和电影片段进行着色和修复(爱因斯坦旧照/清末官员生活场景等案例)

算法步骤

输出结果

核心代码


相关文章

CV之NoGAN:利用图像增强技术(图片上色)实现对旧图像和电影片段进行着色和修复(爱因斯坦、鲁迅旧照/清末官员生活场景等案例)

CV之NoGAN:利用图像增强技术(图片上色)实现对旧图像和电影片段进行着色和修复(爱因斯坦、鲁迅旧照/清末官员生活场景等案例)实现

利用图像增强技术(图片上色)实现对旧图像和电影片段进行着色和修复(爱因斯坦旧照/清末官员生活场景等案例)

算法步骤

  • 第一步,首先以传统方式自行训练生成器,仅使用特征损失(feature loss)。
  • 第二步,从中生成图像,并训练critic区分这些输出和真实图像作为基本的二元分类器。
  • 第三步,在 GAN 设置中一起训练生成器和critic(在这种情况下从目标大小 192 像素开始)。现在是奇怪的部分:这里所有有用的 GAN 训练只发生在一个非常小的时间窗口内。有一个转折点,critic似乎已经转移了对生成器有用的一切。在这一点之后,图像质量会在拐点处获得的最佳或可预测的糟糕(橙色皮肤、过度红唇等)之间摇摆不定。在拐点之后似乎没有有效的训练。而这一点在于仅对 Imagenet 数据的 1% 到 3% 进行训练!这相当于在 192px 下进行大约 30-60 分钟的训练。

        困难的部分是找到这个拐点。到目前为止,我已经通过制作一大堆模型保存checkpoints(每 0.1% 的数据迭代)来实现这一点,然后只是寻找图像看起来很棒的点,然后它们会完全变成橙色皮肤(总是第一件要做的事)。此外,此时生成器渲染会立即开始出现故障和不一致,这对于视频来说尤其不利。我真正想弄清楚的是,拐点的迹象是什么,可以很容易地自动作为早期停止点。不幸的是,我还没有发现任何确凿的证据。一方面,它发生在训练损失减少的中间——而不是在它变平的时候,这从表面上看似乎更合理。

        关于NoGAN训练的另一个关键的事情是,你可以在初始GAN训练之后重复对生成的图像进行预训练critic ,然后以同样的方式重复GAN训练本身。这就是我如何使用“艺术”模型获得额外丰富多彩的结果。但这确实是有代价的 - 生成器的输出变得越来越不一致,您必须尝试渲染分辨率 (render_factor) 以获得最佳结果。但是渲染仍然没有小故障,而且比我用原始的DeOldify模型实现的更加一致。就我所知,在你得到收益递减之前,你可以做五次这样的重复循环,给予或接受。

        请记住 - 我在弄清楚 NoGAN 中发生的一切方面并不是很严谨 - 我会把它留到一篇论文中。这意味着我很有可能在某些事情上是错的。但我认为它现在绝对值得推出,因为我发现它非常有用 - 它基本上解决了我在 DeOldify 中遇到的大部分剩余问题。

输出结果

 

核心代码

1. from deoldify.visualize import *
2. 
3. plt.style.use('dark_background')
4. torch.backends.cudnn.benchmark=True
5. 
6. import warnings
7. warnings.filterwarnings("ignore", category=UserWarning, message=".*?Your .*? set is empty.*?")
8. 
9. artistic_code=False     # True False
10. if artistic_code:
11.     artistic_txt='Artistic'
12. else:
13.     artistic_txt='Stable'
14. colorizer = get_image_colorizer(artistic=artistic_code)  #Artistic 为布尔值, True 表示启用 Artistic 模式 ( False 启用 Stable 模式);
15. 
16. # # render_factor=35
17. # render_factor=10   # 表示渲染因子,值越效果越好
18. # source_path = 'test_images/Einstein.jpg'
19. # result_path = 'test_images/Einstein_res_%s.jpg'%render_factor
20. # colorizer.plot_transformed_image(path=source_path, results_dir=result_path,render_factor=render_factor, compare=True)
1. from fastai.vision import *
2. from fastai.vision.learner import cnn_config
3. from .unet import DynamicUnetWide, DynamicUnetDeep
4. from .loss import FeatureLoss
5. from .dataset import *
6. 
7. # Weights are implicitly read from ./models/ folder
8. def gen_inference_wide(
9.     root_folder: Path, weights_name: str, nf_factor: int = 2, arch=models.resnet101) -> Learner:
10.     data = get_dummy_databunch()
11.     learn = gen_learner_wide(
12.         data=data, gen_loss=F.l1_loss, nf_factor=nf_factor, arch=arch
13.     )
14.     learn.path = root_folder
15.     learn.load(weights_name)
16.     learn.model.eval()
17. return learn
18. 
19. 
20. def gen_learner_wide(
21.     data: ImageDataBunch, gen_loss, arch=models.resnet101, nf_factor: int = 2
22. ) -> Learner:
23. return unet_learner_wide(
24.         data,
25.         arch=arch,
26.         wd=1e-3,
27.         blur=True,
28.         norm_type=NormType.Spectral,
29.         self_attention=True,
30.         y_range=(-3.0, 3.0),
31.         loss_func=gen_loss,
32.         nf_factor=nf_factor,
33.     )
34. 
35. 
36. # The code below is meant to be merged into fastaiv1 ideally
37. def unet_learner_wide(
38.     data: DataBunch,
39.     arch: Callable,
40.     pretrained: bool = True,
41.     blur_final: bool = True,
42.     norm_type: Optional[NormType] = NormType,
43.     split_on: Optional[SplitFuncOrIdxList] = None,
44.     blur: bool = False,
45.     self_attention: bool = False,
46.     y_range: Optional[Tuple[float, float]] = None,
47.     last_cross: bool = True,
48.     bottle: bool = False,
49.     nf_factor: int = 1,
50.     **kwargs: Any
51. ) -> Learner:
52. "Build Unet learner from `data` and `arch`."
53.     meta = cnn_config(arch)
54.     body = create_body(arch, pretrained)
55.     model = to_device(
56.         DynamicUnetWide(
57.             body,
58.             n_classes=data.c,
59.             blur=blur,
60.             blur_final=blur_final,
61.             self_attention=self_attention,
62.             y_range=y_range,
63.             norm_type=norm_type,
64.             last_cross=last_cross,
65.             bottle=bottle,
66.             nf_factor=nf_factor,
67.         ),
68.         data.device,
69.     )
70.     learn = Learner(data, model, **kwargs)
71.     learn.split(ifnone(split_on, meta['split']))
72. if pretrained:
73.         learn.freeze()
74.     apply_init(model[2], nn.init.kaiming_normal_)
75. return learn
76. 
77. 
78. # ----------------------------------------------------------------------
79. 
80. # Weights are implicitly read from ./models/ folder
81. def gen_inference_deep(
82.     root_folder: Path, weights_name: str, arch=models.resnet34, nf_factor: float = 1.5) -> Learner:
83.     data = get_dummy_databunch()
84.     learn = gen_learner_deep(
85.         data=data, gen_loss=F.l1_loss, arch=arch, nf_factor=nf_factor
86.     )
87.     learn.path = root_folder
88.     learn.load(weights_name)
89.     learn.model.eval()
90. return learn
91. 
92. 
93. def gen_learner_deep(
94.     data: ImageDataBunch, gen_loss, arch=models.resnet34, nf_factor: float = 1.5
95. ) -> Learner:
96. return unet_learner_deep(
97.         data,
98.         arch,
99.         wd=1e-3,
100.         blur=True,
101.         norm_type=NormType.Spectral,
102.         self_attention=True,
103.         y_range=(-3.0, 3.0),
104.         loss_func=gen_loss,
105.         nf_factor=nf_factor,
106.     )
107. 
108. 
109. # The code below is meant to be merged into fastaiv1 ideally
110. def unet_learner_deep(
111.     data: DataBunch,
112.     arch: Callable,
113.     pretrained: bool = True,
114.     blur_final: bool = True,
115.     norm_type: Optional[NormType] = NormType,
116.     split_on: Optional[SplitFuncOrIdxList] = None,
117.     blur: bool = False,
118.     self_attention: bool = False,
119.     y_range: Optional[Tuple[float, float]] = None,
120.     last_cross: bool = True,
121.     bottle: bool = False,
122.     nf_factor: float = 1.5,
123.     **kwargs: Any
124. ) -> Learner:
125. "Build Unet learner from `data` and `arch`."
126.     meta = cnn_config(arch)
127.     body = create_body(arch, pretrained)
128.     model = to_device(
129.         DynamicUnetDeep(
130.             body,
131.             n_classes=data.c,
132.             blur=blur,
133.             blur_final=blur_final,
134.             self_attention=self_attention,
135.             y_range=y_range,
136.             norm_type=norm_type,
137.             last_cross=last_cross,
138.             bottle=bottle,
139.             nf_factor=nf_factor,
140.         ),
141.         data.device,
142.     )
143.     learn = Learner(data, model, **kwargs)
144.     learn.split(ifnone(split_on, meta['split']))
145. if pretrained:
146.         learn.freeze()
147.     apply_init(model[2], nn.init.kaiming_normal_)
148. return learn
149. 
150. 
151. # -----------------------------


相关文章
|
6月前
|
人工智能 搜索推荐
StableIdentity:可插入图像/视频/3D生成,单张图即可变成超人,可直接与ControlNet配合使用
【2月更文挑战第17天】StableIdentity:可插入图像/视频/3D生成,单张图即可变成超人,可直接与ControlNet配合使用
109 2
StableIdentity:可插入图像/视频/3D生成,单张图即可变成超人,可直接与ControlNet配合使用
|
机器学习/深度学习 运维 算法
基于卷积神经网络和手工特征注入的皮肤损伤图像异常检测:一种绕过皮肤镜图像预处理的方法
基于卷积神经网络和手工特征注入的皮肤损伤图像异常检测:一种绕过皮肤镜图像预处理的方法
117 1
|
4月前
动态人物抠图换背景 MediaPipe
动态人物抠图换背景 MediaPipe
|
机器学习/深度学习 编解码 算法
【阿里云OpenVI-视觉生产系列之图片上色】照片真实感上色算法DDColor ICCV2023论文深入解读
图像上色是老照片修复的一个关键步骤,本文介绍发表在 ICCV 2023 上的最新上色论文 DDColor
2684 10
【阿里云OpenVI-视觉生产系列之图片上色】照片真实感上色算法DDColor ICCV2023论文深入解读
【永劫无间的捏脸功能】调整角色的基本面部特征,如眼睛大小、眼角、嘴唇、下巴
【永劫无间的捏脸功能】调整角色的基本面部特征,如眼睛大小、眼角、嘴唇、下巴
116 0
|
人工智能 编解码 移动开发
NeRF基于线稿生成逼真三维人脸,细节风格随意改,论文已上SIGGRAPH
NeRF基于线稿生成逼真三维人脸,细节风格随意改,论文已上SIGGRAPH
456 0
|
机器学习/深度学习 人工智能 算法
给图片悄悄加上像素级水印:防止AI「抄袭」艺术作品的方法找到了
给图片悄悄加上像素级水印:防止AI「抄袭」艺术作品的方法找到了
223 0
|
机器学习/深度学习
识别手绘数字图像
识别手绘数字图像
85 0
|
编解码 缓存 计算机视觉
神还原物体复杂、高频细节,4K-NeRF高保真视图合成来了
神还原物体复杂、高频细节,4K-NeRF高保真视图合成来了
137 0
|
机器学习/深度学习 人工智能 算法
活久见!像素随机打乱的手写字体图像竟能被非监督学习方法全新重建?
活久见!像素随机打乱的手写字体图像竟能被非监督学习方法全新重建?