基于Python通过OpenCV实现的口罩识别系统操作篇

基于Python通过OpenCV实现的口罩识别系统操作篇

文章目录

    • 基于Python通过OpenCV实现的口罩识别系统操作篇
  • 前言
  • 一、级联分类器
  • 二、使用步骤
    • 1.引入库
    • 2.引入级联分类器
    • 3.对象识别方式
  • 三、画出识别对象
    • 代码操作方式
    • 测试效果
  • 总代码展示:


前言

理论思路介绍篇,可以查看往日文章。
项目实现环境:
基于Python 3.8.1版本
opencv-python 4.2.0.34版本
需要自己下载OpenCV的库文件,添加其中的分类器


一、级联分类器

首先要引入相应的级联分类器
本项目一共使用了三个级联分类器:
人脸面部识别树:haarcascade_frontalface_alt2.xml
人脸面部鼻子识别树:haarcascade_mcs_nose.xml
口罩检测识别训练树:cascade.xml(这个训练的级联分类器是第三方制作文件,非OpenCV原厂训练文件)

二、使用步骤

1.引入库

import cv2.cv2 as cv
import time
import numpy as np
import pygame
import threading

以上的相应库函数,通过python的pip可以进行添加,添加OpenCV库的时候容易出现多个bug,建议参考以前的文章OpenCV的安装。

2.引入级联分类器

引入分类器时候,注意使用分类器是要将其引入的地址填写正确。

face_cascade = cv.CascadeClassifier('D:/OPENCV/opencv/build/etc/haarcascades/haarcascade_frontalface_alt2.xml')#人脸面部识别
eye_cascade = cv.CascadeClassifier('D:/OPENCV/opencv/build/etc/haarcascades/haarcascade_eye_tree_eyeglasses.xml')#面部眼镜识别
nose_cascade = cv.CascadeClassifier('D:/OPENCV/opencv/build/etc/haarcascades/haarcascade_mcs_nose.xml')#人脸面部鼻子识别
mask_detector = cv.CascadeClassifier("D:/OPENCV/opencv/build/etc/haarcascades/cascade.xml")#人脸佩戴口罩识别

3.对象识别方式

基于Python通过OpenCV实现的口罩识别系统操作篇_第1张图片
可以看到一共有8个参数。

1.img(必需)

这个不用多解释,显然是要输入的图像。图像可以是彩色也可以是灰度的。

2.foundLocations

存取检测到的目标位置

3.hitThreshold (可选)

opencv documents的解释是特征到SVM超平面的距离的阈值(Threshold for the distance between features and SVM classifying plane)

所以说这个参数可能是控制HOG特征与SVM最优超平面间的最大距离,当距离小于阈值时则判定为目标。

4.winStride(可选)

HoG检测窗口移动时的步长(水平及竖直)。

winStride和scale都是比较重要的参数,需要合理的设置。一个合适参数能够大大提升检测精确度,同时也不会使检测时间太长。

5.padding(可选)

在原图外围添加像素,作者在原文中提到,适当的pad可以提高检测的准确率(可能pad后能检测到边角的目标?)

常见的pad size 有(8, 8), (16, 16), (24, 24), (32, 32).

6.scale(可选)
基于Python通过OpenCV实现的口罩识别系统操作篇_第2张图片
图是一个图像金字塔,也就是图像的多尺度表示。每层图像都被缩小尺寸并用gaussian平滑。

scale参数可以具体控制金字塔的层数,参数越小,层数越多,检测时间也长。 一下分别是1.01 1.5 1.03 时检测到的目标。 通常scale在1.01-1.5这个区间
基于Python通过OpenCV实现的口罩识别系统操作篇_第3张图片
基于Python通过OpenCV实现的口罩识别系统操作篇_第4张图片
7.finalThreshold(可选)

这个参数不太清楚,有人说是为了优化最后的bounding box

8.useMeanShiftGrouping(可选)

bool 类型,决定是否应用meanshift 来消除重叠。

default为false,通常也设为false,另行应用non-maxima supperssion效果更好。

实际代码

ret, frame = cameraCapture.read()#首先是将摄像头转化的输出转化为一帧一帧的图像
        gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)将图像转化为灰度图像,减少运算量
        faces = face_cascade.detectMultiScale(gray, 1.2, 10)#运用比对函数1.2为每次以1.2倍移动比对,10为识别次数为10次便认为是我们需要的图像。
        masks = mask_detector.detectMultiScale(gray, 1.03, 5)#
        noses = nose_cascade.detectMultiScale(gray, 1.2, 10)#

对比参数需要按照实际情况进行测试和调整,有时候将对比次数调整的过高将会导致程序的运算量过大,虽然准确无误,但是又会忽略许多的残缺实际对象,比如上图中的小孩子,就会被忽略。

三、画出识别对象

代码操作方式

代码如下(示例):

ret, frame = cameraCapture.read()
        gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
        faces = face_cascade.detectMultiScale(gray, 1.2, 10)# 1.02
        masks = mask_detector.detectMultiScale(gray, 1.03, 5)# 1.01
        noses = nose_cascade.detectMultiScale(gray, 1.2, 10)# 1.05
        for (x, y, w, h) in faces:
            cv.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
            cv.putText(frame, "no_mask", (x, y), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
            n = n + 1
            no_mask = no_mask+1

        for (mx, my, mw, mh) in masks:
            cv.rectangle(frame, (mx, my), (mx + mw, my + mh), (0, 255, 0), 2)
            cv.putText(frame, "have_mask", (mx, my), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
            n = n + 1
            have_mask = have_mask + 1


        for (nx, ny, nw, nh) in noses:
            cv.rectangle(frame, (nx, ny), (nx + nw, ny + nh), (10, 10, 255), 2)
            cv.putText(frame, "no_mask", (nx, ny), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
            #  n = 1
            no_mask = 1

通过识别和比对,输出的值将通过for循环输出,并且使用OpenCV画出矩形框,并得出是否佩戴口罩。

测试效果

以下为测试结果:
基于Python通过OpenCV实现的口罩识别系统操作篇_第5张图片
在图像中通过分类器比对,找到了匹配的数据后,将所得到的数据进行画框,并且输出出来了。以上为全脸未带口罩,识别出了鼻子和人脸,使用红色框图进行表示。
基于Python通过OpenCV实现的口罩识别系统操作篇_第6张图片
以上为佩戴口罩状态,将会识别佩戴口罩的人脸,并且用绿色框图表示。
基于Python通过OpenCV实现的口罩识别系统操作篇_第7张图片
在佩戴口罩不完全时,主要以识别口鼻等关键部位,进行判断是否佩戴了口罩。
基于Python通过OpenCV实现的口罩识别系统操作篇_第8张图片
基于Python通过OpenCV实现的口罩识别系统操作篇_第9张图片
在对比效率的情况下,测试结果为,未佩戴眼镜时,匹配准确率和效率都较为高。主要原因分析:由于引入的级联分类器的训练样本多为未佩戴眼镜的,所以在配戴眼镜时,会对其产生一定的干扰。

总代码展示:

项目一:只含有口罩识别,未添加语音提醒。

import cv2.cv2 as cv
import time
import pygame




def detect():
    n = 0
    have_mask = 0
    no_mask = 0
    face_cascade = cv.CascadeClassifier('D:/OPENCV/opencv/build/etc/haarcascades/haarcascade_frontalface_alt2.xml')
    eye_cascade = cv.CascadeClassifier('D:/OPENCV/opencv/build/etc/haarcascades/haarcascade_eye_tree_eyeglasses.xml')
    nose_cascade = cv.CascadeClassifier('D:/OPENCV/opencv/build/etc/haarcascades/haarcascade_mcs_nose.xml')
    mask_detector = cv.CascadeClassifier("D:/OPENCV/opencv/build/etc/haarcascades/cascade.xml")
    cameraCapture = cv.VideoCapture(0, cv.CAP_DSHOW)# cv.CAP_DSHOW
    while True:
        start = time.time()
        ret, frame = cameraCapture.read()
        gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
        faces = face_cascade.detectMultiScale(gray, 1.2, 10)# 1.02
        masks = mask_detector.detectMultiScale(gray, 1.03, 5)# 1.01
        noses = nose_cascade.detectMultiScale(gray, 1.2, 10)# 1.05
        for (x, y, w, h) in faces:
            cv.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
            cv.putText(frame, "no_mask", (x, y), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
            n = 1
            have_mask = 1
            # roi_gray = gray[y:y+h, x:x+w]
            # img = frame[y:y+h, x:x+w]
            # eyes = eye_cascade.detectMultiScale(roi_gray, 1.03, 8, 0)
            # for (ex, ey, ew, eh) in eyes:
            #     cv.rectangle(img, (ex, ey), (ex+ew, ey+eh), (0, 255, 255), 2)

        for (mx, my, mw, mh) in masks:
            cv.rectangle(frame, (mx, my), (mx + mw, my + mh), (0, 255, 0), 2)
            cv.putText(frame, "have_mask", (mx, my), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
            n = 1
            no_mask = 1


        for (nx, ny, nw, nh) in noses:
            cv.rectangle(frame, (nx, ny), (nx + nw, ny + nh), (10, 10, 255), 2)
            cv.putText(frame, "no_mask", (nx, ny), cv.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
            n = 1
            no_mask = 1


        c = cv.waitKey(50)
        if c == 27:
            break
            # 计算帧率
        end = time.time()  # 结束时间
        fps = 1 / (end - start)  # 帧率
        image = cv.putText(frame, "fps:{:.3f}".format(fps), (550, 15), cv.FONT_HERSHEY_COMPLEX, 0.5, (0, 255, 0), 1)  # 绘制
        image2 = cv.putText(image, f"Number of people tested:{n}", (400, 40), cv.FONT_HERSHEY_COMPLEX, 0.5, (0, 255, 255), 1)
        image3 = cv.putText(image2, f'Number of people wearing masks:{have_mask}', (325, 60), cv.FONT_HERSHEY_COMPLEX, 0.5, (0, 255, 0), 1)
        image4 = cv.putText(image3, f'Number of people not wearing masks:{no_mask}', (290, 80), cv.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 255), 1)
        cv.imshow('camera', image4)


    cameraCapture.release()
    cv.destroyAllWindows()



if __name__=='__main__':
        detect()

文章书写不易,如果对你有帮助的话,可以给作者点个赞嘛!
你的点赞,评论,收藏,是对我们最大的支持和帮助!

你可能感兴趣的:(python,opencv,计算机视觉,人脸识别)