使用Python进行实时人脸检测(附完整代码)
Posted 王仙仙-wxx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Python进行实时人脸检测(附完整代码)相关的知识,希望对你有一定的参考价值。
需要全部代码请点赞关注收藏后评论区留言私信~~~
本文介绍一个简易的项目,我们将使用OpenCV和Python实现实时人脸检测,我们将研究 OpenCV 中的 Haar 级联分类器(Haar Cascade Classifier)算法, Haar 级联分类器是一种流行的目标检测算法。
1.Harr分类器
Haar-like特征最早是由Papageorgiou等人用于物体检测的数字图像特征,而Viola和Jones在此基础上,使用3种类型4种形式的特征:
Haar特征分为三类:边缘特征、线性特征、中心特征和对角线特征,组合成特征模板。特征模板内有白色和黑色两种矩形,并定义该模板的特征值为白色矩形像素和减去黑色矩形像素和。Haar特征值反映了图像的灰度变化情况。例如:脸部的一些特征能由矩形特征简单的描述,如:眼睛要比脸颊颜色要深,鼻梁两侧比鼻梁颜色要深,嘴巴比周围颜色要深等。但矩形特征只对一些简单的图形结构,如边缘、线段较敏感,所以只能描述特定走向(水平、垂直、对角)的结构。
这类矩形特征模板由两个或多个全等的黑白矩形相邻组合而成,而矩形特征值是白色矩形的灰度值的和减去黑色矩形的灰度值的和,矩形特征对一些简单的图形结构,如线段、边缘比较敏感。如果把这样的矩形放在一个非人脸区域,那么计算出的特征值应该和人脸特征值不一样,所以这些矩形就是为了把人脸特征量化,以区分人脸和非人脸。
以Haar特征分类器为基础的对象检测技术是一种非常有效的对象检测技术,但其实并不新颖,不过因为技术成熟好用这里依然采用这一方法。它是基于机器学习的,使用大量的正负样本训练得到分类器。其实就是基于对人脸特征的描述,分类器根据训练的样品数据进行训练,完成后即可感知读取到的图片上的特征,进而对图片进行人脸识别。
OpenCV已在GitHub训练结果网址(https://github.com/opencv/opencv/tree/master/data/haarcascades)上分享了其训练好的结果数据,分类器普适性较好可满足一般人脸检测的需要,调用的代码如下:
import cv2
face_cascade = cv2.CascadeClassifier(r'./haarcascade_frontalface_default.xml')
如果安装好了OpenCV,它的依赖库中OpenCV 提供了关于 Haar 特征和级联分类器的预训练模型,可以在以下位置找到必要的 XML 文件:
/home/<username>/.local/lib/<python-version>/site-packages/cv2/data/
以上Ubuntu的位置,Windows下的情况同样在Python环境的site-package目录下,下面我们看看如何使用这些预训练的 Haar 级联模型来检测人脸。
2.检测步骤实现
首先,创建一个 python 文件 face_detection.py 并粘贴以下代码:
(1)导入包:
import cv2
import os
(2)初始化haar分类器:
cascPath=os.path.dirname(cv2.__file__)+"/data/haarcascade_frontalface_default.xml"
faceCascade = cv2.CascadeClassifier(cascPath)
(3)对相机的画面帧应用人脸haar检测器:
video_capture = cv2.VideoCapture(0)
while True:
# Capture frame-by-frame
ret, frames = video_capture.read()
gray = cv2.cvtColor(frames, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30),
flags=cv2.CASCADE_SCALE_IMAGE
)
# Draw a rectangle around the faces
for (x, y, w, h) in faces:
cv2.rectangle(frames, (x, y), (x+w, y+h), (0, 255, 0), 2)
# Display the resulting frame
cv2.imshow('Video', frames)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
(4)释放画面:
video_capture.release()
cv2.destroyAllWindows()
(5)运行程序:
python3 face_detection.py
在画面中可以看到网络摄像头画面帧中检测出的人脸边界框,要停止网络摄像头获取画面,可按“q”键结束。
Haar级联分类器是一个基础的人脸检测模型,它的检测速度快、精度较高,能够满足常见的人脸检测任务,当然如果想获得高精度的人脸检测可以使用faceNet模型。如何利用检测出的人脸区域进行人脸识别匹配详见CSDN。
基于Opencv-python人脸口罩检测(附完整代码)
目录
一、开发环境
python 3.6.6
opencv-python 4.5.1
二、设计要求
· 1、使用opencv-python对人脸口罩进行检测
三、设计原理
设计流程图如图3-1所示,
图3-1 口罩检测流程图
首先进行图片的读取,使用opencv的haar鼻子特征分类器,如果检测到鼻子,则证明没有戴口罩。如果没有检测到鼻子,接着使用opencv的haar眼睛特征分类器,如果没有检测到眼睛,则结束。如果检测到眼睛,则把RGB颜色空间转为HSV颜色空间。进行口罩区域的检测。口罩区域检测流程是首先把距离坐标原点的较近的横坐标作为口罩区域开始横坐标,离坐标原点较远的横坐标作为口罩区域结束横坐标。离坐标原点较远的纵坐标作为口罩区域开始纵坐标,离坐标原点较远的纵坐标与眼睛高度2倍的和作为口罩区域结束纵坐标。在此叙述的可能不是很清楚,可以见图3-2,
图3-2 口罩区域检测图
最后,知道口罩区域时,只需对像素点进行判断就可以判断出是否佩戴口罩。
四、程序代码
"""
# File : mask_check.py
# Time :2021/6/10 15:02
# Author :Meng
# version :python 3.6
# Description:
"""
import cv2 # 导入opencv
import time # 导入time
"""实现鼻子检测"""
def nose_dection(img):
img = cv2.GaussianBlur(img,(5,5),0)#高斯滤波
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 将图片转化成灰度
nose_cascade = cv2.CascadeClassifier("haarcascade_mcs_nose.xml")
nose_cascade.load("./haarcascades/haarcascade_mcs_nose.xml") # 文件所在的具体位置
'''此文件是opencv的haar鼻子特征分类器'''
noses = nose_cascade.detectMultiScale(gray, 1.3, 5) # 鼻子检测
for(x,y,w,h) in noses:
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) # 画框标识鼻子
flag = 0 # 检测到鼻子的标志位,如果监测到鼻子,则判断未带口罩
if len(noses)>0:
flag = 1
return img,flag
""""实现眼睛检测"""
def eye_dection(img):
img = cv2.GaussianBlur(img,(5,5),0)#高斯滤波
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 将图片转化成灰度
eyes_cascade = cv2.CascadeClassifier("haarcascade_eye_tree_eyeglasses.xml")
eyes_cascade.load("./haarcascades/haarcascade_eye_tree_eyeglasses.xml") # 文件所在的具体位置
'''此文件是opencv的haar眼睛特征分类器'''
eyes = eyes_cascade.detectMultiScale(gray, 1.3, 5) # 眼睛检测
for (x,y,w,h) in eyes:
frame = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) # 画框标识眼部
print("x y w h is",(x,y,w,h))
# frame = cv2.rectangle(img, (x, y+h), (x + 3*w, y + 3*h), (255, 0, 0), 2) # 画框标识眼部
return img,eyes
def empty(a):
pass
def main():
image = cv2.imread("images/backgound.png") # 读取背景照片
cv2.imshow('skin', image) # 展示
cv2.createTrackbar("Hmin", "skin", 0, 90, empty) # 创建bar
cv2.createTrackbar("Hmax", "skin", 25, 90, empty)
capture = cv2.VideoCapture(0) # 打开摄像头,其中0为自带摄像头,
while True:
ref,img=capture.read() # 打开摄像头
# img = cv2.imread("./images/005.jpg") # 读取一张图片
img_hsv = img
image_nose,flag_nose = nose_dection(img) # 进行口罩检测,返回检测之后的图形以及标志位
if flag_nose == 1: # 当检测到鼻子的时候,判断未戴口罩
frame = cv2.putText(image_nose, "NO MASK", (10, 30), cv2.FONT_HERSHEY_COMPLEX, 0.9,(0, 0, 255), 1) # 在图片上写字
cv2.imshow('img', image_nose) # 展示图片
if flag_nose == 0: # 未检测鼻子,进行眼睛检测
img_eye,eyes = eye_dection(img) # 进行眼睛检测,返回检测之后的图形以及标志位
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 将图片转化成HSV格式
H, S, V = cv2.split(hsv) #
Hmin= cv2.getTrackbarPos("Hmin", 'skin') # 获取bar
Hmax= cv2.getTrackbarPos("Hmax", 'skin')
if Hmin> Hmax:
Hmax= Hmin
thresh_h = cv2.inRange(H, Hmin, Hmax) # 提取人体肤色区域
if len(eyes) > 1: # 判断是否检测到两个眼睛,其中eyes[0]为左眼坐标
# 口罩区域的提取
mask_x_begin = min(eyes[0][0],eyes[1][0]) # 把左眼的x坐标作为口罩区域起始x坐标
mask_x_end = max(eyes[0][0],eyes[1][0]) + eyes[list([eyes[0][0], eyes[1][0]]).index(max(list([eyes[0][0], eyes[1][0]])))][2] # 把右眼x坐标 + 右眼宽度作为口罩区域x的终止坐标
mask_y_begin = max(eyes[0][1] + eyes[0][3],eyes[1][1] + eyes[1][3]) + 20 # 把眼睛高度最大的作为口罩区域起始y坐标
if mask_y_begin > img_eye.shape[1]: # 判断是否出界
mask_y_begin = img_eye.shape[1]
mask_y_end = max(eyes[0][1] + 3 * eyes[0][3],eyes[1][1] + 3 * eyes[1][3]) + 20 # 同理
if mask_y_end > img_eye.shape[1]:
mask_y_end = img_eye.shape[1]
frame = cv2.rectangle(img_eye, (mask_x_begin, mask_y_begin), (mask_x_end, mask_y_end), (255, 0, 0), 2) # 画口罩区域的框
total_mask_pixel = 0
total_face_pixel = 0
# 遍历二值图,为0则total_mask_pixel+1,否则total_face_pixel+1
for i in range(mask_x_begin,mask_x_end):
for j in range(mask_y_begin,mask_y_end):
if thresh_h[i,j] == 0:
total_mask_pixel += 1
else:
total_face_pixel += 1
print("total_mask_pixel",total_mask_pixel)
print("total_face_pixel", total_face_pixel)
if total_mask_pixel > total_face_pixel:
frame = cv2.putText(img_eye, "HAVE MASK", (mask_x_begin, mask_y_begin - 10),cv2.FONT_HERSHEY_COMPLEX, 0.9, (0, 0, 255), 1) # 绘制
if total_mask_pixel < total_face_pixel:
frame = cv2.putText(img_eye, "NO MASK", (mask_x_begin, mask_y_begin - 10), cv2.FONT_HERSHEY_COMPLEX,0.9, (0, 0, 255), 1) # 绘制
cv2.imshow("skin", thresh_h) # 显示肤色图
cv2.imshow("img", img_eye) # 显示肤色图
# cv2.imwrite('005_result.jpg',img_eye) 保存图片
c = cv2.waitKey(10)
if c==27:
break
capture.release() #
cv2.destroyAllWindows() # 关闭所有窗口
if __name__ == '__main__':
main()
五、结果展示
检测结果如下:
图5-1 HSV转换结果图
图5-2 口罩检测结果图
图5-3 口罩检测结果图(竟然把耳朵误判为鼻子)
六、结论
本实验使用了opencv-python进行了人脸口罩检测。进行鼻子、眼睛检测使用的时opencv自带的.xml文件。从结果来看,这种方法是可行的。是可以应用在地铁站、火车站出入口进行人脸口罩检测的。
本实验也有一定局限性,例如图片中有两个人、眼睛被遮挡等特殊情况。如果感兴趣可以自己训练.xml文件。当然,也可以使用基于深度学习的目标检测模型例如R-CNN系列、YOLO系列、SSD等进行模型的训练。
(注:部分图片来源于网络,侵删)
(如果觉得本篇文章对你有用的话,就麻烦点个赞吧)
以上是关于使用Python进行实时人脸检测(附完整代码)的主要内容,如果未能解决你的问题,请参考以下文章