目录
利用图像增强技术(图片上色)实现对旧图像和电影片段进行着色和修复(爱因斯坦旧照/清末官员生活场景等案例)
相关文章
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. # -----------------------------