http://openaccess.thecvf.com/content_cvpr_2018/html/Chen_CartoonGAN_Generative_Adversarial_CVPR_2018_paper.html
CartoonGAN是18年的一篇CVPR。
是将一般的图片转换为卡通的图片,可以说是CycleGAN之类的应用版。其中提到了几个改进的技术点,比较有特点, 且效果不错。
值得注意的是,这篇论文,我没有完整实现,只是完成了部分的代码。原因:
最最主要的原因是:实验规模太大。需要模型运算的图片太大,跑起来很麻烦。一开始我也是打算自己跑的,但是做了那个边际模糊的操作后的图片,一压缩,和没有做边际模糊基本一模一样(压缩的时候边际模糊的部分没办法看到了)。
改进部分是比较巧妙的设计,但是理论思想倒不算太突出。但是,能看到有更好的实验效果,并且应用价值也很高。
这篇按照技术点分着来讲,很简单的。
主要分为:模型架构(很重要),Edge Loss,Content Loss,
Initialization phase
(后三者是主要创新点)
模型架构
使用residual block,这个其实我之前在DualGAN的时候已经是使用了的(实际DualGAN论文中没有提到,但是为了模型稳定我在之前加了这个)。
本质上就是多做几层卷积(但是不改变大小)的映射。在ResNet中提出。后来也有人用这个来改进U-Net(医学图像分割),得到更加稳定的结果。因为DualGAN和pix2pix都讲到了这个U-Net后来是都用了的。
当然这个部分其实用DualGAN估计也是没有问题的。
DualGAN模型理论以及Python实现
恰饭
Edge Loss
在CartoonGAN之前也有人做卡通方面的风格迁移,但是效果不好,主要是是体现在图像较为模糊。因为GAN之类的图形,本质上是学习的概率分布。就算模糊,概率部分也是基本相似的,所以存在用GAN生成图片都有中边际不太明显的情况。
因此CartoonGAN创新式地提出了Edge loss的概念。也很简单。就是想办法构造一个目标类(比如卡通图片)对应的边际模糊掉的图片集,称之为E。
然后添加,这个损失:
正常的GAN是只有第一个和最后一个两项的。但是这里加了边际被模糊的图片集合。
构建边际模糊集合的方法:
edge detection(边际探测)
dilate the edge regions(边际区域膨化)
Gaussion blur(高斯模糊)
具体的代码:
import cv2import osimport globdef img_edge_blur(path, dst_path): img = cv2.imread(path) data = (150, 150) img_copy = img.copy() imgCanny = cv2.Canny(img, *data) # 创建矩形结构 g = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) g2 = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7)) # 膨化处理 # 更细腻 img_dilate = cv2.dilate(imgCanny, g) # 更粗大 img_dilate2 = cv2.dilate(imgCanny, g2) shape = img_dilate.shape # 提取 for i in range(shape[0]): for j in range(shape[1]): if img_dilate2[i, j] == 0: # 二维定位到三维 img[i, j] = [0, 0, 0] dst = cv2.GaussianBlur(img, (3, 3), 0, 0, cv2.BORDER_DEFAULT) for i in range(shape[0]): for j in range(shape[1]): if img_dilate[i, j] != 0: # 二维定位到三维 img_copy[i, j] = dst[i, j] filename = path[path.rindex('\\')+1:] dst_path = os.path.join(dst_path, filename) cv2.imwrite(dst_path, img_copy) print(dst_path, 'finished')if __name__ == '__main__': sketch_path = r'D:\Software\DataSet\CUHK_Face_Sketch\CUHK_training_sketch\sketch' edge_path = r'D:\Software\DataSet\CUHK_Face_Sketch\CUHK_testing_sketch\edge_blur' for file in glob.glob(r'D:\Software\DataSet\CUHK_Face_Sketch\CUHK_training_sketch\sketch\*.jpg'): img_edge_blur(file, edge_path)
调用这个函数就好了,path的输入是图片文件的路径,dstpath输入的是目标存放图片的目录(需要自己创建)。
调用的demo也在上面,可以按照自己的情况修改。
Content Loss
除了添加了一个Edge loss之外,CartoonGAN还添加了一个Content Loss。主要是为了保持内容上一致性。有点风格迁移当中的保持内容信息的那些操作。这个Content Loss需要用以前已经需要好的模型来计算。
文中作者推荐使用VGG的feature层。用Pytorch实现这个步骤还是比较简单的。
下载并加载预训练的模型在昨天发的(代码也是按照那个写就好了)
Pytorch预训练模型下载并加载(以VGG为例)自定义路径
因此总的损失计算方法为:(很明显,L_con前面为超参)
并且,使用的L1-范数。
Initialization phase
这个创新点有点意思。而且对于CartoonGAN来说至关重要。
下面是一组对比实验:分别对应于模型中三个步骤。
第一个当然就是初始化操作。表示没有就直接凉了。
第二表示在Content Loss当中,使用L2范数。(会导致和原始图片太接近了,损失太强导致没有学习到风格信息)
第三个对应于edge loss。也是存在纹理细节上不够清晰的问题。
这个初始化也很简单,就是前面几个回合,只考虑Content loss来训练G。
由于Content loss的构造,只涉及到G和已经被训练好的VGG。所以计算上是没有问题的。
后续会补充,基于CartoonGAN提出的这些技术来改进之前提到的那一系列的模型。比如pix2pix,CycleGAN,DualGAN等等。