基于OpenCV的口罩识别系统 相关技术:python,opencv,pyqt (请自行安装向日葵远程软件,以便提供远程帮助) 软件说明:读取用户设备的摄像头,可实时检测画面中的人的口罩佩戴情况,并给予提示。 有基础的同学,可稍作修改,检测图片。 第一张为运行主界面。 第二张为部分代码截图。 第三和第四张为运行界面。

最近在折腾一个挺实用的小项目——用Python+OpenCV搞了个口罩识别系统。这玩意儿能实时检测摄像头画面里的人有没有戴口罩,特别适合用在商场入口或者办公楼闸机的位置。今天就跟大伙儿唠唠实现思路,顺手贴点核心代码。(悄悄说:文末藏了个检测图片的彩蛋)

先看界面长啥样(想象一下图1)——PyQt做的操作面板,中间是视频显示区域,底下有个状态栏实时显示检测结果。整个UI布局用QtDesigner拖控件搞定,这里重点说说视频流处理的核心逻辑。

class CameraThread(QThread):
    frame_signal = pyqtSignal(np.ndarray)

    def run(self):
        cap = cv2.VideoCapture(0)
        while True:
            ret, frame = cap.read()
            if ret:
                self.frame_signal.emit(frame)
            else:
                break

这段代码用QThread开了个独立线程读取摄像头数据,避免界面卡顿。注意用pyqtSignal传递帧数据,这是PyQt多线程交互的经典操作。

检测部分才是重头戏。先加载两个关键模型:

face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
mask_detector = cv2.dnn.readNet('mask_detection_model.pb')

这里用了两个神器——Haar级联分类器做人脸初筛,再用训练好的TensorFlow口罩检测模型做精准判断。双模型组合拳既保证速度又提升准确率。

基于OpenCV的口罩识别系统 相关技术:python,opencv,pyqt (请自行安装向日葵远程软件,以便提供远程帮助) 软件说明:读取用户设备的摄像头,可实时检测画面中的人的口罩佩戴情况,并给予提示。 有基础的同学,可稍作修改,检测图片。 第一张为运行主界面。 第二张为部分代码截图。 第三和第四张为运行界面。

处理单帧的核心流程:

def process_frame(frame):
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray, 1.1, 5)
    
    for (x,y,w,h) in faces:
        face_roi = frame[y:y+h, x:x+w]
        blob = cv2.dnn.blobFromImage(face_roi, 1.0, (224,224), (104,177,123))
        mask_detector.setInput(blob)
        pred = mask_detector.forward()
        
        if pred[0][0] > pred[0][1]:  # 口罩概率判断
            cv2.rectangle(frame, (x,y), (x+w,y+h), (0,255,0), 2)
            text = "Mask: {:.2f}%".format(pred[0][0]*100)
        else:
            cv2.rectangle(frame, (x,y), (x+w,y+h), (0,0,255), 2)
            text = "No Mask: {:.2f}%".format(pred[0][1]*100)
        
        cv2.putText(frame, text, (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255,255,0), 2)
    return frame

这里有个骚操作——把截取的人脸区域缩放成224x224输入到DNN模型。注意blobFromImage的参数设置,那些归一化值是从预训练模型里继承的,别瞎改。输出结果是个二维数组,第一列是戴口罩的概率,第二列是不戴的概率。

想改成图片检测?把摄像头输入换成读取图片文件就行:

image = cv2.imread('test.jpg')
result = process_frame(image)
cv2.imshow('Result', result)

实测效果(想象图3、4)——绿色框配百分比是已戴口罩,红色框会报警。在光线充足的场景下,准确率能到90%以上。不过侧脸和遮挡严重的情况还是会翻车,这时候可以考虑上MTCNN换掉Haar,不过速度会打点折扣。

有遇到帧率过低的情况?试试这两招:

  1. 把Haar检测的缩放因子从1.1调到1.2
  2. 限制最大检测人脸数为5
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5, maxSize=(300,300), flags=cv2.CASCADE_SCALE_IMAGE)

最后说个坑:OpenCV的dnn模块对不同版本模型兼容性玄学,如果遇到加载失败,建议用OpenCV4.2以上版本。需要远程协助调试的记得装向日葵,不过大概率你按照这个套路来应该能跑起来。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐