OpenCV实现人脸识别


Posted in Python onApril 07, 2017

主要有以下步骤:

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函数很容易绘制一些组件,鼠标点击等。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Python 相关文章推荐
Python脚本实现下载合并SAE日志
Feb 10 Python
Python脚本实现DNSPod DNS动态解析域名
Feb 14 Python
Python手机号码归属地查询代码
May 04 Python
python snownlp情感分析简易demo(分享)
Jun 04 Python
Python+matplotlib实现华丽的文本框演示代码
Jan 22 Python
Python中的pack和unpack的使用
Mar 12 Python
Python实现调用另一个路径下py文件中的函数方法总结
Jun 07 Python
python实现简易内存监控
Jun 21 Python
在python中获取div的文本内容并和想定结果进行对比详解
Jan 02 Python
使用python实现下载我们想听的歌曲,速度超快
Jul 09 Python
Python 多线程C段扫描、检测 Ping扫描脚本的实现
Sep 03 Python
宝塔更新Python及Flask项目的部署
Apr 11 Python
python使用opencv进行人脸识别
Apr 07 #Python
Python 实现链表实例代码
Apr 07 #Python
python中如何使用朴素贝叶斯算法
Apr 06 #Python
python获取当前运行函数名称的方法实例代码
Apr 06 #Python
python爬取w3shcool的JQuery课程并且保存到本地
Apr 06 #Python
使用Python对SQLite数据库操作
Apr 06 #Python
使用Python对MySQL数据操作
Apr 06 #Python
You might like
php数组函数序列之array_values() 获取数组元素值的函数与方法
2011/10/30 PHP
php使用post数组的键值创建同名变量并赋值的方法
2015/04/03 PHP
Laravel框架控制器的request与response用法示例
2019/09/30 PHP
JavaScript 高级篇之DOM文档,简单封装及调用、动态添加、删除样式(六)
2012/04/07 Javascript
js读取json的两种常用方法示例介绍
2014/10/19 Javascript
原生JS实现LOADING效果
2015/03/16 Javascript
JavaScript保存并运算页面中数字类型变量的写法
2015/07/06 Javascript
Jquery实现遮罩层的简单实例(就是弹出DIV周围都灰色不能操作)
2016/07/14 Javascript
javascript 操作cookies详解及实例
2017/02/22 Javascript
关于Sequelize连接查询时inlude中model和association的区别详解
2017/02/27 Javascript
基于JavaScript实现的快速排序算法分析
2017/04/14 Javascript
详解vue.js之绑定class和style的示例代码
2017/08/24 Javascript
JavaScript学习笔记之惰性函数示例详解
2017/08/27 Javascript
详解Node使用Puppeteer完成一次复杂的爬虫
2018/04/18 Javascript
JS重学系列之聊聊new操作符
2019/03/04 Javascript
node.js实现带进度条的多文件上传
2020/03/27 Javascript
js实现的订阅发布者模式简单示例
2020/03/14 Javascript
python中对list去重的多种方法
2014/09/18 Python
wxPython事件驱动实例详解
2014/09/28 Python
python中实现将多个print输出合成一个数组
2018/04/19 Python
解决安装tensorflow遇到无法卸载numpy 1.8.0rc1的问题
2018/06/13 Python
使用python+whoosh实现全文检索
2019/12/09 Python
对Python中 \r, \n, \r\n的彻底理解
2020/03/06 Python
keras model.fit 解决validation_spilt=num 的问题
2020/06/19 Python
如何在Canvas中添加事件的方法示例
2019/05/21 HTML / CSS
学校经典推荐信
2013/10/30 职场文书
记者岗位职责
2014/01/06 职场文书
素食餐饮项目创业计划书
2014/02/02 职场文书
生产部厂长职位说明书
2014/03/03 职场文书
秋季运动会演讲稿
2014/09/16 职场文书
防灾减灾宣传标语
2014/10/07 职场文书
2016中秋节问候语
2015/11/11 职场文书
《失物招领》教学反思
2016/02/20 职场文书
九年级语文教学反思
2016/03/03 职场文书
解析高可用Redis服务架构分析与搭建方案
2021/06/20 Redis
浅谈什么是SpringBoot异常处理自动配置的原理
2021/06/21 Java/Android