基于OpenCV和Python的实时口罩识别系统:支持摄像头与图片检测,界面简洁操作便捷
输出结果是个二维数组,第一列是戴口罩的概率,第二列是不戴的概率。先看界面长啥样(想象一下图1)——PyQt做的操作面板,中间是视频显示区域,底下有个状态栏实时显示检测结果。最后说个坑:OpenCV的dnn模块对不同版本模型兼容性玄学,如果遇到加载失败,建议用OpenCV4.2以上版本。软件说明:读取用户设备的摄像头,可实时检测画面中的人的口罩佩戴情况,并给予提示。软件说明:读取用户设备的摄像头,可
基于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,不过速度会打点折扣。
有遇到帧率过低的情况?试试这两招:
- 把Haar检测的缩放因子从1.1调到1.2
- 限制最大检测人脸数为5
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5, maxSize=(300,300), flags=cv2.CASCADE_SCALE_IMAGE)
最后说个坑:OpenCV的dnn模块对不同版本模型兼容性玄学,如果遇到加载失败,建议用OpenCV4.2以上版本。需要远程协助调试的记得装向日葵,不过大概率你按照这个套路来应该能跑起来。

更多推荐
所有评论(0)