diff --git a/demo/mask_detection/README.md b/demo/mask_detection/README.md index ad8aa9204749d58907a7fa8a54f43a93efae56e9..1a6314d059fc52919954e25ad5275fb3f47e5a94 100644 --- a/demo/mask_detection/README.md +++ b/demo/mask_detection/README.md @@ -1,27 +1,35 @@ -# PaddleHub实现口罩佩戴检测应用 +# 基于PaddleHub实现口罩佩戴检测应用 -## 0 项目介绍 +本文档基于飞桨本次开源的口罩佩戴识别模型, 提供了一个完整的支持视频流的WebDemo,以及高性能的Python和C++集成部署方案, 可用于不同场景下的软件集成。 + +## 目录 +- [1. 搭建视频流场景的WebDemo](#1搭建视频流场景WebDemo) +- [2. 高性能Python部署方案](#2高性能Python部署方案) +- [3. 高性能C++部署方案](#3高性能c部署方案) + +## 1. 搭建视频流场景WebDemo ![image](https://note.youdao.com/yws/public/resource/b0a4695bc7d58aed3b1ff797409aee1e/BB6BC87A45D146CEBA7BF237B5383835?ynotemdtimestamp=1582271320612) + ### [>点击查看视频链接<](https://www.bilibili.com/video/av88962128) -##### 背景 -本项目可以部署在大型场馆出入口,学校,医院,交通通道出入口,人脸识别闸机,机器人上,支持的方案有:安卓方案(如RK3399的人脸识别机,机器人),ubuntu 边缘计算,windowsPC+摄像头,识别率80%~90%,如果立项使用场景可以达到 99% (如:人脸识别机场景)。但是限于清晰度和遮挡关系,对应用场景有一些要求。 +### 背景 +本项目可以部署在大型场馆出入口,学校,医院,交通通道出入口,人脸识别闸机,机器人上,支持的方案有:安卓方案(如RK3399的人脸识别机,机器人),Ubuntu 边缘计算,WindowsPC+摄像头,识别率80%~90%,如果立项使用场景可以达到 99% (如:人脸识别机场景)。但是限于清晰度和遮挡关系,对应用场景有一些要求。 -##### 效果分析 -可以看到识别率在80~90%之前,稍小的人脸有误识别的情况,有些挡住嘴的场景也被误识别成了戴口罩,一个人带着口罩,鼻子漏出来识别成没有戴口罩,这个是合理的因为的鼻子漏出来是佩戴不规范。初步判断,这个模型应用在门口,狭长通道,人脸识别机所在位置都是可以的。 +### 效果分析 +可以看到识别率在80~90%之前,稍小的人脸有误识别的情况,有些挡住嘴的场景也被误识别成了戴口罩,一个人带着口罩,鼻子漏出来识别成没有戴口罩,这个是合理的因为的鼻子漏出来是佩戴不规范。这个模型应用在门口,狭长通道,人脸识别机所在位置都是可以的。 ![image](https://note.youdao.com/yws/public/resource/b0a4695bc7d58aed3b1ff797409aee1e/7E12DBD91D1D4AB5B33C84786D519065?ynotemdtimestamp=1582271320612)![image](https://note.youdao.com/yws/public/resource/b0a4695bc7d58aed3b1ff797409aee1e/2BD974FB990C4C448B30B04194545054?ynotemdtimestamp=1582271320612)![image](https://note.youdao.com/yws/public/resource/b0a4695bc7d58aed3b1ff797409aee1e/E49E34A071F8484D948511430FAB0360?ynotemdtimestamp=1582271320612) -## 1 部署环境 +### 1. 部署环境 参考: https://www.paddlepaddle.org.cn/install/quick -### 安装paddlehub +#### 安装paddlehub `pip install paddlehub` -## 2 开发识别服务 -### 加载预训练模型 +### 2. 开发识别服务 +#### 加载预训练模型 ```python import paddlehub as hub module = hub.Module(name="pyramidbox_lite_mobile_mask") #口罩检测模型 @@ -29,7 +37,7 @@ module = hub.Module(name="pyramidbox_lite_mobile_mask") #口罩检测模型 >以上语句paddlehub会自动下载口罩检测模型 "pyramidbox_lite_mobile_mask" 不需要提前下载模型 -### OpenCV打开摄像头或视频文件 +#### OpenCV打开摄像头或视频文件 ```python import cv2 @@ -37,19 +45,17 @@ capture = cv2.VideoCapture(0) # 打开摄像头 # capture = cv2.VideoCapture('./2.mp4') # 打开视频文件 while(1): ret, frame = capture.read() # frame即视频的一帧数据 - if ret == False: break cv2.imshow('Mask Detection', frame) - if cv2.waitKey(1) & 0xFF == ord('q'): break cv2.destroyAllWindows() ``` -### 口罩检测 +#### 口罩佩戴检测 ```python # frame为一帧数据 @@ -100,6 +106,7 @@ for result in results: >原DEMO中是英文+置信度显示在框的上面,尝试改为中文,遇到字体问题,以下是解决办法 ### 图片写入中文 + 需要事先准备ttf/otf等格式的字体文件 ```python def paint_chinese_opencv(im,chinese,position,fontsize,color_bgr):#opencv输出中文 @@ -152,130 +159,9 @@ with open("./result/2-mask_detection.json","w") as f: >此处可以按照自己的应用需要改为输出到mysql,Redis,kafka ,MQ 供应用消化数据 -### 完整代码如下 -```python -import paddlehub as hub -import cv2 -from PIL import Image, ImageDraw, ImageFont -import numpy as np -import json -import os - -module = hub.Module(name="pyramidbox_lite_mobile_mask") - - -def paint_chinese_opencv(im,chinese,position,fontsize,color_bgr):#opencv输出中文 - img_PIL = Image.fromarray(cv2.cvtColor(im,cv2.COLOR_BGR2RGB))# 图像从OpenCV格式转换成PIL格式 - font = ImageFont.truetype('思源黑体SC-Heavy.otf',fontsize,encoding="utf-8") # 加载字体文件 - #color = (255,0,0) # 字体颜色 - #position = (100,100)# 文字输出位置 - color = color_bgr[::-1] - draw = ImageDraw.Draw(img_PIL) - draw.text(position,chinese,font=font,fill=color)# PIL图片上打印汉字 # 参数1:打印坐标,参数2:文本,参数3:字体颜色,参数4:字体 - img = cv2.cvtColor(np.asarray(img_PIL),cv2.COLOR_RGB2BGR)# PIL图片转cv2 图片 - return img - - -result_path = './result' -if not os.path.exists(result_path): - os.mkdir(result_path) - - -name = "./result/1-mask_detection.mp4" -width = 1920 -height = 1080 -fps = 30 -fourcc = cv2.VideoWriter_fourcc(*'mp4v') -writer = cv2.VideoWriter(name, fourcc, fps, (width, height)) - -maskIndex = 0 -index = 0 -data = [] - -# capture = cv2.VideoCapture(0) # 打开摄像头 -capture = cv2.VideoCapture('./2.mp4') # 打开视频文件 -while(1): - frameData = {} - - ret, frame = capture.read() # frame即视频的一帧数据 - - if ret == False: - break - - frame_copy = frame.copy() +完整代码可以参考`mask_detection.py` - input_dict = {"data": [frame]} - - results = module.face_detection(data=input_dict) - # print(results) - - maskFrameDatas = [] - for result in results: - # print(result) - - label = result['data']['label'] - - confidence_origin = result['data']['confidence'] - confidence = round(confidence_origin, 2) - confidence_desc = str(confidence) - - top, right, bottom, left = int(result['data']['top']), int(result['data']['right']), int(result['data']['bottom']), int(result['data']['left']) - - #将当前帧保存为图片 - img_name = "avatar_%d.png" % (maskIndex) - path = "./result/" + img_name - image = frame[top - 10: bottom + 10, left - 10: right + 10] - cv2.imwrite(path, image,[int(cv2.IMWRITE_PNG_COMPRESSION), 9]) - - maskFrameData = {} - maskFrameData['top'] = top - maskFrameData['right'] = right - maskFrameData['bottom'] = bottom - maskFrameData['left'] = left - maskFrameData['confidence'] = float(confidence_origin) - maskFrameData['label'] = label - maskFrameData['img'] = img_name - - maskFrameDatas.append(maskFrameData) - - maskIndex += 1 - - color = (0, 255, 0) - label_cn = "有口罩" - if label == 'NO MASK': - color = (0, 0, 255) - label_cn = "无口罩" - - cv2.rectangle(frame_copy, (left, top), (right, bottom), color, 3) - # cv2.putText(frame, label, (left, top-10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 2) - frame_copy = paint_chinese_opencv(frame_copy, label_cn, (left, top-36), 24, color) - - - writer.write(frame_copy) - - cv2.imshow('Mask Detection', frame_copy) - - frameData['frame'] = index - # frameData['seconds'] = int(index/fps) - frameData['data'] = maskFrameDatas - - data.append(frameData) - - print(json.dumps(frameData)) - - index += 1 - - if cv2.waitKey(1) & 0xFF == ord('q'): - break - -with open("./result/2-mask_detection.json","w") as f: - json.dump(data, f) - -writer.release() - -cv2.destroyAllWindows() -``` -## 3 制作网页呈现效果 +## 3.制作网页呈现效果 此DEMO是显示一个固定视频,分析导出的 json 渲染到网页里面,如需实时显示需要再次开发 ### python 导出的数据 @@ -293,11 +179,19 @@ cv2.destroyAllWindows() ![image](https://note.youdao.com/yws/public/resource/b0a4695bc7d58aed3b1ff797409aee1e/6329B326216A4950BF35E0CB37CDC58F?ynotemdtimestamp=1582271320612) -## 4 欢迎交流 +## 2. 高性能Python部署集成方案 +更多信息可以参考[文档](./python/README.md) -**百度飞桨合作伙伴:** +## 3. 高性能C++部署集成方案 + +更多信息可以参考[文档](./cpp/README.md) + + +## 欢迎交流 + +**百度飞桨合作伙伴:** ![image](https://note.youdao.com/yws/public/resource/b0a4695bc7d58aed3b1ff797409aee1e/DC72DE1CF51747138871BB0E3D54E20D?ynotemdtimestamp=1582271320612) diff --git a/demo/mask_detection/mask_detection/PaddleMaskDetection.py b/demo/mask_detection/mask_detection/PaddleMaskDetection.py deleted file mode 100644 index 4b042baff051b2e1908943c4f7272a669d21d039..0000000000000000000000000000000000000000 --- a/demo/mask_detection/mask_detection/PaddleMaskDetection.py +++ /dev/null @@ -1,127 +0,0 @@ -# -*- coding:utf-8 -*- -import paddlehub as hub -import cv2 -from PIL import Image, ImageDraw, ImageFont -import numpy as np -import json -import os - -module = hub.Module(name="pyramidbox_lite_mobile_mask") - - -#opencv输出中文 -def paint_chinese(im, chinese, position, fontsize, color_bgr): - img_PIL = Image.fromarray(cv2.cvtColor( - im, cv2.COLOR_BGR2RGB)) # 图像从OpenCV格式转换成PIL格式 - font = ImageFont.truetype( - 'SourceHanSansSC-Medium.otf', fontsize, encoding="utf-8") - #color = (255,0,0) # 字体颜色 - #position = (100,100)# 文字输出位置 - color = color_bgr[::-1] - draw = ImageDraw.Draw(img_PIL) - # PIL图片上打印汉字 # 参数1:打印坐标,参数2:文本,参数3:字体颜色,参数4:字体 - draw.text(position, chinese, font=font, fill=color) - img = cv2.cvtColor(np.asarray(img_PIL), cv2.COLOR_RGB2BGR) # PIL图片转cv2 图片 - return img - - -result_path = './result' -if not os.path.exists(result_path): - os.mkdir(result_path) - -name = "./result/1-mask_detection.mp4" -width = 1920 -height = 1080 -fps = 30 -fourcc = cv2.VideoWriter_fourcc(*'mp4v') -writer = cv2.VideoWriter(name, fourcc, fps, (width, height)) - -maskIndex = 0 -index = 0 -data = [] - -capture = cv2.VideoCapture(0) # 打开摄像头 -#capture = cv2.VideoCapture('./2.mp4') # 打开视频文件 -while (1): - frameData = {} - - ret, frame = capture.read() # frame即视频的一帧数据 - - if ret == False: - break - - frame_copy = frame.copy() - - input_dict = {"data": [frame]} - - results = module.face_detection(data=input_dict) - # print(results) - - maskFrameDatas = [] - for result in results: - # print(result) - - label = result['data']['label'] - - confidence_origin = result['data']['confidence'] - confidence = round(confidence_origin, 2) - confidence_desc = str(confidence) - - top, right, bottom, left = int(result['data']['top']), int( - result['data']['right']), int(result['data']['bottom']), int( - result['data']['left']) - - #将当前帧保存为图片 - img_name = "avatar_%d.png" % (maskIndex) - path = "./result/" + img_name - image = frame[top - 10:bottom + 10, left - 10:right + 10] - cv2.imwrite(path, image, [int(cv2.IMWRITE_PNG_COMPRESSION), 9]) - - maskFrameData = {} - maskFrameData['top'] = top - maskFrameData['right'] = right - maskFrameData['bottom'] = bottom - maskFrameData['left'] = left - maskFrameData['confidence'] = float(confidence_origin) - maskFrameData['label'] = label - maskFrameData['img'] = img_name - - maskFrameDatas.append(maskFrameData) - - maskIndex += 1 - - color = (0, 255, 0) - label_cn = "有口罩" - if label == 'NO MASK': - color = (0, 0, 255) - label_cn = "无口罩" - - cv2.rectangle(frame_copy, (left, top), (right, bottom), color, 3) - # cv2.putText(frame, label, (left, top-10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 2) - origin_point = (left, top - 36) - frame_copy = paint_chinese(frame_copy, label_cn, origin_point, 24, - color) - - writer.write(frame_copy) - - cv2.imshow('Mask Detection', frame_copy) - - frameData['frame'] = index - # frameData['seconds'] = int(index/fps) - frameData['data'] = maskFrameDatas - - data.append(frameData) - - print(json.dumps(frameData)) - - index += 1 - - if cv2.waitKey(1) & 0xFF == ord('q'): - break - -with open("./result/2-mask_detection.json", "w") as f: - json.dump(data, f) - -writer.release() - -cv2.destroyAllWindows()