Deep Image Matting

10 篇文章 1 订阅


还有一篇:深度抠图--Deep Image Matting也不错。不过,下面转载另一篇挺好的博文↓,对Deep Image Matting复现过程总结:

原文链接:想要快速了解论文的同学可以只看第一部分。想自己实现一遍这篇论文的同学,请仔细阅读第二部分论文复现,这部分涉及非常多的细节。

论文地址
https://arxiv.org/abs/1703.03872

目录

论文梳理

首先需要理清的是,image matting到底是用于解决什么样的问题?matting问题的核心是一个表达式:
———————————-(1)
即通过alpha控制透明度来使前景FG和背景BG融合的技术。有不少人把deep image matting理解为’深度抠图’,其实抠图用到的是backgournd removal技术[1],它关注的是如何寻找确定的前景和背景,即alpha等于0和1的部分,matting想解决的则像是如何完美的将两张图融入到一起,即alpha不等于1的部分(我的理解,可能有误)。认识这点对后面损失函数权重的配比至关重要。

创建新的训练集

要以深度学习的方式来解决这个问题,就需要寻找大量的训练数据。已经公开的matting领域的benchmark——alphamatting[2][3]的训练集只有27张训练样本,远远达不到深度学习的要求。作者从视频中采取了400多张图,并用PS人工抠出了它的前景图,然后将每一张图分别融合到100个不同的背景里,最后得到了49300个训练样本(在申请作者数据的时候,得到的文件中会包含一份纠错说明,提到论文的数据有误,实际上并没有那么多)。

想要训练什么样的网络

文章想要最终实现的效果如下图:输入原始的RGB图片和对应的trimap(确定的前景alpha=1,确定的背景alpha=0,和不确定的边缘——unknown region, alpha=0.5),输出预测的alpha,即没有unknown region的trimap。
输入
输出

模型结构和训练技巧


左边为典型的encoder和decoder结构,在segmentation和很多以图得图的GAN中比较常见。encoder用pre-trained的VGG16,把fc6从全连接换成了卷积,并在输入增加了第四通道channel4,用来存放输入的trimap,因为channel4而增加的weights全部初始化为0。decoder用简单的unpool和convolution的组合来做upsampling和空间结构推断。右边的refine network是为了解决第一阶段预测输出边缘blur的情况。

损失函数

为两个loss的加权组合:alpha loss和compositional loss。alpha loss是预测alpha和实际alpha的误差,conpositional loss是将预测的alpha通过公式(1)与相应的背景和前景融合后,与ground truth RGB图的误差。只有trimap中unknown region区域的预测误差才会被反向传播(这是matting与background removal的区别,matting需要trimap作为用户交互接口,只需预测matting中不确定的区域,而backgournd removal则需要将整张图的误差反响传播),即trimap中为纯背景和纯前景的部分不计入模型预测范围,只需要把这两部分直接复制到输出的alpha即可。(注意误差都是pixel-wise的)

作者在训练过程中的技巧

  1. 从原图中随机crop 320,480,640的训练patch,然后统一resize到320,作为网络输入(这里的操作必须对于你训练的那个样本的background,foreground,alpha同步操作)。
  2. 随机翻转(同上)
  3. trimap由alpha以随机大小kernel的dilation[4]操作生成。
    Refinement很好理解,这里不展开解释了。

论文阅读阶段遗留的几个问题

  1. 训练mini batch的size
  2. crop的安全性是怎么解决的?因为以unknown region为中心随机crop,很可能会出现crop超出边界的情况。
  3. compositional值的scale是0~255,而alpha loss的scale是0~1,如果不对compositional loss除以255的话,会出现loss严重倾向于compositional loss的情况。
  4. 在网络结构上是否有其他技巧,比如PReLU,batch_normalization。

论文复现

数据准备和预处理阶段

由于有来自xx公司的数据,所以实验没有建立在作者数据的基础上。预处理阶段需要注意的很多很多,大致流程如下图:

能离线处理的数据就尽量离线处理,比如把所有的backgournd都提前整理好,具体文件夹结构的组织方式可以去看我在github[5]上上传的data_structure说明。对这个图简单解释一下:

我们有什么?

  1. 训练数据的alpha
  2. 训练数据的RGB(即图中的eps,这个数据是foreground的来源,需要在程序中与alpha组合产生foreground,再matting到背景上实现真正的输入RGB)
  3. background(来自pascal voc和coco)

如何整理数据?

  1. 把alpha和eps都resize到最长边为640,同时保留长宽比。
  2. 因为crop的最大size为640*640,所以把background都resize到最短边为1280,同时保留长宽比。
  3. 把alpha和eps都center padding到背景里,这样无论怎样crop,只要是以trimap的unknown region为中心,就不会出现crop出边界的情况(另一种解决方案,不resize背景,直接将alpha和eps center pad进背景,假设crop出边界,把出界的那条边拉回来即可。比如crop左边出界了,则设置crop左边的起始位置为0。作者应该采用的是这种方式,因为从作者分享的代码来看没有针对background做特殊操作)。

前三点都是离线准备好的,即不是在网络训练的时候进行,下面的步骤都是在网络训练的时候同时进行。

  1. 通过对alpha进行random dilation得到trimap。
  2. 以trimap中的unknown region任取一点为中心对alphap,eps,trimap进行crop(size也是从320,480,640中随机选择)
  3. 如果size选择到的不是320,则对所有数据resize到320作为网络输入。此时我们拥有了ground truth background, ground truth alpha, ground truth trimap, ground truth eps。还缺了什么?缺了ground truth foreground
  4. 通过公式1对此时的alpha和eps进行composition得到ground truth foregournd。
  5. 通过公式1对此时的alpha,eps和BGcomposition得到ground truth RGB。
  6. ground truth RGB减去global mean,然后concatenate trimap作为网络的4通道输入,剩余的作为计算Loss的原料。

至此,数据准备和预处理阶段完成。这里值得提的有四点(我犯过的错误)
1. 离线数据不到最后一步千万不要用jpg格式保存,用png,因为jpg是有损压缩,对于这种像素级精度都要求很高的项目来说,中间以jpg保存一次就非常致命了。可以在最后一步保存为jpg因为即便出现误差,也是ground truth的整体飘移,飘移后的数据依然保持一致性,不会对网络的训练造成影响。
2. 任何resize操作不能发生在用公式(1)之后,这也是为什么要组织上图那样精细的数据预处理的原因。这样会造成ground truth漂移,会产生训练数据的不一致性。下面有举例说明。
3. 其他resize可以采用默认的双线性插值。但是trimap最好用nearest插值的方式resize,因为其他方式几乎都会改变像素值,而对于trimap必须保证unknown region为128,而nearest插值不会生成新的像素值,只会在原始图像的像素中提取,而且trimap对nearest插值带来的锯齿不敏感(因为trimap本身就是非常语义模糊的),所以对于trimap,nearest是最理想的resize方式。
4. resize alpha的时候,先把数据类型转换成uint8,resize过后再转换回float32,因为misc.imresize操作会对float型的数据rescale,所以你输入图片最大的像素值是32,输出可能直接就被rescale到255了。

为什么先融合再resize会产生ground truth飘移

先融合,再resize先resize,在融合

两张图看似一样,但是一作差就会发现

所以如果先融合,再resize,此时你得到的foreground对应的都不是当初原原本本的alpha了(resize产生的误差),这对于神经网络的训练极为不利,因为网络努力拟合的方向不是真正它应该去的方向(出现了些许飘移)。从adobe公司提供的组合compositional的代码可以发现,ground truth RGB是提前离线生成的,也就是说先mat了,而在后面的预处理阶段还有resize操作。假设作者真的犯了这个错误而没意识到,那可能是文章中模型需要第二阶段refinement的原因。也就是说如果不犯这个错误的话,可能就不需要第二阶段的refinement网络了(这是我个人的推测)。

训练阶段

训练阶段没有太多可以谈的。谈谈我实现过程中与作者不一致的地方。
1. 一开始我选择用deconvolution代替unpool操作,因为tensorflow没有现成的unpool函数,虽然有opensource的,但是都会对网络输入的batch size产生限制。即你训练用mini batch size为5,那么预测阶段也只能5个一起预测,非常不便。但是实验中发现,虽然用deconvolution能对单一的有样本过拟合,但是却很难在整个训练集上拟合,考虑到用deconvolution后,网络的复杂度其实是高于作者用的网络的,所以不能在整个网络上拟合是非常奇怪的事。我能想到唯一的解释就是训练时间不够。最终deconvolution的实验在学习率为1e-5的情况下跑了5天,模型能非常好的预测general shape,但是一直无法拟合边缘,后来放弃了deconvolution的做法。
2. 用了batch normalization。虽然原文没提到这一点,但是仅仅是因为不用batch norm,模型最后都会预测出全黑的结果,所以加上了这个正则化方法,相应的把学习率调整到了1e-4,拟合变得非常快。用了unpool之后拟合只需要7小时。
3. 之前说unpool有限制输入batch size的问题,后来为什么又用unpool了?因为参考了segmentation的论文发现,其实在这种以图预测图的任务中,可以认为每一个像素都是一个训练样本,这样即便batch size为一,模型在一次训练中也进行了大量的预测,这点是与classification任务不同的地方。所以最后索性设置batch size为1,将deconvolution换成了unpool.模型成功拟合了,泛化略微没有作者表现的那么好。具体请参考我关于这个项目的github页面[5]。
4. 出于某些原因,在github上的代码里对纯背景和纯前景的地方也进行了误差的反向传播,权重设为了0.5。实验证明,是否对bg和fg区域进行反向传播对模型的上限没有影响。如果不想那两部分的误差有影响,只需将权重设置为0。


公司出于某些原因,给我安排了新任务,虽然跟matting很像,但是这篇论文的复现恐怕要到此为止了,训练阶段的第一点,即“排除了作者预处理上的失误后,我们能不能不用refinement网络而达到原论文的水平”暂时没时间去验证。也因为公司接下来不会用这个项目,所以才能以博客和开源的方式在这里把复现过程分享给各位,欢迎大家发表自己的意见。

最后把这个项目的github地址单独拉出来:
https://github.com/Joker316701882/Deep-Image-Matting

References

[1]https://clippingmagic.com/
[2]http://alphamatting.com/
[3]http://www.juew.org/publication/CVPR09_evaluation_final_HQ.pdf
[4]http://docs.opencv.org/2.4/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html
[5]https://github.com/Joker316701882/Deep-Image-Matting


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值