前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >明月机器学习系列017:人脸对齐与仿射变换

明月机器学习系列017:人脸对齐与仿射变换

作者头像
明月AI
发布2021-10-28 09:58:31
3.5K0
发布2021-10-28 09:58:31
举报
文章被收录于专栏:野生AI架构师

我们所说的人脸识别通常是几个算法的集合,包括人脸检测,人脸对齐,人脸特征提取等。人脸检测就是从输入的图片中识别出人脸box和关键点,效果如下图:

我们现在使用的模型实现人脸检测,在2080TI上,大概13帧每秒,慢是慢了点,不过胜在精度比较高,如上图所示,都能正确识别,关键点也很准确。这是人脸检测。 在人脸检测之后,如果我们需要做人脸比对或者匹配,通常就需要先进行人脸对齐,这样在提取特征会更有效。所谓人脸对齐,其实就是将原来倾斜等的人脸转换成端正的。如下图:

左图就是原图,而纠正之后的头像应该类似右图。原来的人脸对齐算法是从一个开源项目里拿来用的,因为效果还可以,所以就一直用着,最近发现这个算法有点问题,才抽时间这个算法撸了一遍。

人脸对齐


现在我们有一个人脸的box及其关键点,怎么进行对齐呢?

这里其实就是将人脸的5个关键点,通过某种映射,通常是线性变换,映射成一个标准的人脸,5个原始关键点:

代码语言:javascript
复制
X = [
    [828.1219482421875, 356.0898132324219],
    [901.5404052734375, 369.9261779785156],
    [844.2774047851562, 405.2549133300781],
    [820.4654541015625, 441.8576965332031],
    [874.6876831054688, 454.26739501953125]
]

标准的人脸关键点坐标是这样的:

代码语言:javascript
复制
Y = [
    [30.2946, 51.6963],
    [65.5318, 51.5014],
    [48.0252, 71.7366],
    [33.5493, 92.3655],
    [62.7299, 92.2041]
]

从X映射到Y,其实就是需要找到一个矩阵M,使得:

代码语言:javascript
复制
Y = M*X

这里的矩阵M就是我们要找的变换矩阵,只要找到一个M,那么对于原图像中的所有点,都能找到对应的映射点。

Python实现


Python实现其实很简单,代码如下:

代码语言:javascript
复制
import numpy as np
from skimage import transform

X, Y = np.array(X), np.array(Y)
tform = transform.SimilarityTransform()
# 程序直接估算出转换矩阵M
tform.estimate(X, Y)
M = tform.params[0:2, :]

打印M的输出如下:

代码语言:javascript
复制
array([[ 4.62207723e-01,  9.64380058e-02, -3.85718987e+02],
       [-9.64380058e-02,  4.62207723e-01, -3.31742763e+01]])

这就是转换矩阵。如果是人脸截取的话,还差最后一步:

代码语言:javascript
复制
# 截取一个112*112的头像
import cv2
warped = cv2.warpAffine(img, M, (112, 112), borderValue=0.0)

至于是怎么估算转换矩阵M的,这里涉及到SVD分解(SVD就像一个幽灵,是不是就会跑出来),有机会可以写一篇。

展示一下人脸纠正后的效果:

感觉对于侧脸的对齐效果不太好,会有点偏,有时间再优化优化。

仿射变换


Python解决问题很简单,不过我们有必要认识一下其背后的仿射变换。其在百科上的定义如下: 仿射变换,又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。 更加严谨的定义如下:

简单说:仿射变换 = 线性变换 + 平移。(注意不是平移+线性变换)

平移变换

平移变换其实就是所有点都向同一个方向移动一个距离,例如对于平面内的任意点(x, y):

代码语言:javascript
复制
new_x = x + e
new_y = y + f
代码语言:javascript
复制
如果使用矩阵来表示,这个需要使用增广矩阵的形式:

线性变换

所谓线性变换如下:

显然线性变换有一个明显的特征就是,无论怎么变,原点始终不变,就是如果输入的是原点(0,0),则输出的必定是(0,0)。 不过如果这样,我们无法跟平移叠加,需处理成增广矩阵的形式:

这样线性变换和平移变换就能叠加了。计算也不复杂,就是线性变换的矩阵乘以平移矩阵,最后的结果如下:

注意这里是先做线性变换,再平移,如果把他们交换顺序,其结果是不一样的。 简化表示:

等价于:

其中仿射变换矩阵为:

因为最后一行的格式都是固定的,前面是0,最后一个1,所以前面Python实现时得到的变换矩阵并没有最后一行。

仿射变换的一个可视化理解


图片来自 https://www.cnblogs.com/shine-lee/p/10950963.html ps: 1. skimage的接口说明:https://cloud.tencent.com/developer/section/1415102#stage-100055709

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-12-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 野生AI架构师 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 我们所说的人脸识别通常是几个算法的集合,包括人脸检测,人脸对齐,人脸特征提取等。人脸检测就是从输入的图片中识别出人脸box和关键点,效果如下图:
    • 人脸对齐
      • 现在我们有一个人脸的box及其关键点,怎么进行对齐呢?
        • Python实现
          • Python实现其实很简单,代码如下:
            • 仿射变换
              • 线性变换
            • 仿射变换的一个可视化理解
            相关产品与服务
            人脸识别
            腾讯云神图·人脸识别(Face Recognition)基于腾讯优图强大的面部分析技术,提供包括人脸检测与分析、比对、搜索、验证、五官定位、活体检测等多种功能,为开发者和企业提供高性能高可用的人脸识别服务。 可应用于在线娱乐、在线身份认证等多种应用场景,充分满足各行业客户的人脸属性识别及用户身份确认等需求。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档