纯前端实现人脸检测,并给你的头像戴上口罩!
本文来自社区投稿与征集,作者 Howard Zhang,东华大学研究生在读,中科院计算所客座学生。
本文转自:https://zhuanlan.zhihu.com/p/104070435
根据春节的起源,如果“年”真的是一个凶猛的怪兽,那么今年一定是 2019-nCoV 病毒。往年辟邪用的红纸和鞭炮,变成了各色各样的口罩。约好的聚会和自驾游纷纷取消,同学们都成了躲避瘟疫的牛顿,在家里思考科学。甚至在社交网络上也少了很多年味,越来越多的人把口罩都戴到了自己的头像上。
第一次瞥见这种潮流是在除夕前一天,微信群聊里的一个朋友的头像突然刷新,只是多了个口罩,一切都令人猝不及防。我当时的第一反应是又有小机灵鬼出现了,应该已经做出能自动给头像加口罩的应用了吧?但是经过一番短暂的调研,现有的 APP 和网页版的头像生成器都没有人脸检测的功能,还是靠手动添加贴纸,一点都不智能。理想太丰满,反正也是假期,遂打算自己写一个。于是这一写就写了三天,最后用纯前端实现了一个可以对图像进行人脸关键点检测并自动添加口罩的单页应用。
给你的头像戴上口罩
由于这个项目压根不需要后台代码,因此部署很方便(有点边缘计算的意思?)。考虑到 GitHub Pages 在国内的惨烈加载速度,我同时在码云上部署了一份,欢迎体验。
立即试用:给你的头像戴上口罩
https://zamhown.gitee.io/wear-a-mask/
至于大体的使用流程,就是用户上传自己的头像后,页面会自动检测图片中的人脸,识别出关键点后匹配最适合的口罩贴纸。然后用户可以在编辑器内改变贴纸的位置、大小、旋转角度和翻转,然后将修改后的头像导出。整个过程都在前端完成,图片无需上传到服务器。最后成品的一个截图如下,界面中间是编辑区,正在编辑用户上传的图片:
偶然发现草间弥生老奶奶和我的 UI 蜜汁般配
分割线一划,下面介绍一下实现吧。由于开发时间比较紧促(因为眼看着越来越多的人给自己头像 P 了口罩,潜在用户越来越少),因此在技术上只做到了 baseline,后续如果有机会和时间,可能会在模型等各个方面提升一下。目前项目已开源(仓库链接在文末),下文的内容大体上写进了 README,也包含对 README 的一点扩充。
人脸检测和人脸关键点检测
面对这两个任务,第一个想法是直接用 TensorFlow.js(tfjs) 实现。目前 tfjs 拥有基于 WebGL 的 GPU 加速功能,并支持任何现代 GPU,并不局限于英伟达,如果不考虑它尚不支持的功能的话还是有点香。但是偶然间发现了一个更细化的库,名为 face-api.js,它是对 tfjs-core 的一个封装,包含了一些人脸检测和识别的模型和 API。
TensorFlow.js
https://github.com/tensorflow/tfjs
在本项目中,通过实际效果的比较,人脸检测任务选择了 SSD MobileNet V1 模型(用 WIDERFACE 数据集进行训练),人脸关键点检测任务选择了 face-api.js 作者构建的基于 CNN 的 68 点检测模型(在约有 35,000 张面部图像的数据集上进行训练),模型权重数据来源于 face-api.js。
WIDERFACE 数据集
http://mmlab.ie.cuhk.edu.hk/projects/WIDERFace
68 点检测模型的一个输出
由于本项目的研究对象是用户头像,和单纯的人脸检测任务还是有不小的区别。简单来说就是口罩不光可以加在人脸上,有时还需要加在二次元人像和动物面部之上等等。但是由于时间原因还没有扩充相关数据集进行重新训练或迁移学习,只是用人脸检测模型做出了成品。目前经过实际测试,模型在大部分的清晰人脸照片和小部分的二次元人像上表现良好。
AI 给了周杰伦一个口罩
小乌的脸也能够识别,但是二次元效果不如三次元
关于 SSD MobileNet V1,结构上是用 Google 提出的 MobileNet V1 模型替换了 SSD 网络中的 VGG16 部分作为特征提取器,将深度可分离卷积带到了 SSD。顺带相关论文链接:
SSD
https://arxiv.org/pdf/1512.02325.pdfMobileNet V1
https://arxiv.org/pdf/1704.04861.pdf
口罩贴纸的自动选择与定位
目前项目中包含了 24 个口罩贴纸素材和每个口罩的数据。对于每个口罩贴纸,在上面取三个关键点(左上角、右上角和下巴底部)作为特征信息,在检测出用户头像上的 68 个关键点以后,计算出和口罩同样位置的三个点的坐标,根据这些数据计算出与脸型最匹配的口罩贴纸,并反向计算出相应的几何变换,将贴纸放在头像上的合适位置。
这部分涉及的主要是一些解析几何知识,开发这个模块时费了一些草稿纸(实际上自从上次开发平面几何机器证明算法之后,我已经有些年没接触过这些了,这生疏感令人措手不及)。
平面几何机器证明算法
https://www.zhihu.com/question/64898551/answer/229772358
目前这个方法在匹配的精度上感觉还可以进一步提高,比如在口罩上多选几个特征点等等。但是目前口罩素材的数量也有限,丰富度不足,算法精度的提升对实际效果影响不会很大。
拥有贴纸编辑功能的图像编辑器
本项目的图像编辑器用 canvas 实现,在开发时主要参考了 npm 包 xl_canvas。但是由于该包不能直接使用,又进行了深度修改,添加了翻转、触摸支持、按原始分辨率导出等一系列功能,集成在项目中。
xl_canvas
https://www.npmjs.com/package/xl_canvas
图像编辑器
这个模块在开发过程中同样用到了不少解析几何和三角函数,在涉及到例如图层管理的时候有一种在开发微型 PS 的爽快感。Canvas 确实强大得无与伦比,但是水很深坑也很多。
最后放上本项目在 GitHub 上的链接,欢迎 Star,也欢迎各位大佬提出建议~
Github
https://github.com/zamhown/wear-a-mask
今年过了一个难忘的春节。虽然肺炎疫情如同洪水猛兽,但能得此机会静一静做些平常没机会做的小事也不是一件坏事。计算所的老师在学生群里发了一张图片鼓励大家,以此作为结尾,祝大家身体健康!
“哪吒头”—玩转小潮流