基于Tensorflow+SDD+Python人脸口罩识别系统(深度学习)含全部工程源码及模型+视频演示+图片数据集
目录
- 前言
- 总体设计
- 系统整体结构图
- 系统流程图
- 运行环境
- Python 环境
- Anaconda 环境搭建
- 模块实现
- 1. 数据预处理
- 2. 模型构建及算法实现
- 3. 模型生成
- 系统测试
- 1. 训练准确率
- 2. 运行结果
- 工程源代码下载
- 其它资料下载
前言
在当今全球范围内,新冠疫情对我们的生活方式带来了巨大的改变。在公共场所,佩戴口罩成为了常态,以保护我们自己和他人的健康安全。然而,这也给人脸识别技术带来了新的挑战。如何准确地辨别佩戴口罩的人成为了一个重要的问题。
本文介绍的一种基于Tensorflow、SDD和Python的人脸口罩识别系统,结合了深度学习技术和计算机视觉算法,能够高效地检测人脸并准确地判断是否佩戴口罩。通过使用这个系统,我们可以更好地管理公共场所的出入口,确保员工、顾客和访客的健康安全。
当然,您可以在文末下载本系统的全部工程源码(包括Web demo)进行个人二次开发。
总体设计
本部分包括系统整体结构图和系统流程图。
系统整体结构图
系统整体结构如图所示。
系统流程图
系统流程如图所示。
运行环境
本部分包括 Python 环境和Anaconda 环境。
Python 环境
需要 Python 3.5 及以上配置,在 Windows 环境下推荐下载 Anaconda 完成 Python 所需的配置,下载地址:https://www.anaconda.com/,也可以下载虚拟机在 Linux 环境下运行代码。
Anaconda 环境搭建
打开 Anaconda Prompt,输入清华仓库镜像。
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config –set show_channel_urls yes
创建 Python3.5 的环境,名称为 TensorFlow:
conda create -n tensorflow python=3.5
有需要确认的地方,都输入 y。
在 Anaconda Prompt 中激活 TensorFlow 环境:
activate tensorflow
安装 CPU 版本的 TensorFlow:
pip install –upgrade --ignore-installed tensorflow
安装完毕。
模块实现
本项目包括 3 个模块:数据预处理、模型构建及算法实现、模型生成,下面分别给出各模块的功能介绍及相关代码。
1. 数据预处理
WIDER Face 和 MAFA 这两个数据集包含了大量的人脸及人脸佩戴口罩的图片,但只使用WIDER Face 数据集,所含其他遮挡脸部的图片较少(如用手挡住脸部),会出现识别偏差的情况。因此,从 WIDER Face 数据集中选取 3894 张图片、MAFA 数据集中选取 4064张图片,包含戴口罩、不戴口罩、用其他物体遮挡面部共 8000 张图片进行训练。
数据集下载链接:https://pan.baidu.com/s/1nsQf_Py5YyKm87-8HiyJeQ 提取码:eyfz
2. 模型构建及算法实现
数据加载进模型之后,需要定义模型结构,并进行算法实现。
1. 定义模型结构
定义的架构共 28 个卷积层,其中有 8 个主干层,即特征提取层;20 个定位和分类层。每个卷积层的通道数是 32、64、128 三种,为了能够更好地运行在终端设备上,模型设计的较小,共 101.5 万个参数,输入为 260*260 大小的图片。
2. 算法实现
基于 SSD 检测模型推理,实现以下三步:生成全部的 anchor、网络输出值根据全部的anchors 解码、NMS(非极大值抑制)即可,即以下三个函数:
function anchorGenerator()
、function decodeBBox()
、function nonMaxSuppression()
训练目标检测模型,最重要的是合理设置 anchor 的大小和宽高比。所谓 anchor 是指在图像上预设好的不同大小,不同长宽比的参照框。假设一个 256*256 大小的图片,经过 64、128 和 256 倍下采样,会产生 4X4、2X2、1X1 大小的特征图,每个点上都设置三个不同大小的 anchor。在实际的 SSD 模型中,300X300 的输入下,anchor 数量也特别多,在38X38、19X19、10X10、5X5、3X3、1X1 的六个特征图上,每个点分别设置 4、6、6、6、6、4 个不同大小和长宽比的 anchor,一共有 38X38X4+ 19X19X6+ 10X10X6+ 5X5X6+3X3X4+ 1X1X4= 8732个 anchor。借助卷积神经网络,可直接输出每个 anchor 是否包含(与物体有较大重叠,也就是 IoU 较大)物体,以及被检测物体相对本 anchor 的中心点偏移、长宽比例。
在训练的时候,也就是给每张图片物体的 Bounding Box,相对于 anchor 进行编码,如果物体 Bounding Box 与某个 anchor 的 IoU 较大,例如,大于 0.5 认为是正样本,否则是负样本。
对于检测网络,有的实现,是用没有归一化的坐标,例如,anchor 设置为(30, 42)尺度大小,但是,有的算法实现,是将坐标和物体框的宽高比,除以图片的宽和高。如果图片都是正方形的,那归一化后宽高比没有变化,如果是 1080P 分辨率的摄像头,那么长宽比是16:9。本来就小的宽度,再除以 1920,而高度除以 1080,会导致归一化后的人脸高度是宽度的 2 倍左右。归一化处理即:
根据数据的分布,将五个定位层的 anchor 的宽高比统一设置为 1,0.62, 0.42。(转换为高宽比,也就是约 1,1.6:1,2.4:1)。
3. 代码实现
# -*- 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('models/face_mask_detection.pb')
# anchor configuration
#特征图大小
feature_map_sizes = [[33, 33], [17, 17], [9, 9], [5, 5], [3, 3]]
#anchor大小
anchor_sizes = [[0.04, 0.056], [0.08, 0.11], [0.16, 0.22], [0.32, 0.45], [0.64, 0.72]]
#anchor宽高比
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:是否显示图像。'''output_info = []height, width, _ = image.shape#获取初始图像的长宽image_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)#构建图,返回包含预测结果的框和颜色# 删除批次维度,因为用于推断批次始终是1。y_bboxes = decode_bbox(anchors_exp, y_bboxes_output)[0]y_cls = y_cls_output[0]# 为了加快速度,执行单类 NMS,而不是多类 NMS。即戴口罩人脸和不戴口罩人脸两个类别一起做NMSbbox_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)
3. 模型生成
该应用主要有两部分,一是对图片中的人脸进行识别;二是对视频中出现的人脸进行识别。
1. 调用训练好的模型
sess, graph = load_tf_model('models\face_mask_detection.pb') #载入模型
2. 图片处理
1)anchor 设定完成后,进行识别
2)解码及非极大值抑制
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, 0.8, color)#图片,添加的文字,左上角坐标,字体,字体大小,颜色output_info.append([class_id, conf, xmin, ymin, xmax, ymax])if show_result:Image.fromarray(image).show()return output_info
3. 视频处理
#视频检测
def 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')#XVID是MPEG-4编码类型,文件名后缀为.avi# 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()#第一个参数ret 为True 或者False,代表有没有读取到图片# #第二个参数frame表示截取到一帧的图片img_raw = cv2.cvtColor(img_raw, cv2.COLOR_BGR2RGB)#色彩空间BGR转为RGBread_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 += 1#循环直到识别到口罩,然后输出帧数和时间.print("%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()
系统测试
本部分包括模型训练准确率及模型测试效果。
1. 训练准确率
戴口罩的人脸识别准确率接近 92%,可识别绝大部分戴口罩的人脸,如图所示。
2. 运行结果
1. 在命令行中运行
# 跟命令行有关的
if __name__ == "__main__":# 跟命令行有关的parser = argparse.ArgumentParser(description="Face Mask Detection") # 创建解析器parser.add_argument('--img-mode', type=int, default=1, 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()# 把parser中设置的所有"add_argument"给返回到args子类实例当中, 那么parser中增加的属性内容都会在args实例中,使用即可。if args.img_mode:imgPath = args.img_path#图片路径img = cv2.imread(imgPath)#读取图片img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)#转换色彩空间(R,G,B换个位置)inference(img, show_result=True, target_shape=(260, 260))else:video_path = args.video_path#视频路径if args.video_path == '0':video_path = 0run_on_video(video_path, '', conf_thresh=0.5)
运行方法如下:
- 如果您要运行图片,需要:
python tensorflow_infer.py --img-path /path/to/your/img
如果您要在视频上运行,需要:
python tensorflow_infer.py --img-mode 0 --video-path /path/to/video
如果要打开本地摄像头, video_path 填写 0 就可以:
python tensorflow_infer.py --img-mode 0 --video-path 0
2. 运行结果
照片测试结果如图所示:
工程源代码下载
详见本人博客资源下载页
其它资料下载
如果大家想继续了解人工智能相关学习路线和知识体系,欢迎大家翻阅我的另外一篇博客《重磅 | 完备的人工智能AI 学习——基础知识学习路线,所有资料免关注免套路直接网盘下载》
这篇博客参考了Github知名开源平台,AI技术平台以及相关领域专家:Datawhale,ApacheCN,AI有道和黄海广博士等约有近100G相关资料,希望能帮助到所有小伙伴们。
相关文章:

基于Tensorflow+SDD+Python人脸口罩识别系统(深度学习)含全部工程源码及模型+视频演示+图片数据集
目录 前言总体设计系统整体结构图系统流程图 运行环境Python 环境Anaconda 环境搭建 模块实现1. 数据预处理2. 模型构建及算法实现3. 模型生成 系统测试1. 训练准确率2. 运行结果 工程源代码下载其它资料下载 前言 在当今全球范围内,新冠疫情对我们的生活方式带来了…...
abc200 D 鸽巢原理
题意:https://www.luogu.com.cn/problem/AT_abc200_d 思路:对于一个序列最多有多少个模数,其实就是子序列个数,所以当子序列个数超过200是那么答案一定存在,那么我们就可以直接枚举了,所以我们直接枚举前八…...

QT day1 (图形界面设计)
要求: 功能函数模块 #include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow) {qDebug("%s","hello world");//qDebug() << &qu…...

JS逆向系列之猿人学爬虫第9题-动态cookie2
文章目录 目标参数流程分析js代码Python调用测试目标 https://match.yuanrenxue.cn/match/9参数流程分析 二次请求cookie携带m 第一次请求响应内容格式化之后是这样的: < body > < script src = "/static/match/safety/match9/udc.js" > <...

Java ~ Reference ~ FinalizerHistogram【总结】
前言 文章 相关系列:《Java ~ Reference【目录】》(持续更新)相关系列:《Java ~ Reference ~ FinalizerHistogram【源码】》(学习过程/多有漏误/仅作参考/不再更新)相关系列:《Java ~ Referenc…...

【MySQL】一文带你了解SQL
🎬 博客主页:博主链接 🎥 本文由 M malloc 原创,首发于 CSDN🙉 🎄 学习专栏推荐:LeetCode刷题集! 🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指…...

python基础学习3【NumPy矩阵与通用函数【矩阵相乘+平方+广播机制+转置】+ save、load、sort、repeat、unique、鸢尾花1】
NumPy矩阵与通用函数 a np.mat([[1,2],[3,4]])#生成矩阵b np.matrix([[1,7],[6,4]])np.bmat("a b") 矩阵的运算 矩阵特有属性: 属性 说明 T自身转置H共轭转置I逆矩阵A自身数据的二维数据视图 例如: np.matrix(a).T 矩阵相乘:…...

【Spring学习之更简单的读取和存储Bean对象】教会你使用五大类注解和方法注解去存储 Bean 对象
前言: 💞💞今天我们依然是学习Spring,这里我们会更加了解Spring的知识,知道Spring是怎么更加简单的读取和存储Bean对象的。也会让大家对Spring更加了解。 💟💟前路漫漫,希望大家坚持…...
微客云原生淘宝客APP小程序系统如何定制
淘宝是中国最大的电商网站,而淘宝的火热,也兴起了一个全新的行业,淘宝客。就是帮助淘宝商家推广商品的一种职业。目前淘宝每年有百分之10的销售业绩都是通过淘宝客贡献的,所以说淘宝客的市场越来越大。但是淘宝客要推广自己的产品…...
QT CTK插件开发(六) 多对一插件
CTK在软件的开发过程中可以很好的降低复杂性、使用 CTK Plugin Framework 提供统一的框架来进行开发增加了复用性 将同一功能打包可以提供多个应用程序使用避免重复性工作、可以进行版本控制提供了良好的版本更新迭代需求、并且支持动态热拔插 动态更新、开发更加简单快捷 方便…...
【Spring Boot整合MyBatis教程】
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发…...

ThinkPHP3.2.3通过局域网手机访问项目
折腾一上午, 试了nginx, 试了修改Apache的httpd.conf 试了关闭代理 试了手动配置网络 试了关闭防火墙 试了添加防火墙入站出站规则 问了五个ChatGPT 都没解决。 记录一下 wampserver3.0.4 Apache2.4.18 PHP 5.6.19 MySQL 5.7.11 所有服务启…...
2306C++虚继承
构 B{无序映<串,串>列;整 大小0;空 f(){大小;} }; //虚继承其实不错,但是占位置,占空间.构 C:虚 公 B{空 g(){} };构 D:虚 公 C{空 h(){} }; 构 S{}; 构 T{}; //元<类 T>构 E:虚 公 D{}; 构 E:虚 公 D{};空 主(){//E<S>e;e.f();打印(e.大小);//E<T>m;m…...
使用oracle遇到问题笔记
一、oracle还原到不同版本的oracle数据库报错和解决办法 产生:执行imp导入dmp备份文件时报错 错误内容:导入失败提示:“不是有效的导出文件, 标头验证失败”解决方法 解决办法:http://t.csdn.cn/pJyhc...

我和老刘又被搞惨了
前两天在调试PHY的时候遇到了一堆问题,老刘都不耐其烦的搞定了,这次我们开始调试音频部分,音频部分很简单,无非就是录音,要是能把录音的音频拿到了,那就万事大吉了。老刘也是信心满满,老刘对我说…...
DDD--基本概念
最近项目组一直在推DDD领域驱动设计,现就一些个人理解分享如下。 DDD(领域驱动设计)是一种软件开发方法论,旨在解决复杂业务场景下的软件设计与开发问题。以下是DDD的基本概念: 领域(Domain)&…...

chatgpt赋能python:Python多行注释
Python 多行注释 在 Python 中,我们经常需要写注释来解释代码或者用于调试。Python 的注释分为单行注释和多行注释,本文主要介绍 Python 中如何多行注释。 单行注释 在 Python 中,单行注释以符号 # 开头,可以写在代码的任何位置…...
JSP详细基础教学
目录 前言 环境设置 创建JSP文件 编写基本的JSP代码 部署和运行JSP页面 基础语法 前言 JSP(JavaServer Pages)是一种用于开发动态网页的Java技术。它允许将Java代码嵌入HTML页面中,以便在服务器端生成动态内容。在本次教程中ÿ…...
mysql修改登录用户的密码
文章目录 mysql5.7即mysql7.0 的修改方式mysql5.8即mysql8.0的修改方式如果修改完密码,发现旧密码和新密码都登录不进来怎么办?发现设置密码老报错 mysql5.7即mysql7.0 的修改方式 1.如果是使用docker里装的mysql 首先使用 [rootlocalhost /]# docker p…...
SNAT和DNAT
SNAT和DNAT 一、SNAT的策略及应用: 1.SNAT: (1)定义:又称源地址转换。源地址转换是内网地址向外访问时,发起访问的内网ip地址转换为指定的ip地址(可指定具体的服务以及相应的端口或端口范围&…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...

Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...

抽象类和接口(全)
一、抽象类 1.概念:如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象,这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法,包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中,⼀个类如果被 abs…...