看了很长一段时间的opencv,以前都是使用opencv时看看,现在对图像识别背后的一大堆的数学知识感到了非常的敬佩。
首先是获取一张脸作为训练数据,这就是要求门禁管理员把自己的面部无表情的时刻录下来。
接着确定两张脸的相似性,分为如下几个步骤:
1,人脸检测,找到图像中人脸所在的位置,经典方法为haar+adaboost;
2,脸部特征点定位,包括眼球中心点,还可以进一步包括脸颊等轮廓特征点,经典方法包括基于haar+adaboost的眼睛定位,和asm等alignment方法等;
3,人脸几何归一化,根据脸部特征点位置从图像中得到归一化的人脸区域图像,这一步主要是使得不同人脸上的像素对应的人脸位置一致,这样才有可比性,这个步骤可以看作是一个对图像进行仿射变化的过程;
4,人脸光照归一化,主要目的是克服不同光照对人脸的影响,提高算法对光照条件的鲁棒性,预处理方法很多,自商,或者DOG等方法效果较好;
5,人脸表示(特征提取),比如gabor特征和上述的lbp特征,常常会对多种特征进行融合;
6,鉴别特征提取,就是将高维的人脸特征映射到分类能力更强的低维特征,成熟的思路是PCA+LDA的方法;
7,计算两个脸得到的鉴别特征之间的距离,作为相似度衡量,距离最经典的是cos距离;
俗语说,不怕贼偷,不怕贼抢,就怕贼惦记,如果一个人发现另外一个有钱人使用人脸识别门禁系统,他花几十万去韩国整个容,结局也未可知,所以,成熟的产品还要加上语音识别。
接着就是算法的主要内容了:
A.算法的训练阶段
主要需要经过如下的几步:
(1) 需要一个训练人脸照片集。
(2) 在训练人脸照片集上计算特征脸,即计算特征值,保存最大特征值所对应的的M 张图片。这M 张图片定义了"特征脸空间"(原空间的一个子空间)。当有新的人脸添加进来时,这个特征脸可以进行更新和重新计算得到。
(3) 在"特征脸空间"上,将要识别的各个个体图片投影到各个轴(特征脸)上,计算得到一个M 维的权重向量。简单而言,就是计算得到各个个体所对应于M 维权重空间的坐标值。
OpenCV 实现为:先用cvLoadImage()载入图片并利用cvCvtcolor()转换为灰度图片,建立自定义的迭代标准CvTermCriteria,调用cvCalcEigenObjects()进行PCA 操作,计算出的Eigenface 都存放在向量组成的数组中,利用cvEigenDecomposite()将每一个训练图片投影在PCA 子空间(eigenspace)上,结果保存在矩阵数组中,用cvWrite将训练结果保存至XML文件中。
B.算法的身份识别阶段
在识别新的人脸图片时,具体的操作方法流程如下:
(1) 基于前面得到的M 个特征脸,将新采集的图片投影到各个特征脸,计算得到一个权重集合(权重向量)。
(2) 判断新图片是否是一幅人脸图像,即通过判断图像是否足够靠近人脸空间。
(3)如果是人脸图像,则根据前面计算的权重集合(权重向量),利用权重模式将这个人脸分类划归到初始时计算得到的各个个体或者是成为一个新的个体照片。简单而言,就是计算新权重到原来各个个体权重的距离,选择最近的,认为是识别成这个个体;如果最近的距离超出阈值,则认为是一个新的个体。
(4) 更新特征脸或者是权重模式。
(5)如果一个未知的人脸,出现了很多次,也就意味着,对这个人脸没有记录,那么计算它的特征权重(向量),然后将其添加到已知人脸中[6].
OpenCV 实现调用cvRead加载训练结果XML 文件,调cvEigenDecomposite()将采集图片映射至PCA 子空间,利用最近距离匹配方法SquaredEuclidean Distance,计算要识别图片同每一个训练结果的距离,找出距离最近的即可。
之前之所以加上了要求门禁管理员把自己的面部无表情的时刻录下来,是因为没有使用表情识别,表情识别,也是一个部分:
脸部表情识别
脸部运动跟踪利用了Camshift 算法,该算法利用目标的颜色直方图模型将图像转换为颜色概率分布图,初始化一个搜索窗的大小和位置,并根据上一帧得到的结果自适应调整搜索窗口的位置和大小,从而定位出当前图像中目标的中心位置。
Camshift 能有效解决目标变形和遮挡的问题,对系统资源要求不高,时间复杂度低,在简单背景下能够取得良好的跟踪效果。
Camshift 的OpenCV 实现分以下几步:
(1)调用cvCvtColor()将色彩空间转化到HSI 空间,调用cvSplit()获得其中的H 分量。
(2) 调用cvCreateHist()计算H 分量的直方图,即1D 直方图。
(3) 调用cvCalcBackProject()计算Back Projec
tion.
(4) 调用cvCamShift()输出新的Search Window 的位置和面积。
我们利用光流算法评估了两帧图像的之间的变化,Lucas–Kanade 光流算法是一种两帧差分的光流估计算法。它计算两帧在时间t 到t +δt 之间每个每个像素点位置的移动。是基于图像信号的泰勒级数,就是对于空间和时间坐标使用偏导数。
首先要用到shi-Tomasi 算法,该算法主要用于提取特征点,即图中哪些是我们感兴趣需要跟踪的点,对应函数为cvGoodFeaturesToTrack(),可以自定义第一帧特征点的数目,函数将输出所找到特征值。接下来是cvCalcOpticalFlowPyrLK 函数, 实现了金字塔中Lucas-Kanade 光流计算的稀疏迭代版本。它根据给出的前一帧特征点坐标计算当前视频帧上的特征点坐标。输入参数包括跟踪图像的前一帧和当前帧,以及上面函数输出的前一帧图像特征值,自定义的迭代标准,输出所找到的当前帧的特征值点。这些点可以确定面部局部区域的特征如眼部,鼻子高度与宽度,嘴部两侧与底部的夹角等等,利用与前一帧的特征比较,可得出反应脸部动态变化的参数,这些数据可以与脸部的一些简单表情相关联。