工作总结:用OpenCV和Dlib(C++ ML库)进行换脸

临近开学,实习也接近尾声了。两个月的时间里,感觉还是干了点微不足道的贡献的。老大看我会点C++和视觉,就让我做一个换脸的项目,场景是演示看吸毒后人脸的变化。从项目研发到上线交付,也算是完成了一个实际的商业项目,对我自己而言意义重大。那么在这里就做个工作总结吧 : )

摄影于华南理工大学

初始化

由于初始化的速度比较慢,所以在构造函数里一开始直接开一个子线程,子线程负责初始化摄像头,构造函数后续负责初始化ui。(这里没有使用线程同步,但实测中暂时没有出现问题)。

人脸检测

项目涉及到人脸检测人脸特征点检测。一开始版本的人脸检测使用的是OpenCV提供的人脸检测器。OpenCV提供的人脸检测器基于haar特征和adaboost分类器(也提供了LBP特征,但一般用haar),比较传统,效果一般,尤其侧脸的检测比较糟糕,但优点是比较快,每一帧都进行检测也不会感到卡顿。现版本使用的是机器学习库Dlib提供的人脸检测器。Dlib使用的人脸检测器基于HOG(方向梯度直方图,Histogram of Oriented Gradient)特征,并使用线性分类器。Dlib提供的人脸检测器对侧脸的检测效果很好,但速度要慢一些,在我的机器上(i7-7700 & GTX1060)略有卡顿,但几帧进行一次检测还是比较流畅的。

在OpenCV3.3.1版本及以后,提供了DNN模块(Deep Neural Networks),预训练了基于深度学习的人脸检测器。新的人脸检测器使用SSD作为检测网络,ResNet作为分类网络(OpenCV’s deep learning face detector is based on the Single Shot Detector (SSD) framework with a ResNet base network)。Dlib中也有基于深度学习的人脸检测器,原理是使用基于CNN的功能的最大边距对象检测器(MMOD)。当然出于速度考虑,这里并没有使用深度学习的方法。

OpenCV预训练了人脸检测的caffe模型

References:
OpenCV人脸检测例程
OpenCV-DNN github项目
Face detection with OpenCV and deep learning
Dlib 人脸检测例程
Dlib dnn_mmod_face_detection例程
opencv_deeplearning实战1:基于深度学习的opencv人脸检测
人脸检测学习笔记(数据集-DLIB人脸检测原理-DLIB&OpenCV人脸检测方法及对比)

人脸特征点检测

人脸特征点检测(Facial landmark detection)是人脸检测过程中的一个重要环节。是在人脸检测的基础上进行的,对人脸上的特征点例如嘴角、眼角等进行定位。现在很多美颜APP的一些特效功能,比如说加一副眼镜,P上一个鹿的鼻子之类的操作,都是基于人脸特征点检测算法。对于换脸而言,人脸特征点的检测更是重中之重。由于要展现出吸毒之后人的病态,要进行瘦脸操作。利用特征点进行瘦脸应该会比使用坐标映射变换的方式要更自然一些。

传统方法是使用人脸检测+坐标变换

Dlib中提供了人脸关键点检测的预训练检测器,参考的论文是:One Millisecond Face Alignment with an Ensemble of Regression Trees by Vahid Kazemi and Josephine Sullivan, CVPR 2014。论文里使用的是基于树结构的级联回归器,实现出来的效果良好。Dlib预训练的检测器可以得到68个特征点,结构如下

68个特征点,但不包括额头

对于我刚才提到的一些应用,比如P个鼻子P个眼镜这样的操作,这些点够用了。然而项目中需要换上整张脸,所以还需要额头部位的特征点。一位硅谷的工程师训练了81个点的人脸特征点检测器,包括额头的部位。

硅谷小哥train的81点检测器

这位小哥的初衷是好的,但检测器的效果一般,标记的点会不太准确,估计是训练集的原因(Dlib预训练的.dat文件有100M,这位小哥的.dat文件只有20多M)。没办法,train是不可能自己train的,只好自己跟据68点的位置,根据人脸比例构造出额头的辅助点来进行换脸了。这里我构造了11个额头点,虽然会超出人脸的范围,但可以根据后续的算法来处理。

根据原来的68点瞎构造几个

References:
Dlib face_landmark_detection官方例程
Android:修图技术之瘦脸效果的实现(drawBitmapMesh)
Dlib 81点人脸特征点检测器github
One Millisecond Face Alignment with an Ensemble of Regression Trees by Vahid Kazemi and Josephine Sullivan, CVPR 2014。

肤色分割

前面说到,构造出来的额头点会超出人脸的范围,这样会导致换脸的结果是把头发都弄成皮肤了。另一方面,有可能会有刘海的情况,毕竟不是所有人都光着大脑门的。所以,要使用肤色检测来作为换脸过程中的掩膜,来避免头发也变成皱巴巴的皮肤的情况。

肤色检测的方法很多,我这里使用的是基于椭圆皮肤模型的皮肤检测。经过前人学者大量的皮肤统计信息可以知道,如果将皮肤信息映射到YCrCb空间,则在CrCb二维空间中这些皮肤像素点近似成一个椭圆分布。因此如果我们得到了一个CrCb的椭圆,下次来一个坐标(Cr, Cb)我们只需判断它是否在椭圆内(包括边界),如果是,则可以判断其为皮肤,否则就是非皮肤像素点。

肤色检测+分割

实际项目中,可以把这个椭圆的面积弄大一些,这样分割的条件会宽松一些。也可以弄小一些,看实际需求。

Reference:
OpenCV探索之路(二十七):皮肤检测技术

三角剖分

Delaunary三角剖分发明于1943年的一项技术,这种方式使空间中点连接成为三角形组,并且使这些三角形中最小的角取得最大值。这意味着Delaunary三角剖分在将点连接成为三角形的同时试图避免产生狭长的三角形。生成三角剖分的算法有很多,也比较复杂,实际使用中调用接口即可。

Delaunary三角剖分

我们这里需要做的,是把整张脸换过去,而不是单纯地在特征点附近P上一些特效。所以,在检测到人脸特征点以后,需要对特征点进行三角剖分(包括原图和被换脸的图片),然后使用几何变换和像素加权融合的方式,才能真正完成。

透视变换+加权融合

References:
OpenCV——Delaunay三角剖分
Learning OpenCV3 Adrian Kaehler & Gary Bradski 附录A平面划分

瘦脸算法

继续说下前面讲到的瘦脸操作。瘦脸的方式有很多,在本项目中,由于前面已经完成了人脸特征点的检测以及三角区域的剖分,那么利用区域变形(透视变换)的方式进行瘦脸的方式很自然就能够想到,具体的操作就是让下巴上的点往鼻子缩。

这里我并没有刻意去参考一些博客和论文,不过大概看了看跟这篇 Image Deformation Using Moving Least Squares里的思想比较类似。

坐标变换

Reference:
Image deformation using moving least squares. Scott Schaefer, Travis McPhail, Joe D. WarrenPublished in ACM Trans. Graph. 2006

最后

出来被社会毒打了两个月,还是有些收获的 - -!终于要恢复自由身了,真开心。但接下来的秋招还要继续努力啊 :) 。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352

推荐阅读更多精彩内容