OpenCV实现人脸识别

摘要:
基于LBP的人脸检测器的基本思想与基于Haar的人脸检测器相似,但它比较像素亮度的直方图,例如边缘、角落和平坦区域的直方图。这些级联的分类检测器通常需要使用至少1000张独特的人脸图像和10000张非人脸图像进行训练。LBP的培训时间通常为几个小时,Haar的培训时间为一周。人脸预处理的目的是减少此类问题,并帮助提高整个人脸识别系统的可靠性。使用OpenCV提供的经过训练的眼睛检测器。

// 总结:OpenCV实现人脸识别
// 2016.2.12 by Huangtao
// 

主要有以下步骤:
1、人脸检测
2、人脸预处理
3、从收集的人脸训练机器学习算法
4、人脸识别
5、收尾工作


=================================================
人脸检测算法:
=================================================

基于Haar的脸部检测器的基本思想是,对于面部正面大部分区域而言,会有眼睛所在区域应该比前额和脸颊更暗,嘴巴
应该比脸颊更暗等情形。它通常执行大约20个这样的比较来决定所检测的对象是否为人脸,实际上经常会做上千次。
基于LBP的人脸检测器基本思想与基于Haar的人脸检测器类似,但它比较的是像素亮度直方图,例如,边缘、角落和平坦
区域的直方图。
这两种人脸检测器可通过训练大的图像集找到人脸,这些图像集在opencv中存在XML文件中以便后续使用。
这些级联分类检测器通常至少需使用1000个独特的人脸图像和10000个非人脸图像作为训练,训练时间一般LBP要几个小时,
Haar要一个星期。

项目中的关键代码如下:
initDetectors
faceCascade.load(faceCascadeFilename);
eyeCascade1.load(eyeCascadeFilename1);
eyeCascade2.load(eyeCascadeFilename2);

initWebcam
videoCapture.open(cameraNumber);

cvtColor(img, gray, CV_BGR2GRAY);
//有需要则缩小图片使检测运行更快,之后要恢复原来大小
resize(gray, inputImg, Size(scaledWidth, scaledHeight));
equalizeHist(inputImg, equalizedImg);
cascade.detectMultiScale(equalizedImg......);


=================================================
人脸预处理:
=================================================

实际中通常训练(采集图像)和测试(来自摄像机图像)的图像会有很大不同,受(如光照、人脸方位、表情等),
结果会很差,因此用于训练的数据集很重要。
人脸预处理目的是减少这类问题,有助于提高整个人脸识别系统的可靠性。

人脸预处理的最简单形式就是使用equalizeHist()函数做直方图均衡,这与人脸检测那步一样。
实际中,为了让检测算法更可靠,会使用面部特征检测(如,检测眼睛、鼻子、嘴巴和眉毛),本项目只使用眼睛检测。
使用OpenCV自带的训练好的眼部探测器。如,正面人脸检测完毕后,得到一个人脸,在使用眼睛检测器提取人脸的左眼区域
和右眼区域,并对每个眼部区域进行直方图均衡。

这步涉及的操作有以下内容:
1、几何变换和裁剪
人脸对齐很重要,旋转人脸使眼睛保持水平,缩放人脸使眼睛之间距离始终相同,平移人脸使眼睛总是在所需高度上水平居中,
裁剪人脸外围(如图像背景、头发、额头、耳朵和下巴)。

2、对人脸左侧和右侧分别用直方图均衡

3、平滑
用双边滤波器来减少图像噪声

4、椭圆掩码
将剩余头发和人脸图像背景去掉

项目中的关键代码如下:
detectBothEyes(const Mat &face, CascadeClassifier &eyeCascade1, CascadeClassifier &eyeCascade2,
Point &leftEye, Point &rightEye, Rect *searchedLeftEye, Rect *searchedRightEye);
topLeftOfFace = face(Rect(leftX, topY, widthX, heightY));
//在左脸区域内检测左眼
detectLargestObject(topLeftOfFace, eyeCascade1, leftEyeRect, topLeftOfFace.cols);
//右眼类似,这样眼睛中心点就得到了
leftEye = Point(leftEyeRect.x + leftEyeRect.width/2, leftEyeRect.y + leftEyeRect.height/2);
//再得到两眼的中点,然后计算两眼之间的角度
Point2f eyesCenter = Point2f( (leftEye.x + rightEye.x) * 0.5f, (leftEye.y + rightEye.y) * 0.5f );
//仿射扭曲(Affine Warping)需要一个仿射矩阵
rot_mat = getRotationMatrix2D(eyesCenter, angle, scale);
//现在可变换人脸来得到检测到的双眼出现在人脸的所需位置
warpAffine(gray, warped, rot_mat, warped.size());

//先对人脸左侧和右侧分开进行直方图均衡
equalizeHist(leftSide, leftSide);
equalizeHist(rightSide, rightSide);
//再合并,这里合并时左侧1/4和右侧1/4直接取像素值,中间的2/4区域像素值通过一定计算进行处理。

//双边滤波
bilateralFilter(warped, filtered, 0, 20.0, 2.0);

//采用椭圆掩码来删除一些区域
filtered.copyTo(dstImg, mask);


=================================================
收集并训练人脸:
=================================================

一个好的数据集应包含人脸变换的各种情形,这些变化可能出现在训练集中。如只测试正面人脸,则只需训练图像有完全正面人脸即可。
因此一个好的训练集应包含很多实际情形。
本项目收集的图像之间至少有一秒的间隔,使用基于L2范数的相对错误评价标准来比较两幅图像素之间的相似性。
errorL2 = norm(A, B, CV_L2);
similarity = errorL2 / (double)(A.rows * A.cols);
再与收集新人脸的阈值相比来决定是否收集这次图像。

可用很多技巧来获取更多的训练数据,如,使用镜像人脸、加入随机噪声、改变人脸图像的一些像素、旋转等。
//翻转
flip(preprocessedFace, mirroredFace, 1);

对每个人收集到足够多的人脸图像后,接下来必须选择适合人脸识别的机器学习算法,通过它来学习收集的数据,从而训练出一个人脸识别系统。

人脸识别算法:
1、特征脸,也称PCA(主成分分析)
2、Fisher脸,也称LDA(线性判别分析)
3、局部二值模式直方图(Local Binary Pattern Histograms,LBPH)
其他人脸识别算法:www.face-rec.org/algorithms/

OpenCV提供了CV::Algorithm类,该类有几种不同的算法,用其中一种算法就可以完成简单而通用的人脸识别。
OpenCV的contrib模板中有一个FaceRecognizer类,它实现以上这些人脸识别算法。
initModule_contrib();
model = Algorithm::create<FaceRecognizer>(facerecAlgorithm);

model->train(preprocessedFaces, faceLabels);
这一代码将执行所选人脸识别的整个训练算法。


=================================================
人脸识别:
=================================================

1、人脸识别:通过人脸来识别这个人
可以简单调用FaceRecognizer::predict()函数来识别照片中的人,
int identity = model->predict(preprocessedFace);
它带来的问题是它总能预测给定的人(即使输入图像不属于训练集中的人)。
解决此问题的办法是制定置信度标准,置信度过低则可判读是一个不认识的人。

2、人脸验证:验证图像中是否有想找的人
为了验证是否可靠,或者说系统是否能对一个不认识的人进行正确识别,这需要进行人脸验证。
这里计算置信度的方法是:
使用特征向量和特征值重构人脸图,然后将输入的图像与重构图进行比较。如果一个人在训练集中有多张人脸图,用特征向量和特征
值重构后应该有非常好的效果,如果没有则差别很大,表明它可能是一个未知的人脸。
subspaceProject()函数将人脸图像映射到特征空间,再用
subspaceReconstruct()函数从特征空间重构图像。


=================================================
收尾:交互式GUI
=================================================
利用OpenCV函数很容易绘制一些组件,鼠标点击等。

参考书籍:

《深入理解OpenCV 实用计算机视觉项目解析 》,这本书确实不错,里面相关项目也很多,写的也很好。

免责声明:文章转载自《OpenCV实现人脸识别》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇12-rm 命令总结MySQL 数据同步下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

OpenCV 2.4.9 学习笔记(1)—— 基本功能结构

一些关于OpenCV(2.4.9版本)的学习笔记,作为记录,以免自己忘了。 安装与配置   OpenCV的下载、安装以及在各个平台(Windows/Linux等)配置网上有很多的资料,自己就不用存了。需要或者遇到问题的时候再说。 基本模块结构   OpenCV(Open Source Computer Vision Library),一个遵循BSD协议的计...

python利用opencv去除水印方法

OpenCV(Open Source Computer Vision Library)是一个跨平台计算机视觉库,实现了图像处理和计算机视觉方面的很多通用算法 在python中可以利用opencv来去除水印 opencv安装 window10 OpenCV 3:http://www.lfd.uci.edu/~gohlke/pythonlibs/#opencv...

项目实战:Qt+OpenCV图像处理与识别算法平台

若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062本文章博客地址:https://blog.csdn.net/qq21497936/article/details...

人脸识别手机端APK分享 | 极速体验人脸识别功能 创建一个简单的人脸识别手机APP程序

1.前言 虹软公司提供免费离线人脸识别,对于开发者提供了比较友好、完整的可配置demo。但是如需直接体验功能,还是要花一点时间去完成项目编译、配置等一系列工作,对于初学者、不怎么熟悉整个项目的人来说可能会踩不少坑。 本文是基于虹软人脸识别SDK V3.0 Android Java的demo,封装后输出的一个简单的的APK程序,直接安装到手机即可体验功能,...

opencv视觉系统开发教程资料下载

opencv视觉系统开发教程资料下载 转 https://bbs.52iss.com/forum.php?mod=viewthread&tid=3995&extra=opencv对于编程绝对是一个好东西。opencv的意思是开放源代码计算机视觉类库(open source computer vision library),未来研究人工智能可...

MAC下Xcode配置opencv(2017.3.29最新实践,亲测可行)(转)

本文原创,未经同意,谢绝转载!(转载请告知本人并且经过本人同意--By Pacific-hong) 本人小硕一枚,因为专业方向图像相关,所以用到opencv,然后网上MAC下Xcode配置opencv的教程比较少,要不然就是过时了。所以在一番倒腾之后,成功配置了OpenCV。写下本文供他人参考,少走弯路。 一.版本介绍 首先介绍macOS,Xcode,Op...