口罩检测识别率惊人,这个Python项目开源了

news/2024/7/3 2:19:50


作者 | 一颗小树x,CSDN 博主

编辑 | 唐小引

来源 | CSDN 博客

昨天在 GitHub 上看到一个有趣的开源项目,它能检测我们是否有戴口罩,跑起程序测试后,发现识别率挺高的,也适应不同环境,于是分享给大家。

首先感谢 AIZOOTech 的开源项目 —— FaceMaskDetection????,以下为该项目的 GitHub 地址:

https://github.com/AIZOOTech/FaceMaskDetection

测试环境

我们采用:

  • Windows 系统;

  • 软件:PyCharm;

  • 使用模型:TensorFlow。

先看一下效果:

检测出帅气的胡歌没有带口罩。红色框框是圈出人脸部分,上方的字体:NoMask ,准确率 1 (即有 100% 把握认为没带口罩)。

如果在多人的情况下,能检测出来吗?如下图所示。

不错不错,这个模型能同时检测多人的,并且准确高。

有人带口罩,有人没带口罩,能检测出来吗?

哇,这个模型很棒。检测出带口罩大叔,和两个没带口罩的小伙子。

大家可以先在网页体验一下:

https://aizoo.com/face-mask-detection.html

接下来,我们具体分析一下这个项目:

  • 支持 5 大主流深度学习框架(PyTorch、TensorFlow、MXNet、Keras 和 Caffe),已经写好接口了;可以根据自身的环境选择合适的框架,比如:TensorFlow;所有模型都在 models 文件夹下。

  • 公开了近 8000 张的人脸口罩数据和模型,数据集来自于 WIDER Face 和 MAFA 数据集, 重新修改了标注并进行了校验(主要是 MAFA 和 WIDER Face 的人脸位置定义不一样,所以进行了修改标注)并将其开源出来。

模型结构

在本项目中使用了 SSD 类型的架构,为了让模型可以实时的跑在浏览器以及终端设备上,将模型设计的非常小,只有 101.5 万个参数。模型结构在本文附录部分。

本模型输入大小为 260x260,主干网络只有 8 个卷积层,加上定位和分类层,一共只有 24 层(每层的通道数目基本都是 32\64\128),所以模型特别小,只有 101.5 万参数。模型对于普通人脸基本都能检测出来,但是对于小人脸,检测效果肯定不如大模型。

网页使用了 Tensorflow.js 库,所以模型是完全运行在浏览器里面的。运行速度的快慢,取决于电脑配置的高低。

模型在五个卷积层上接出来了定位分类层,其大小和 anchor 设置信息如下表。

工程包目录结构分析

GitHub 工程包下载:

https://github.com/AIZOOTech/FaceMaskDetection

下载完 FaceMaskDetection 压缩包后,解压后如下图:

如何运行程序?

以 TensorFlow 模型为例子,代码中 TensorFlow 版本应该是 1.x;

如果是 TensorFlow 版本是 2.x 的朋友,对应函数修改为 tf.compat.v1.xxxx,使函数与 1.x 版本兼容。

如果想运行图片:

python tenforflow_infer.py  --img-path /path/to/your/img

比如,img 目录中作者放了一些图片的,选择 demo2.jpg。

python tenforflow_infer.py  --img-path  img/demo2.jpg

运行结果:

如果想运行运行视频:

python tenforflow_infer.py --img-mode 0 --video-path /path/to/video

/path/to/video 为视频所在的路径+视频名。

如果想实时使用摄像头检测:

python tenforflow_infer.py --img-mode 0 --video-path 0

这里的 0 ,代表在电脑中设备号;0 默认为电脑自带的摄像头。

如果想使用外接摄像头,可以改为 1 (比如外接上一个 USB 摄像头)。

这里看一下 tenforflow_infer.py 代码:

# -*- coding:utf-8 -*-
import cv2
import time
import argparseimport numpy as np
from PIL import Image
from keras.models import model_from_json
from utils.anchor_generator import generate_anchors
from utils.anchor_decode import decode_bbox
from utils.nms import single_class_non_max_suppression
from load_model.tensorflow_loader import load_tf_model, tf_inference#sess, graph = load_tf_model('FaceMaskDetection-master\models\face_mask_detection.pb')
sess, graph = load_tf_model('models\face_mask_detection.pb')
# anchor configuration
feature_map_sizes = [[33, 33], [17, 17], [9, 9], [5, 5], [3, 3]]
anchor_sizes = [[0.04, 0.056], [0.08, 0.11], [0.16, 0.22], [0.32, 0.45], [0.64, 0.72]]
anchor_ratios = [[1, 0.62, 0.42]] * 5# generate anchors
anchors = generate_anchors(feature_map_sizes, anchor_sizes, anchor_ratios)#用于推断,批大小为1,模型输出形状为[1,N,4],因此将锚点的dim扩展为[1,anchor_num,4]
anchors_exp = np.expand_dims(anchors, axis=0)
id2class = {0: 'Mask', 1: 'NoMask'}def inference(image, conf_thresh=0.5, iou_thresh=0.4, target_shape=(160, 160), draw_result=True, show_result=True):'''  检测推理的主要功能# :param image:3D numpy图片数组#  :param conf_thresh:分类概率的最小阈值。#  :param iou_thresh:网管的IOU门限#  :param target_shape:模型输入大小。#  :param draw_result:是否将边框拖入图像。#  :param show_result:是否显示图像。'''# image = np.copy(image)output_info = []height, width, _ = image.shapeimage_resized = cv2.resize(image, target_shape)image_np = image_resized / 255.0  # 归一化到0~1image_exp = np.expand_dims(image_np, axis=0)y_bboxes_output, y_cls_output = tf_inference(sess, graph, image_exp)# remove the batch dimension, for batch is always 1 for inference.y_bboxes = decode_bbox(anchors_exp, y_bboxes_output)[0]y_cls = y_cls_output[0]# 为了加快速度,请执行单类NMS,而不是多类NMS。bbox_max_scores = np.max(y_cls, axis=1)bbox_max_score_classes = np.argmax(y_cls, axis=1)# keep_idx是nms之后的活动边界框。keep_idxs = single_class_non_max_suppression(y_bboxes, bbox_max_scores, conf_thresh=conf_thresh,iou_thresh=iou_thresh)for idx in keep_idxs:conf = float(bbox_max_scores[idx])class_id = bbox_max_score_classes[idx]bbox = y_bboxes[idx]# 裁剪坐标,避免该值超出图像边界。xmin = max(0, int(bbox[0] * width))ymin = max(0, int(bbox[1] * height))xmax = min(int(bbox[2] * width), width)ymax = min(int(bbox[3] * height), height)if draw_result:if class_id == 0:color = (0, 255, 0)else:color = (255, 0, 0)cv2.rectangle(image, (xmin, ymin), (xmax, ymax), color, 2)cv2.putText(image, "%s: %.2f" % (id2class[class_id], conf), (xmin + 2, ymin - 2),cv2.FONT_HERSHEY_SIMPLEX, 1, color)output_info.append([class_id, conf, xmin, ymin, xmax, ymax])if show_result:Image.fromarray(image).show()return output_infodef run_on_video(video_path, output_video_name, conf_thresh):cap = cv2.VideoCapture(video_path)height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)fps = cap.get(cv2.CAP_PROP_FPS)fourcc = cv2.VideoWriter_fourcc(*'XVID')#writer = cv2.VideoWriter(output_video_name, fourcc, int(fps), (int(width), int(height)))total_frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)if not cap.isOpened():raise ValueError("Video open failed.")returnstatus = Trueidx = 0while status:start_stamp = time.time()status, img_raw = cap.read()img_raw = cv2.cvtColor(img_raw, cv2.COLOR_BGR2RGB)read_frame_stamp = time.time()if (status):inference(img_raw,conf_thresh,iou_thresh=0.5,target_shape=(260, 260),draw_result=True,show_result=False)cv2.imshow('image', img_raw[:, :, ::-1])cv2.waitKey(1)inference_stamp = time.time()# writer.write(img_raw)write_frame_stamp = time.time()idx += 1print("%d of %d" % (idx, total_frames))print("read_frame:%f, infer time:%f, write time:%f" % (read_frame_stamp - start_stamp,inference_stamp - read_frame_stamp,write_frame_stamp - inference_stamp))# writer.release()if __name__ == "__main__":parser = argparse.ArgumentParser(description="Face Mask Detection")parser.add_argument('--img-mode', type=int, default=0, help='set 1 to run on image, 0 to run on video.')  #这里设置为1:检测图片;还是设置为0:视频文件(实时图像数据)检测parser.add_argument('--img-path', type=str, help='path to your image.')parser.add_argument('--video-path', type=str, default='0', help='path to your video, `0` means to use camera.')# parser.add_argument('--hdf5', type=str, help='keras hdf5 file')args = parser.parse_args()if args.img_mode:imgPath = args.img_path#img = cv2.imread("imgPath")img = cv2.imread(imgPath)img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)inference(img, show_result=True, target_shape=(260, 260))else:video_path = args.video_pathif args.video_path == '0':video_path = 0run_on_video(video_path, '', conf_thresh=0.5)

测试集 PR 曲线

因为 WIDER face 是一个任务比较复杂的数据集,模型又设计的非常小,所以对于人脸的 PR 曲线并不是那么性感。这点可以通过设计大模型来提升对于小人脸的检测效果。

再次感谢 AIZOOTech 的开源项目 —— FaceMaskDetection。

【end】

原力计划

《原力计划【第二季】- 学习力挑战》正式开始!即日起至 3月21日,千万流量支持原创作者!更有专属【勋章】等你来挑战

推荐阅读

  • 2019年度CSDN博客之星TOP10榜单揭晓,你上榜了吗?

  • Javascript函数之深入浅出递归思想,附案例与代码!

  • 不看就亏系列!这里有完整的 Hadoop 集群搭建教程,和最易懂的 Hadoop 概念!| 附代码

  • 智能合约编写之Solidity的基础特性

  • 微信七年「封链」史

  • 计算机博士、加班到凌晨也要化妆、段子手……IT 女神驾到!

  • 你点的每个“在看”,我都认真当成了AI


http://lihuaxi.xjx100.cn/news/272543.html

相关文章

设计文档

因为内容过多,只发一部分,详见设计文档。 本详细设计说明书编写的目的是说明程序模块的设计考虑,包括程序描述、输入/输出、算法和流程逻辑等,为软件编程和系统维护提供基础。 本说明书是设计阶段的成果,说明了功能分配…

AS1.0(2.0)中的XML示例

虽然Flash早就升级为AS3.0&#xff0c;但是FMS的服务端编程依然仅支持AS1.0(2.0)&#xff0c;服务端与.net通讯的最简单方式莫过于请求一个RESTful的webService或wcf&#xff0c;通过它们返回的xml来获取数据。 var _xml:XML new XML("<ArrayOfstring xmlns\"htt…

基于 Spring Cloud 开发的分布式系统,遇到爬虫、接口盗刷怎么办?

点击上方“方志朋”&#xff0c;选择“设为星标”回复”666“获取新整理的面试文章来源 | oschina.net/p/kk-anti-reptilekk-anti-reptile是&#xff0c;适用于基于spring-boot开发的分布式系统的反爬虫组件。系统要求基于spring-boot开发(spring-boot1.x, spring-boot2.x均可)…

smarty 模板引擎

http://blog.csdn.net/zuiaituantuan/article/details/5951242 http://wenku.baidu.com/link?url-UHlSnTXOOAjFG1KjX6T9sEG6V4hNAMfRDpMuRRnc_FKbFAxiE5Ntk4lzxSm-7Z531uWdfvgYx81sdC61SgTZm7q8FdUt3gSs7ZlC0JR1SW转载于:https://www.cnblogs.com/hxjbc/p/4441879.html

国内高校硕博补贴大公开!(某校博士在读已经年薪 25w 了)

点击上方“视学算法”&#xff0c;选择加"星标"或“置顶”重磅干货&#xff0c;第一时间送达转自 | 中国农业大学论坛&#xff0c;论文项目硕博招聘仅作学术分享&#xff0c;不代表本公众号立场&#xff0c;侵权联系删除之前有消息称&#xff0c;中科大为吸引优质的博…

听说过代码洁癖,Bug洁癖怎么解?

来源 | Python编程时光&#xff08;ID: Cool-Python&#xff09;当我们写的一个脚本或程序发生各种不可预知的异常时&#xff0c;如果我们没有进行捕获处理的时候&#xff0c;通常都会致使程序崩溃退出&#xff0c;并且会在终端打印出一堆 密密麻麻 的 traceback 堆栈信息来告诉…

VS code 插件配置手册

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶”重磅干货&#xff0c;第一时间送达VS code 插件配置手册C/C Tools插件---C/C支持安装库文件的配置GDB本地调试配置GDB远程调试配置Remote VSCode插件---远程编辑文件安装环境配置在本地端的配置在远程端的配…

Python 哪种方式循环最快,或许颠覆你的认知

众所周知&#xff0c;Python 不是一种执行效率较高的语言。此外在任何语言中&#xff0c;循环都是一种非常消耗时间的操作。假如任意一种简单的单步操作耗费的时间为 1 个单位&#xff0c;将此操作重复执行上万次&#xff0c;最终耗费的时间也将增长上万倍。 和是 Python 中常…