前言
人脸检测与识别是深受关注的技术。目前,人脸检测与识别有很多的算法实现,常用的人脸检测的算法有Dilb,OpenCV,OpenFace,MTCNN等。常用人脸识别的算法包括FaceNet,InsightFace模型等。
此文是当初做人脸识别项目时根据他人博客做的小程序,全文比较简单,因此在我介绍人脸识别项目前先介绍一下简单的OpenCV人脸检测。
一、OpenCV人脸检测原理
OpenCV采用的是基于Haar的cascade分类器。
基于Haar特征的cascade分类器是Paul Viola和 Michael Jone在2001年发表的论文”Rapid Object Detection using a Boosted Cascade of Simple Features”中提出的一种有效的物品检测方法。它是一种机器学习方法,通过许多正负样例中训练得到cascade方程,然后将其应用于其他图片。
和许多分类器的训练一样,需要根据大量正样例(包含人脸的图片)和负样例(不包含人脸的图片)来进行训练,由此在这些图片中获取特征。
Haar特征包含三种:边缘特征、线性特征、中心特征和对角线特征。每种分类器都从图片中提取出对应的特征。
对于下图来说,第一个特征根据眼睛所在位置通常比脸颊和鼻子更黑来选择,即横的黑道将人脸中较暗的双眼提取了出来;而第二个特征选择的依据则是眼睛比鼻梁要黑,即竖的白道将人脸中较亮的鼻梁提取了出来。
就如何在大量特征中选择最好的特征这个问题来说,采用了Adaboost的方法,首先通过机器学习找出人脸分类效果最好、错误率最小的特征。训练开始时,所有训练集中的图片具有相同的权重,对于被分类错误的图片,提升权重,重新计算出新的错误率和新的权重。直到错误率或迭代次数达到要求。
最终的分类器是这些弱分类器的加权和。之所以称之为弱分类器是因为每个分类器不能单独分类图片,但是将他们聚集起来就形成了强分类器。论文表明,只需要200个特征的分类器在检测中的精确度达到了95%。最终的分类器大约有6000个特征。(将超过160000个特征减小到6000个,这是非常大的进步了)
事实上,一张图片绝大部分的区域都不是人脸。如果对一张图片的每个角落都提取6000个特征,将会浪费巨量的计算资源。如果能找到一个简单的方法能够检测某个窗口是不是人脸区域,如果该窗口不是人脸区域,那么就只看一眼便直接跳过,也就不用进行后续处理了,这样就能集中精力判别那些可能是人脸的区域。
为此,有人引入了Cascade 分类器。它不是将6000个特征都用在一个窗口,而是将特征分为不同的阶段,然后一个阶段一个阶段的应用这些特征(通常情况下,前几个阶段只有很少量的特征)。如果窗口在第一个阶段就检测失败了,那么就直接舍弃它,无需考虑剩下的特征。如果检测通过,则考虑第二阶段的特征并继续处理。如果所有阶段的都通过了,那么这个窗口就是人脸区域。
作者的检测器将6000+的特征分为了38个阶段,前五个阶段分别有1,10,25,25,50个特征(前文图中提到的识别眼睛和鼻梁的两个特征实际上是Adaboost中得到的最好的两个特征)。根据作者所述,平均每个子窗口只需要使用6000+个特征中的10个左右。
二、OpenCV实现人脸检测
实际上OpenCV自带的Harr级联分类器是成熟的分类器,并不需要再次进行训练,所需代码量非常少。
OpenCV包含许多训练好的分类器,比如脸、眼、微笑等。这些XML文件存储在opencv/data/haarcascades/文件夹中,使用时可以直接调取。
import cv2
path = '【图片】' #图片地址
img = cv2.imread(path) #读取图片
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades+'haarcascade_frontalface_default.xml') #获取人脸级联分类器,'.xml'文件里包含训练出来的人脸特征
faces = face_cascade.detectMultiScale(img,scaleFactor=【放大倍数】,minNeighbors=【重复识别次数】) #用分类器进行人脸识别,返回人脸坐标列表
for (x,y,w,h) in faces: #对每一张人脸进行操作
img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) #画出人脸框,倒数两个参数分别为颜色和线条宽度,其中颜色采用BGR格式
cv2.imshow('img',img) #展示人脸框
怎么样,是不是很简单~
以《庆余年》海报为例,人脸区域使用蓝色方框圈出。
除了人脸分类器,还有人眼分类器
eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades+'haarcascade_eye.xml')
还有微笑分类器
smile_cascade = cv2.CascadeClassifier(cv2.data.haarcascades+'haarcascade_smile.xml')
代码与示例代码相似,加载相应模型,只不过为了节省计算资源,需要在识别出的人脸框内再进行检测。
示例代码:
for (x,y,w,h) in faces:
img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
# 框选出人脸区域,在人脸区域而不是全图中进行人眼检测,节省计算资源
face_area = img[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(face_area)
# 用人眼级联分类器引擎在人脸区域进行人眼识别,返回的eyes为眼睛坐标列表
for (ex,ey,ew,eh) in eyes:
#画出人眼框,绿色,画笔宽度为1
cv2.rectangle(face_area,(ex,ey),(ex+ew,ey+eh),(0,255,0),1)
三、调用摄像头实时人脸检测
原理也比较简单,OpenCV有调用电脑摄像头的函数,然后用循环实时把人脸框显示出来。
import cv2
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades+'haarcascade_frontalface_default.xml')
# 调用摄像头摄像头
cap = cv2.VideoCapture(0) #opencv的函数,参数0代表调用电脑自带摄像,若改为1则调用外设摄像
while(True):
# 获取摄像头拍摄到的画面
ret, frame = cap.read()
faces = face_cascade.detectMultiScale(frame, 1.3, 5)
img = frame
for (x,y,w,h) in faces:
# 画出人脸框,蓝色,画笔宽度微
img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
# 实时展示效果画面
cv2.imshow('frame2',img)
# 每5毫秒监听一次键盘动作
if cv2.waitKey(5) & 0xFF == ord('q'):
break
# 最后,关闭所有窗口
cap.release()
cv2.destroyAllWindows()
动态监测如下:
(本来我想用我女朋友的照片,毕竟我手机里有很多,奈何她不同意,只好选择另一张照片,正好也测试一下非现实人脸是否可以识别)
下期采用深度学习实现人脸识别(在检测的基础上识别出人物对应信息)
缺陷
- 脸部倾斜时识别不出人脸区域
- 2D识别,图片即可识别,并不是根据人脸的三维建模
参考资料
今天的文章OpenCV实现人脸检测分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/18533.html