OpenCV项目实战---人脸检测

OpenCV是一个强大的图像处理库 , 包含各种功能 。人脸识别只是其众多应用的其中一个 。
 
本篇文章与上一篇所讲述的知识有很大的重合  , 请按需观看 。
 
理论知识
 
计算机的视觉系统 , 计算机通过摄像头看到的 , 简单来说 , 就是一堆由数字组成的矩阵 。这些数字表明了物体发出的光的强弱 , 摄像头的光敏元件将光信号转化成数字信号 , 将其量化为矩阵 。
 
计算机中的彩色图片都是由若干个色彩通道累积出来的 , 比如RGB模式的图片 , 这三个通道都是灰度图 , 比如一个点由8位来表示 , 则一 个通道可以表示2^8=256个灰度 。那样三个通道进行叠加以后可以表3*8=24位种色彩 。
 
对这样的图片做处理 , 无疑是一件很复杂的事 , 所以有必要先将彩色图转为灰度图 , 那样可以减少数据量(比如RGB模式 , 可以减少到原图片的1/3) , 同时可 以去掉一些噪声信号 。先将图片转化为灰度图 , 然后将这个灰度图的对比度增高 , 这样可以使得图片本来暗的地方更暗 , 亮的地方更亮一些 。这样处理以后 , 图片就更容易被算法识别出来了 。
 
Haar特征
 
Haar特征包含三种:边缘特征、线性特征、和中心围绕特征 。

OpenCV项目实战---人脸检测

文章插图
 

OpenCV项目实战---人脸检测

文章插图
 
Haar特征提取流程图
在OpenCV人脸检测中 , Haar特征分类器就是一个XML文件 , 该文件中会描述人体各个部位的Haar特征值 。包括人脸、眼睛、嘴唇等等 。
 
HOG (Histograms of Oriented Gradients)
对于一张待检测图片 , 我们分析每个像素以及其周围的像素 , 根据明暗度画一个箭头 , 箭头的指向代表了像素逐渐变暗的方向 , 如果我们重复操作每一个像素 , 最终像素会被箭头取代 。这些箭头被称为梯度(gradients) , 它们能显示出图像从明亮到黑暗流动的过程 。
OpenCV项目实战---人脸检测

文章插图
 
分析每个像素对我们来说太过细节化了 , 像素过多不利于整体的分析 , 我们应该从更高的角度观察明暗的流动 。为此我们将图像分割成16x16像素的小方块 。在每个小方块中 , 计算出每个主方向有多少个梯度(有多少指向上 , 指向右上 , 指向右等) 。然后用指向性最强的那个方向箭头来代替原来那个小方块 。
OpenCV项目实战---人脸检测

文章插图
 
最终结果 , 我们把原始图像转换成非常简单的HOG图像 , 它可以很轻松的捕获面部的基本结构 。为了在HOG图像中找到脸部 , 我们需要做的是 , 与已知的一些HOG图案中 , 来寻找看起来最相似的部分 。
这些HOG图案都是从其他面部训练数据中提取出来的 。
 
级联分类器
对于本次的设计人脸检测 , 可以说是一次机器学习的过程 。级联分类器中有一个级联分类函数 , 此函数当中的一些参数就是由机器训练得到的 。对于人脸识别 , 计算机通过大量带人脸和不带人脸的图片 , 对人脸上的几万个特征 , 通过机器学习找出人脸分类效果最好、错误率最小的特征 。训练开始时 , 所有训练集中的图片具有相同的权重 , 对于被分类错误的图片 , 提升权重 , 重新计算出新的错误率和新的权重 。直到错误率或迭代次数达到要求 。这种训练方法叫做Adaboost 。
上文提到的hog图像 , 正是由adaboost训练方法对大量图片进行训练后所提取出来的 。
 
Cascade级联分类器
Cascade 译为级联 , 阶梯 。cascade级联分类器是一种基于Haar特征的有效的物体检测方法 。
 
一张图片绝大部分的区域都不是人脸 。如果对一张图片的每个角落都提取6000个特征 , 将会浪费巨量的计算资源 。
如果能找到一个简单的方法能够检测某个窗口是不是人脸区域 , 如果该窗口不是人脸区域 , 那么就只看一眼便直接跳过 , 也就不用进行后续处理了 , 这样就能集中精力判别那些可能是人脸的区域 。为此 , 有人引入了Cascade 分类器 。它不是将6000个特征都用在一个窗口 , 而是将特征分为不同的阶段 , 然后一个阶段一个阶段的应用这些特征(通常情况下 , 前几个阶段只有很少量的特征) 。如果窗口在第一个阶段就检测失败了 , 那么就直接舍弃它 , 无需考虑剩下的特征 。如果检测通过 , 则考虑第二阶段的特征并继续处理 。如果所有阶段的都通过了 , 那么这个窗口就是人脸区域 。


推荐阅读