手把手教你用OpenCV做人脸口罩佩戴检测(附详细步骤+代码) 您所在的位置:网站首页 佩戴口罩规范 手把手教你用OpenCV做人脸口罩佩戴检测(附详细步骤+代码)

手把手教你用OpenCV做人脸口罩佩戴检测(附详细步骤+代码)

2023-11-16 20:08| 来源: 网络整理| 查看: 265

导读

本期将介绍使用OpenCV实现人脸口罩佩戴检测的详细步骤,手把手教你做一个效果还可以的口罩佩戴检测系统。

口罩检测思路与常用方法

在动手实现人脸口罩佩戴检测系统之前,我们常常会思考如何检测一个人是否佩戴口罩?方法很多,这里列举几个比较典型的方法:

① 用深度学习目标检测的方法,标注佩戴口罩与未佩戴口罩两类,然后选择合适的网络去训练检测,比如YoloV5等;

② 先检测人脸,然后将人脸ROI图像做分类,分为佩戴口罩和未佩戴口罩两类,结合人脸检测和分类网络实现;

③ 用OpenCV实现,先检测人脸,然后判断人脸ROI是否有佩戴口罩的特征;

④ 其他更好的方法。

本文使用第③种方法,选择合适的人脸检测方法与口罩佩戴判断方法即可。

效果展示

演示从视频中检测人脸是否佩戴口罩,未佩戴口罩将语音提示,避免露脸,测试视频素材来源于网络,实测使用笔记本自带摄像头检测效果更佳:

实现步骤与对应代码

程序实现步骤:

(1) 使用OpenCV DNN网络检测人脸;

(2) 通过HSV阈值提取肤色;

(3) 通过肤色轮廓面积与人脸ROI面积比值判断是否佩戴口罩。

人脸检测方法对比:

(1) 使用OpenCV Haar分类器检测人脸,例如使用自带的haarcascade_frontalface_alt.xml不能适应光线暗的情况和人脸遮挡情况,佩戴了口罩无法检测到人脸,无法继续进行后面步骤;

(2) 使用Dlib检测人脸,例如使用自带的shape_predictor_5_face_landmarks.dat不能适应人脸遮挡情况,佩戴了口罩无法检测到人脸,无法继续进行后面步骤;

(3) 使用OpenCV DNN网络检测人脸,使用自带的opencv_face_detector_uint8.pb能适应部分人脸遮挡和侧脸情况,能继续进行后续检测。

人脸检测步骤与代码:

(1) 下载OpenCV DNN人脸检测模型:

链接:https://pan.baidu.com/s/1AaLYDjyMn17ZTxOv5f-m5A

提取码:9396

(2) 加载模型检测人脸,实例代码与效果如下;

import sys import numpy as np import cv2 modelFile = "opencv_face_detector_uint8.pb" configFile = "opencv_face_detector.pbtxt" net = cv2.dnn.readNetFromTensorflow(modelFile, configFile) conf_threshold = 0.7 def detectFaceOpenCVDnn(net, frame): blob = cv2.dnn.blobFromImage(frame, 1.0, (300, 300), [104, 117, 123], False, False) frameHeight = frame.shape[0] frameWidth = frame.shape[1] net.setInput(blob) detections = net.forward() bboxes = [] ret = 0 for i in range(detections.shape[2]): confidence = detections[0, 0, i, 2] if confidence > conf_threshold: x1 = int(detections[0, 0, i, 3] * frameWidth) y1 = int(detections[0, 0, i, 4] * frameHeight) x2 = int(detections[0, 0, i, 5] * frameWidth) y2 = int(detections[0, 0, i, 6] * frameHeight) ROI = frame[y1:y2,x1:x2].copy() cv2.rectangle(frame,(x1,y1),(x2,y2),(0,255,0),2)#框出人脸区域 return ret, frame if __name__ == '__main__': img = cv2.imread("./2.jpg") _, result = detectFaceOpenCVDnn(net,img) cv2.imshow("face_detection", result) cv2.waitKey() cv2.destroyAllWindows()

(3) 通过HSV阈值提取肤色轮廓:

ROI = frame[y1:y2,x1:x2].copy() hsv_img=cv2.cvtColor(ROI,cv2.COLOR_BGR2HSV) lower_hsv_1 = np.array([0,30,30])#颜色范围低阈值 upper_hsv_1 = np.array([40,255,255])#颜色范围高阈值 lower_hsv_2 = np.array([140,30,30])#颜色范围低阈值 upper_hsv_2 = np.array([180,255,255])#颜色范围高阈值 mask1 = cv2.inRange(hsv_img,lower_hsv_1,upper_hsv_1) mask2 = cv2.inRange(hsv_img,lower_hsv_2,upper_hsv_2) mask = mask1 + mask2 mask = cv2.blur(mask,(3,3)) mask_color = cv2.cvtColor(mask,cv2.COLOR_GRAY2BGR) cv2.imshow("mask", mask)

(4) 通过肤色轮廓面积与ROI面积比值判断是否有佩戴口罩,这里设置比值为0.65,上面三幅图的比例分别如下:

def cnt_area(cnt): area = cv2.contourArea(cnt) return area def If_Have_Mask(img): hsv_img=cv2.cvtColor(img,cv2.COLOR_BGR2HSV) lower_hsv_1 = np.array([0,30,30])#颜色范围低阈值 upper_hsv_1 = np.array([40,255,255])#颜色范围高阈值 lower_hsv_2 = np.array([140,30,30])#颜色范围低阈值 upper_hsv_2 = np.array([180,255,255])#颜色范围高阈值 mask1 = cv2.inRange(hsv_img,lower_hsv_1,upper_hsv_1) mask2 = cv2.inRange(hsv_img,lower_hsv_2,upper_hsv_2) mask = mask1 + mask2 mask = cv2.blur(mask,(3,3)) mask_color = cv2.cvtColor(mask,cv2.COLOR_GRAY2BGR) cv2.imshow("mask", mask) contours,hierarchy = cv2.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE) if len(contours) < 1: return "No Mask" contours.sort(key = cnt_area, reverse=True) #print(cv2.contourArea(contours[0])) area = cv2.contourArea(contours[0]) mask_rate = area / (img.shape[0]*img.shape[1]) print(mask_rate) if mask_rate < 0.65: return "Have Mask" else: return "No Mask"结尾语:

文章实现的步骤并非最优,但基本检测效果还OK,大家跟着上述步骤和代码完全可以自己做出来。当然如果你懒得动手,那就加入知识星球获取吧,那里为你准备了完整源码和测试素材。

更多实用文章请移步至--精华文章--专题文章分类。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有