python基于Opencv实现人脸口罩检测

作者:伤心兮 时间:2021-11-18 02:45:16 

一、开发环境

python 3.6.6

opencv-python 4.5.1

二、设计要求

1、使用opencv-python对人脸口罩进行检测

三、设计原理

设计流程图如图3-1所示,

python基于Opencv实现人脸口罩检测

图3-1 口罩检测流程图

首先进行图片的读取,使用opencv的haar鼻子特征分类器,如果检测到鼻子,则证明没有戴口罩。如果检测到鼻子,接着使用opencv的haar眼睛特征分类器,如果没有检测到眼睛,则结束。如果检测到眼睛,则把RGB颜色空间转为HSV颜色空间。进行口罩区域的检测。口罩区域检测流程是首先把距离坐标原点的较近的横坐标作为口罩区域开始横坐标,离坐标原点较远的横坐标作为口罩区域结束横坐标。离坐标原点较远的纵坐标作为口罩区域开始纵坐标,离坐标原点较远的纵坐标与眼睛高度2倍的和作为口罩区域结束纵坐标。在此叙述的可能不是很清楚,可以见图3-2,

python基于Opencv实现人脸口罩检测

图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("data/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("data/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)                          #
           minH = cv2.getTrackbarPos("Hmin", 'skin')           # 获取bar
           maxH = cv2.getTrackbarPos("Hmax", 'skin')
           if minH > maxH:
               maxH = minH
           thresh_h = cv2.inRange(H, minH, maxH)       # 提取人体肤色区域
           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()

五、结果展示

检测结果如下:

python基于Opencv实现人脸口罩检测

图5-1 HSV转换结果图

python基于Opencv实现人脸口罩检测

图5-2 口罩检测结果图

python基于Opencv实现人脸口罩检测

图5-3 口罩检测结果图(竟然把耳朵误判为鼻子)

六、结论

本实验使用了opencv-python进行了人脸口罩检测。进行鼻子、眼睛检测使用的时opencv自带的.xml文件。从结果来看,这种方法是可行的。是可以应用在地铁站、火车站出入口进行人脸口罩检测的。

本实验也有一定局限性,例如图片中有两个人、眼睛被遮挡等特殊情况。如果感兴趣可以自己训练.xml文件。当然,也可以使用基于深度学习的目标检测模型例如R-CNN系列、YOLO系列、SSD等进行模型的训练。

来源:https://blog.csdn.net/qq_43717870/article/details/117733341

标签:Opencv,人脸,口罩,检测
0
投稿

猜你喜欢

  • scrapy数据存储在mysql数据库的两种方式(同步和异步)

    2023-07-10 03:29:43
  • python gensim使用word2vec词向量处理中文语料的方法

    2023-02-25 08:12:56
  • 详解Python中的多线程编程

    2023-09-17 00:34:08
  • Python开发之QT解决无边框界面拖动卡屏问题(附带源码)

    2023-10-31 09:31:29
  • sqlserver数据库主键的生成方式小结(sqlserver,mysql)

    2012-08-21 10:25:45
  • Oracle9i在Win2k环境下的完全卸载

    2010-07-28 13:03:00
  • python实现bucket排序算法实例分析

    2023-09-17 17:54:07
  • 将以用户为中心的设计嵌入产品设计和开发流程

    2009-08-11 14:27:00
  • 技巧/诀窍:在ASP.NET中重写URL

    2007-09-23 12:21:00
  • python实现opencv+scoket网络实时图传

    2023-07-03 16:09:17
  • PHP中生成UUID自定义函数分享

    2023-11-14 16:57:04
  • PHP实现更改hosts文件的方法示例

    2023-10-19 18:30:12
  • 浅谈function(函数)中的动态参数

    2023-08-11 10:23:59
  • 基于Python编写简单实用的日志装饰器

    2022-10-09 01:21:51
  • python自动化实现登录获取图片验证码功能

    2022-09-21 13:23:59
  • 如何避免SQL语句中含有单引号而导致操作失败?

    2009-11-07 18:40:00
  • Python中规范定义命名空间的一些建议

    2022-05-16 17:05:24
  • Python asyncio异步编程常见问题小结

    2023-10-04 23:13:56
  • IE9报“DOM Exception: INVALID_CHARACTER_ERR (5)”错误的原因及解决办法

    2011-09-01 19:11:07
  • Django中间件实现拦截器的方法

    2022-10-21 04:47:53
  • asp之家 网络编程 m.aspxhome.com