引自:http://blog.csdn.net/linolzhang/article/details/55271815

人脸检测 早已比较成熟,传统的基于HOG+线性分类器 的方案检测效果已经相当不错,我们也不再过多讨论,本节重点讨论人脸特征点对齐,特征点对齐主要应用在确定关键点的位置上,并进一步用于人脸姿态或状态的判断(用在辅助驾驶、疲劳检测、AR等)。

下面介绍常用的人脸对齐算法

• ASM

ASM(Active Shape Model)是指主观形状模型,即通过形状模型 对 目标物体进行抽象。

ASM 是一种 基于点分布模型(Point Distribution Model, PDM)的算法。在PDM中,外形相似的物体,例如 人脸、人手、心脏等的几何形状可以通过若干关键特征点(landmarks)的坐标依次串联形成一个形状向量来表示。

基于ASM的人脸 通常通过 标定好的68个关键特征点 来进行描述:

ASM算法 分为 训练过程 和 搜索过程

一. ASM的训练:

1.1 搜集 T 个训练样本,样本数量根据需要(假定 T=100)

注:样本只需要包含人脸图像即可,大小和方向不需要限定(后续可以归一化)。

1.2 手动标记n个脸部特征点(假定 n=68)

需要配合标定软件将结果坐标存到文本文档。

1.3 构建形状向量

将记录下来的坐标点(坐标点二维位置信息x,y),按照顺序连成向量,每一个样本 描述为一个向量:

1.4 进行归一化和对齐(采用Procrustes方法)

可以看作是通过简单的 平移、旋转、缩放,在不改变点分布模型的基础上,将样本中多个人脸归一化到一个统一的标准。

这个统一的标准即为 平均脸

Procrusts归一化方法一般为使用一个四元数:旋转角度a, 缩放尺度s,水平位移x,  垂直位移y 。这里仅把他看作一个变化T,具体过程为:

(1)将训练集中的所有人脸模型对齐到第一个人脸模型(典型意义,可以自主选择);

(2)计算 平均人脸模型 X0;

(3)将所有样本模型对齐到平均人脸 X0,描述为: Xi = X0 + b (b为相对于平均脸的偏置);

任意的一个脸可以由平均脸和参数b来进行描述,参数b描述了平均脸到人脸的细微变化。

(4)重复(2)(3),直至X0收敛 或者到一定时间停止。

1.5 PCA降维

PCA 降维主要作用是降低非关键维度的影响,减少数据量、提高效果,这个过程并不是必须的。

1.6 为每个特征点构建局部特征

局部特征 用于在 特征点附近进行搜索(可以在特征点附近的矩形框搜索,也可以沿法线方向搜索),以迭代的方式寻找新的特征点匹配位置

为防止光照变化,局部特征一般采用梯度特征描述(当然也可以通过颜色、纹理等,可以参考后续AAM算法)。

对于第 i(<T)个样本,上图中的第k 个点(<n,图中k=29),沿着垂直于其相邻两个点连线(图中虚线)的垂直方向,两个各选择m个点,构成一个长度为2m+1的向量,对该向量所包含的像素灰度求导,得到一个局部纹理值 gik,对其他样本中对应点执行同样的操作,就得到第k个特征点对应的局部纹理 序列:

{ gi0, gi1, gi2, …gik…, gin }

我们用 均值 和 方差 来描述第 k 个特征点对应的局部特征:

特征点 与 样本特征的比对采用 马氏距离

二. ASM的搜索:

1.1 初始化对齐人脸

根据HOG人脸检测结果的大致人脸位置,将前面计算得到的平均脸 X0 进行仿射变换,得到一个初始的特征点模型:

X = M ( X0 ) + b

1.2 搜索特征点

a)针对每个特征点

在特征点邻域内进行 迭代搜索,通过局部特征点的特征匹配,获取新的特征点位置;

关于特征点搜索方式,有的方法沿着边缘的法线方向提取,有的方法在特征点附近的矩形区域提取,这里先不展开讨论。

通过特征点选择算法,选择多个 候选点候选点 采用上面同样的方法进行特征提取,然后与样本特征点模型进行匹配,匹配采用前面提到的马氏距离,距离最小的候选点即作为新的特征点中心。

b)采用 平均人脸模型 对匹配结果进行修正;

反复执行 (a)(b),直到收敛

用初始模型在新的图像中搜索目标形状,使搜索中的特征点和相对应的特征点最为接近,持续优化 b,计算最接近模型。

目前关于ASM 主要的工具包:

1. Asmlib-OpenCV

基于opencv2.0,比较老了,效果一般,起步学习用。

链接地址:https://github.com/cxcxcxcx/asmlib-opencv

2. stasm

准确度还可以,开源。

链接地址:https://github.com/juan-cardelino/stasm

• AAM

AAM 称为 主动外观模型(Active Appearance Model),AAM是在ASM的基础上,进一步对纹理(将人脸图像变换到平均形状 而得到的形状无关图像)进行统计建模,并将形状和纹理两个统计模型进一步融合为 外观模型。可以理解为:

Appreance = Shape + Texture

AAM 在对形状和纹理特征统一量纲后,建模和搜索过程和ASM基本相同。

• CLM

CLM 是有约束的局部模型(Constrained Local Model),它通过初始化平均脸的位置,然后让每个平均脸上的特征点在其邻域位置上进行搜索匹配来完成人脸点检测。前面讲到的ASM也属于CLM的一种。

CLM分别继承 ASM和AAM的优点,在ASM的效率 与 AAM的效果之间做了平衡。抛弃了AAM的全局纹理方法,在ASM的基础上,通过特征点周围的局部纹理Patch,提高了ASM仅仅依靠灰度 带来的匹配问题,引用一张老掉牙的图 说明原理:

CLM的关键在于约束(Constrains),有两个层面的意思:

1)我们的眼睛、鼻子、嘴巴 相对位置是明确的,你不需要到鼻子上面找嘴巴(这肯定是怪物对不对?),这些Patch的位置称为Shape Model;

2)对于每个Patch,对应一个Local Model,你只需要在限定的位置周围(Local Region)进行查找匹配即可;

• SDM

SDM 全名是 Supervised Descent Method,中文叫监督下降方法。

SDM 方法提出的背景就是为了更好的解决非线性优化问题,那么什么是非线性优化问题呢?非线性优化问题 就是约束条件或者目标函数是非线性的。

学界通常使用二阶导数的方法进行优化,比如牛顿法。

非线性最优化问题 通常有 2个难点:

(1)函数(方程)可能不可微,或者参数无法估计;

(2)Hessian不正定,或者维度太高导致计算量过大;


SDM 与其他方法不同的地方在于:牛顿法 每次迭代的步长 Δx 是计算得到的:

Δx =-Jf/H(参见上图牛顿法公式),也就是以 雅可比矩阵 除以 Hessian矩阵作为下降方向。

SDM 每次的步长 Δx = R * x,R是通过对样本训练得到的

也可以认为SDM的 步长 Δx 是通过样本学习的到 Hessian矩阵的逆 与 Jacobian矩阵的乘积 Jf/H。

OK,到这里我们知道了,SDM是一种优化方法,主要是用于目标函数的优化求解。和人脸对齐本身没什么关系,But 作者用这个方法,很好的解决了关键点的回归问题,取得了 State-Of-The-Art的效果。

//下面我给出 SDM 的推导过程:

人脸特征点检测的任务就是给定一张脸,然后标定出这张脸上的一些特征点。

如图,左边是手工标记的人脸特征点坐标,也就是人脸特征点任务中的最优解x∗,右边是初始化时的特征点坐标,记做x0。

建模

d(x)∈Rp∗1表示图片中的p个特征点坐标,h是每个特征点处的非线性特征提取函数,本文使用的特征是SIFT特征,也就是每个特征点要提取128维的SIFT特征,所以h(d(x))∈R128p∗1。由人工标定的最优解为x∗,在x∗处提取的SIFT特征可以记为ϕ∗=h(d(x∗))。由此,人脸特征点检测可以看做,求使得下列函数最小的Δx:

f(x0+Δx)=∥h(d(x0+Δx))−ϕ∗∥2

无论是牛顿法还是SDM,在这里需要做的是,得到一系列的方向和步长Δx

xk+1=xk+Δxk

将特征点从初值x0收敛到最小值x∗。

对于这一问题,牛顿法的解答是:

xk=xk−1−2H−1JTh(ϕk−1−ϕ∗)

而SDM对此的解答是

xk=xk−1+Rk−1ϕk−1+bk−1

这里的Rk和bk就代表了每次迭代的路径,两个值都要从训练数据中得到。对比两个式子可以发现,两个式子的差异在于迭代步长的选择,牛顿法是通过计算得到,而SDM是从训练集中训练得到。

SDM训练

SDM需要从训练集中得到Rk和bk。训练时,人脸图片集为{di},与此对应的手工标定的特征点为{xi∗}。每张图片的初始特征点为x0,这样人脸特征点定位就变成了一个线性回归问题,回归问题的目标是从x0到x∗迭代的步长Δxi∗=xi∗−xi0(训练集中是已知的),这个回归问题的输入特征就是在x0处的SIFT特征ϕi0。这样,套用线性回归问题就可以得到目标函数:

argminR0,b0∑di∥Δxi∗−R0ϕi0−b0∥2

这样就从训练集中得到了R0和b0。这里是得到了第一次迭代的系数R0和b0,相同的方法可以得到第k次迭代的系数Rk和bk

argminRk,bk∑di∥Δxki∗−Rkϕik−bk∥2

这样,就可以从训练集中得到每次迭代的参数Rk和bk。

结果

本文在当时取得了state-of-the-art的结果。与之前的方法相比,本文结果的RMS error提升明显。

总结

这篇文章将人脸特征点检测问题建模为一个回归问题。通过训练集得到每次迭代的步长参数,而在实际测试时,只需要根据当前特征点处的局部特征,不断迭代就可以得到最终的特征点位置。

人脸特征点检测问题需要关注两个方面:一是特征点处的局部特征提取方法,二是回归算法。比如MSRA在CVPR2014上发表的论文《Face Alignment at 3000FPS via Regressing Local Binary Features》,使用了一种名为LBF的局部特征提取方法,回归模型使用了随机森林。而在CVPR2014的另一篇论文《One Millisecond Face Alignment with an Ensemble of Regression Trees》使用了correlation baed feature selection(EF+CB),回归模型使用了Ensemble of Regression Trees。这类方法可以统称为shape regression approach。

特征点处的局部特征提取也可以看做是人脸的一种特征表示,现在的基于深度学习的方法可以看做是先使用神经网络得到人脸特征表示,然后使用线性回归得到点坐标。

 
 

机器学习----人脸对齐的算法-ASM.AAM..CLM.SDM的更多相关文章

  1. 人脸Pose检测:ASM、AAM、CLM总结

    人脸的Pose检测可以使用基于位置约束的特征点的方法.人脸特征点定位的目的是在人脸检测的基础上,进一步确定脸部特征点(眼睛.眉毛.鼻子.嘴巴.脸部外轮廓)的位置.定位算法的基本思路是:人脸的纹理特征和 ...

  2. 机器学习--详解人脸对齐算法SDM-LBF

    引自:http://blog.csdn.net/taily_duan/article/details/54584040 人脸对齐之SDM(Supervised Descent Method) 人脸对齐 ...

  3. MTCNN算法与代码理解—人脸检测和人脸对齐联合学习

    目录 写在前面 算法Pipeline详解 如何训练 损失函数 训练数据准备 多任务学习与在线困难样本挖掘 预测过程 参考 博客:blog.shinelee.me | 博客园 | CSDN 写在前面 主 ...

  4. 基于机器学习人脸识别face recognition具体的算法和原理

    引自:http://blog.csdn.net/eclipsesy/article/details/78388468?utm_source=debugrun&utm_medium=referr ...

  5. 揭秘人脸对齐之3D变换-Java版(文末赋开源地址)

    一.人脸对齐基本概念 人脸对齐通过人脸关键点检测得到人脸的关键点坐标,然后根据人脸的关键点坐标调整人脸的角度,使人脸对齐,由于输入图像的尺寸是大小不一的,人脸区域大小也不相同,角度不一样,所以要通过坐 ...

  6. 基于Landmark的人脸对齐以及裁剪方法

    利用Landmarks进行人脸对齐裁剪是人脸检测中重要的一个步骤.效果如下图所示: 基本思路为: a.人脸检测 人脸的检测不必多说了,基本Cascade的方式已经很不错了,或者用基于HOG/FHOG的 ...

  7. 人脸对齐SDM原理----Supervised Descent Method and its Applications to Face Alignment

    最近组里研究了SDM算法在人脸对齐中的应用,是CMU的论文<Supervised Descent Method and its Applications to Face Alignment> ...

  8. 机器学习六--K-means聚类算法

    机器学习六--K-means聚类算法 想想常见的分类算法有决策树.Logistic回归.SVM.贝叶斯等.分类作为一种监督学习方法,要求必须事先明确知道各个类别的信息,并且断言所有待分类项都有一个类别 ...

  9. 机器学习之K近邻算法(KNN)

    机器学习之K近邻算法(KNN) 标签: python 算法 KNN 机械学习 苛求真理的欲望让我想要了解算法的本质,于是我开始了机械学习的算法之旅 from numpy import * import ...

随机推荐

  1. MFC添加自定义窗口消息

    原文链接: http://www.cnblogs.com/smartvessel/archive/2011/07/18/2109472.html 1. 在头文件stdafx.h中增加一个自定义消息宏 ...

  2. C#中const 详细分析与说明

    const是一个c语言的关键字,它限定一个变量不允许被改变.使用const在一定程度上可以提高程序的安全性和可靠性,另外,在观看别人代码的时候,清晰理解const所起的作用,对理解对方的程序也有一些帮 ...

  3. django -- 为model 指定数据库名

    一.为model指定数据库名: django自己实现的ORM中.如果要指定一个model的表名是通过Meta类来实现的. from django.db import models # Create y ...

  4. mongodb 远程访问配置

    1.首先修改mongodb的配置文件 让其监听所有外网ip 编辑文件:/etc/mongodb.conf 修改后的内容如下: bind_ip = 0.0.0.0 port = 27017 auth=t ...

  5. 怎么在eclipse中安装svn插件

    Subclipse   Subclipse is an Eclipse Team Provider plug-in providing support for Subversion within th ...

  6. HTTP报文头Accept和Content-Type总结

    1.Accept属于请求头, Content-Type属于实体头. Http报头分为通用报头,请求报头,响应报头和实体报头. 请求方的http报头结构:通用报头|请求报头|实体报头 响应方的http报 ...

  7. RDD转换DataFrame

    Spark SQL有两种方法将RDD转为DataFrame. 1. 使用反射机制,推导包含指定类型对象RDD的schema.这种基于反射机制的方法使代码更简洁,而且如果你事先知道数据schema,推荐 ...

  8. HTML常用模板:用DIV实现网站首页、后台管理首页(整理)

    1. 说明 网上下载的模板,用DIV实现页面模块之间的分隔(不是用frameset/frame).可以选择有无header/menu/footer,主体如何等等.删除了几个我认为重复的.重新命名而已. ...

  9. git add 不必要的文件 如何撤回

    [root@666 IT-DOC]# git status -s ?? a.txt [root@666 IT-DOC]# git add a.txt [root@666 IT-DOC]# git st ...

  10. 不忘初心,回归本质 .net core

    static void Main(string[] args) { ; object j = i;//装箱 就是把值类型转换成引用类型 int k = (int)j;//拆箱 就是把引用类型转换成值类 ...