入门深度学习的教材都看了一些,但缺乏实践理解的都不是很深刻,只能反复看一些比较好的教材来加深印象。
正好导师给我布置了一个入门深度学习的小任务:输入人脸照片->提取前景->换背景,最后以软件应用的形式呈现出现。
1. 入门准备
由于我学深度学习之前是做全栈开发的,并且这个实践任务最后要以软件应用的形式呈现出来,正好过年刚回家,家里琐事很多,没有一个长时间段可以让我专注的学习。我便先发挥自己的长处,利用碎片的时间将该应用简易地搭建好。(为了快捷,我这里选择了SpringBoot+Wechat小程序的形式)如图所示:
这里使用了百度人像分割的API来帮助我完成,主要利用其分割返回给我的labelmap二值图来做Matting的操作。
2. 开始动手
正值疫情期间,可以安心在家做该项目。
首先捋清楚思路,现在应用是做好了,但是利用的是百度的接口,这显然是不行的,得把百度接口提供的服务拿掉,利用自己做的功能来将其替换,才能算是完成该项任务,毕竟主要目的也就是为了训练自己在DNN方面的能力。
考虑我在此之前从没有碰过深度学习,所以完全靠自己空手做出来是不太可能的,我也没有如何去做的思路。
于是我把我的思路改成这样:
(1)在Google、Github上找已经搭建好的相关项目(最好是Pytorch版)
(2)跑通它的预训练模型,剖析源码,了解并走通整个深度学习的流程
(3)对其进行修改,使其满足自己的需求,最后替换掉百度接口
2.1 找现成项目
2.1.1 Deep-Image-Matting
这是我找到的第一个项目:开源地址,复现的是该论文:论文地址(访问需梯子),
跑通该项目花了点时间:
(1)项目依赖论文作者的数据集,向作者索取数据集的时候花了一周时间
(2)我电脑存储和内存都不够,最后根据现状升级设备:外接移动硬盘,加了根内存条扩到12G(我电脑允许的最大值)
最后勉强把该项目的预训练模型跑了起来,跑通效果:
项目的效果是十分好的,但是在我解读源码的时候,发现该项目并不满足我的要求。因为该项目的良好效果依赖于用户提供的Trimap图(通过侵蚀分割出的Alpha图生成),我再细看一遍论文,发现Trimap图是作者通过手动PS获取的,这显然不满足我的需求,手动的成本太高了,遂放弃。
2.1.2 再读论文
除了Deep Image Matting,我还拜读了其它几篇论文。
(1)沈小勇的Automatic Portrait Segmentation for Image Stylization和Deep Automatic Portrait Matting
(2)Alibaba的Semantic Human Matting(访问需梯子)
这三篇论文都有一个共同的特点,不依赖于与用户的交互,根据上传的照片自动分割出前景,无需用户提供Trimp图,这人性化多了。
这下思路就有了,找找Github上这几个论文的复现项目,试试效果。
1.复现沈小勇论文效果的项目
原论文是用MATLAB来写的,我看不太明白,遂接着找有没有人用Pytorch复现该论文效果的。
但是只找到一篇用Chainer和一篇用Tensorflow的:
portrait_matting(开源地址) 和AutoPortraitMatting(开源地址)
我花了一个多礼拜的时间,尝试去跑通这两个项目中的某一个,但是都失败了。。。
这两个项目都是两三年前的了,且都已经被作者抛弃,所有issues里没有我遇见的error。
2.复现Alibaba论文效果的项目
还是跑不通。。。这几个开源项目,要么就是缺少预训练模型,要么就是一堆的errors遗留着没解决,而我暂时无法靠一己之力解决所有的问题。
2.1.3 重整思路
一两周的时间没一点成效,我开始反思自己的方向。于是又重新拜读了沈小勇的两篇论文,再次明确需求:我现在需要的效果不是Mating,而是能够根据用户上传的肖像图自动分割出前景,生成Alpha图。像这样:
要达到这种效果,也就是做Portrait Segmentation 或者 Image Segmentation,反正重点就在于自动分割。
2.1.4 再度尝试
再次明确需求后,我把重点从Matting转移到Segmentation上。
于是我在Github上找到了Pytorch-UNet这个项目,该项目高达2K+的star,100+的issues,且作者似乎还在继续更新中。该项目提供的模型是分割汽车的,且在自述文件中,作者也说明可以更换数据集去训练其它模型,用于分割其它物体。
相比之前没几个issues和star,并且被作者废弃的项目,我仿佛看到了春天,终于从没人的小角落到了人堆里来了!!
(1)第一次尝试
跑该项目只需要如下几个环境:
matplotlib numpy Pillow torch torchvision tensorboard
我很快开始了尝试,但是我跑失败了。。
于是我接着尝试了该项目以前的版本并且别人fork过去的版本。但还是失败了。。。
得到的结果都是:
Stack Overflow查出来的结果是添加strict=False参数
net.load_state_dict(torch.load(args.model, map_location=device), strict=False)
但是这样得到的效果却是一张全黑的图片:
在100+的issues里没有相关的问题出现,于是我提了个issue,希望能得到作者的解答。
(2)第二次尝试
我考虑可能是我电脑的问题,正好前几天入手了一台阿里云2核4G的服务器(无GPU)
于是我我便尝试配置一台Linunx的Ubuntu16.04系统,配置Pytorch的环境去跑该项目。
搞了两天服务器整顿好了,最后运行 :
python predict.py -i image.jpg -o output.jpg
然而还是得到了相同的报错。。。本以为即使报错也会是另一个错误的,相同的报错让我不知所措。。。
(3)第三次尝试
前两次尝试都是用pytorch的cpu版本跑的,我又再想,可能是需要GPU的原因?我的电脑显卡是950M 2G显存,姑且尝试一下吧。于是配置了CUDA和CUDNN,装了一个pytorch 1.2.0 的gpu版本。
matplotlib 3.0.3 numpy 1.18.1 Pillow 6.2.0 tensorboard 1.6.0
torch 1.2.0+cu92 torchvision 0.4.0+cu92
再度尝试:failed again...
好几天过去了,也没没得到作者对issue的答复...
问题是版本不兼容问题,作者更新了代码,但是没有更新模型,要么用旧版本代码和旧版本模型。要么用新版本代码训练新模型。
3.训练模型
细致内容请查看项目链接:GitHub - leijue222/portrait-matting-unet-flask: Portrait Mating implementation in UNet with PyTorch.