AIStudio地址

Github地址
不抽烟,也没有烟,所以只能以这种形式代替了

爸,这下你还敢抽烟吗?/邪笑

我爸:这锅我不背!!

项目背景

  2014年11月24日,卫生计生委起草了《公共场所控制吸烟条例(送审稿)》向社会公开征求意见。送审稿明确,所有室内公共场所一律禁止吸烟。此外,体育、健身场馆的室外观众坐席、赛场区域;公共交通工具的室外等候区域等也全面禁止吸烟。而《公共场所控制吸烟条例》实施后,卫计委将考虑为控烟条例设置举报电话,同时开展监测评估,鼓励全社会参与戒烟活动。

  但有很多人秉持“多一事不如少一事”的原则:“欸,有点电话就不打,我就忍着!”,导致社会公共场所禁烟效果普遍不佳。

  因而“公共场所,禁止吸烟”的标牌,也渐渐沦为了摆设。

项目介绍

  本项目基于PaddleX进行模型训练,并利用inference导出后部署在本地,并使用百度大脑合成后进行“公共场所,禁止吸烟”的语音播报。

首先导入使用PaddleX时所需的模块

!pip install paddlex
!pip install paddle2onnx
# 进行数据集解压
!unzip -oq /home/aistudio/data/data86368/smoke.zip -d /home/aistudio/dataset2

  下面这个check.py是我在开发过程中遇到点小问题在PaddleX的Github issue中找到的,后面我们会提到这个脚本的功能。
(深刻启示:有问题就去逛issue!!!要相信你现在所遇到的绝大多数问题已经有“先烈”替你趟过了!即使没有也可以提issue!飞桨的开发小哥哥们回复也是炒鸡快!!!!)

!mv check.py dataset

数据处理和数据清洗

  在我们解压好数据集后,我们可以看到数据集中给了images和Annotations两个文件夹,分别存放着.jpg和.xml文件。但其实这是不符合PaddleX在目标检测中的数据格式要求的。并且,我们打开他的.xml文件可以发现,它的filename、name、path等内容均需要我们后期进行处理和更改。

  当然,在本项目中的数据处理方式有些许笨拙和低劣。

# 这里修改.xml文件中的<path>元素
!mkdir dataset/Annotations1
import xml.dom.minidom
import ospath = r'dataset/Annotations'  # xml文件存放路径
sv_path = r'dataset/Annotations1'  # 修改后的xml文件存放路径
files = os.listdir(path)
cnt = 1for xmlFile in files:dom = xml.dom.minidom.parse(os.path.join(path, xmlFile))  # 打开xml文件,送到dom解析root = dom.documentElement  # 得到文档元素对象item = root.getElementsByTagName('path')  # 获取path这一node名字及相关属性值for i in item:i.firstChild.data = '/home/aistudio/dataset/JPEGImages/' + str(cnt).zfill(6) + '.jpg'  # xml文件对应的图片路径with open(os.path.join(sv_path, xmlFile), 'w') as fh:dom.writexml(fh)cnt += 1
# 这里修改.xml文件中的<failname>元素
!mkdir dataset/Annotations2
import xml.dom.minidom
import ospath = r'dataset/Annotations1'  # xml文件存放路径
sv_path = r'dataset/Annotations2'  # 修改后的xml文件存放路径
files = os.listdir(path)for xmlFile in files:dom = xml.dom.minidom.parse(os.path.join(path, xmlFile))  # 打开xml文件,送到dom解析root = dom.documentElement  # 得到文档元素对象names = root.getElementsByTagName('filename')a, b = os.path.splitext(xmlFile)  # 分离出文件名afor n in names:n.firstChild.data = a + '.jpg'with open(os.path.join(sv_path, xmlFile), 'w') as fh:dom.writexml(fh)
# 这里修改.xml文件中的<name>元素
!mkdir dataset/Annotations3
#!/usr/bin/env python2
# -*- coding: utf-8 -*-import os
import xml.etree.ElementTree as ETorigin_ann_dir = '/home/aistudio/dataset/Annotations2/'# 设置原始标签路径为 Annos
new_ann_dir = '/home/aistudio/dataset/Annotations3/'# 设置新标签路径 Annotations
for dirpaths, dirnames, filenames in os.walk(origin_ann_dir):   # os.walk游走遍历目录名for filename in filenames:print("process...")# if os.path.isfile(r'%s%s' %(origin_ann_dir, filename)):   # 获取原始xml文件绝对路径,isfile()检测是否为文件 isdir检测是否为目录origin_ann_path = os.path.join(origin_ann_dir, filename)   # 如果是,获取绝对路径(重复代码)new_ann_path = os.path.join(new_ann_dir, filename)tree = ET.parse(origin_ann_path)  # ET是一个xml文件解析库,ET.parse()打开xml文件。parse--"解析"root = tree.getroot()   # 获取根节点for object in root.findall('object'):   # 找到根节点下所有“object”节点name = str(object.find('name').text)  # 找到object节点下name子节点的值(字符串)# 如果name等于str,则删除该节点if (name in ["smoke"]):#   root.remove(object)pass# 如果name等于str,则修改nameelse:object.find('name').text = "smoke"tree.write(new_ann_path)#tree为文件,write写入新的文件中。print("OK1")

由于在上述数据处理过程中我们产生了很多冗余的文件,故需将其删除。并将其更改为适合PaddleX的数据集格式。

!rm -rf dataset/Annotations
!rm -rf dataset/Annotations1
!rm -rf dataset/Annotations2
!mv dataset/Annotations3 dataset/Annotations
!mv dataset/images dataset/JPEGImages

在原始数据集中,存在.jpg文件和.xml文件匹配不对等的情况,这里我们根据.jpg文件名删除了在Annotations文件夹中无法匹配的.xml文件,使得.jpg和.xml能够一一对应。

import os
import shutil
path_annotations = 'dataset/Annotations'
path_JPEGImage = 'dataset/JPEGImages'
xml_path = os.listdir(path_annotations)
jpg_path = os.listdir(path_JPEGImage)
for i in jpg_path:a = i.split('.')[0] + '.xml'if a in xml_path:passelse:print(i)os.remove(os.path.join(path_JPEGImage,i))

因为懒(有现成的为啥还要自己写呢~),所以就用了PaddleX 自带的划分数据集的命令,这里我们训练集、验证集、测试集的比例为7:2:1。

!paddlex --split_dataset --format VOC --dataset_dir /home/aistudio/dataset/ --val_value 0.2 --test_value 0.1

  当然,从一般情况来说,这一步完成之后就可以进行模型训练了。但其实在实际过程中,若进行模型训练,在训练过程中会报错。具体报错,大家感兴趣的可以实地体验一下(嘿嘿嘿)。这里就需要用到我们在开头所提到的check.py文件。执行以下命令,会输出图片读取有误的图片路径。我们用rm -rf命令将其与其对应的.xml文件删除。

%cd dataset/
!cat train_list.txt | python check.py
!cat test_list.txt | python check.py
!cat val_list.txt | python check.py
/home/aistudio/dataset
Wrong img file: JPEGImages/790_strawberry.jpg
Wrong img file: JPEGImages/791_strawberry.jpg
Wrong img file: JPEGImages/000143.jpg
Wrong img file: JPEGImages/000144.jpg
Wrong img file: JPEGImages/000120.jpg
Wrong img file: JPEGImages/780_strawberry.jpg
Wrong img file: JPEGImages/845_strawberry.jpg
Wrong img file: JPEGImages/smoke132.jpg
Corrupt JPEG data: 1 extraneous bytes before marker 0xdb
Wrong img file: JPEGImages/000325.jpg
Wrong img file: JPEGImages/000193.jpg
!rm -rf JPEGImages/000120.jpg
!rm -rf JPEGImages/000143.jpg
!rm -rf JPEGImages/791_strawberry.jpg
!rm -rf JPEGImages/smoke132.jpg
!rm -rf JPEGImages/780_strawberry.jpg
!rm -rf JPEGImages/000193.jpg
!rm -rf JPEGImages/845_strawberry.jpg
!rm -rf JPEGImages/000325.jpg
!rm -rf JPEGImages/000144.jpg
!rm -rf JPEGImages/790_strawberry.jpg
!rm -rf Annotations/000120.xml
!rm -rf Annotations/000143.xml
!rm -rf Annotations/791_strawberry.xml
!rm -rf Annotations/smoke132.xml
!rm -rf Annotations/780_strawberry.xml
!rm -rf Annotations/000193.xml
!rm -rf Annotations/845_strawberry.xml
!rm -rf Annotations/000325.xml
!rm -rf Annotations/000144.xml
!rm -rf Annotations/790_strawberry.xml

并且删除之前生成的几个关于数据集的文本文件,重新执行PaddleX划分数据集的命令。

!rm -rf val_list.txt
!rm -rf train_list.txt
!rm -rf test_list.txt
!rm -rf labels.txt
!paddlex --split_dataset --format VOC --dataset_dir /home/aistudio/dataset/ --val_value 0.2 --test_value 0.1
%cd /home/aistudio/
/home/aistudio

模型训练

  在使用PaddleX进行模型训练的过程中,我们使用目前PaddleX适配精度最高的PPYolo模型进行训练。其模型较大,预测速度比YOLOv3-DarkNet53更快,适用于服务端。大家也可以更改其他模型尝试一下。这里我训练了大概300个epoch(别问,问就是没算力了也懒得续点了……)其中第277个epoch效果最佳,map大概在76。(有算力的童鞋可以试着调参或者继续往下面去试试)

import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0'from paddlex.det import transforms
import paddlex as pdx# 定义训练和验证时的transforms
# API说明 https://paddlex.readthedocs.io/zh_CN/develop/apis/transforms/det_transforms.html
train_transforms = transforms.Compose([transforms.MixupImage(mixup_epoch=250), transforms.RandomDistort(),transforms.RandomExpand(), transforms.RandomCrop(), transforms.Resize(target_size=608, interp='RANDOM'), transforms.RandomHorizontalFlip(),transforms.Normalize()
])eval_transforms = transforms.Compose([transforms.Resize(target_size=608, interp='CUBIC'), transforms.Normalize()
])# 定义训练和验证所用的数据集
# API说明:https://paddlex.readthedocs.io/zh_CN/develop/apis/datasets.html#paddlex-datasets-vocdetection
train_dataset = pdx.datasets.VOCDetection(data_dir='/home/aistudio/dataset',file_list='/home/aistudio/dataset/train_list.txt',label_list='/home/aistudio/dataset/labels.txt',transforms=train_transforms,parallel_method='thread',shuffle=True)
eval_dataset = pdx.datasets.VOCDetection(data_dir='/home/aistudio/dataset',file_list='/home/aistudio/dataset/val_list.txt',label_list='/home/aistudio/dataset/labels.txt',parallel_method='thread',transforms=eval_transforms)# 初始化模型,并进行训练
# 可使用VisualDL查看训练指标,参考https://paddlex.readthedocs.io/zh_CN/develop/train/visualdl.html
num_classes = len(train_dataset.labels)# API说明: https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#paddlex-det-ppyolo
model = pdx.det.PPYOLO(num_classes=num_classes)# API说明: https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#train
# 各参数介绍与调整说明:https://paddlex.readthedocs.io/zh_CN/develop/appendix/parameters.html
model.train(num_epochs=540,train_dataset=train_dataset,train_batch_size=8,eval_dataset=eval_dataset,learning_rate=0.000125,save_interval_epochs=1,lr_decay_epochs=[270,320, 480],save_dir='output/ppyolo',use_vdl=True)

模型导出

  这里我们将训练过程中保存的模型导出为inference格式模型,其原因在于:PaddlePaddle框架保存的权重文件分为两种:支持前向推理和反向梯度的训练模型 和 只支持前向推理的推理模型。二者的区别是推理模型针对推理速度和显存做了优化,裁剪了一些只在训练过程中才需要的tensor,降低显存占用,并进行了一些类似层融合,kernel选择的速度优化。而导出的inference格式模型包括__model__、__params__和model.yml三个文件,分别表示模型的网络结构、模型权重和模型的配置文件(包括数据预处理参数等)。

!paddlex --export_inference --model_dir=PaddleDetection/output/ppyolo/epoch_277 --save_dir=./inference_model

简单部署尝试

  下面我们简单地部署体验了一番。这里打开了设备摄像头进行视频流预测,并设置了在阈值>=0.3的时候会播放“公共场所,禁止吸烟!”

  在本项目中可以看到存在“cigarette.mp3”和“dad.mp3”的音频文件。“dad.mp3”的具体内容这里卖个关子。大家下载下来体验一下就知道了hhh。

  而这里的音频,使用的是百度大脑的语音合成API,具体的大家可以去百度大脑官网看看,在本项目中就不予展示了。

import cv2
import paddlex as pdx
from playsound import playsound# 修改模型所在位置
predictor = pdx.deploy.Predictor('D:\\project\\python\\cigarette\\inference_model')
cap = cv2.VideoCapture(0)while cap.isOpened():ret, frame = cap.read()if ret:result = predictor.predict(frame)score = result[0]['score']if score >= 0.3:print("*"*100)# 修改音频所在位置playsound('D:\\project\\python\\cigarette\\cigarette.mp3')# print(result)vis_img = pdx.det.visualize(frame, result, threshold=0.6, save_dir=None)cv2.imshow('cigarette', vis_img)if cv2.waitKey(1) & 0xFF == ord('q'):breakelse:break
cap.release()

个人相关介绍

  • 笔名:左右

  • 华东理工大学自动化专业大二在读

  • 号称:冷板凳常客

  • 热衷于利用人工智能技术做点有价值的东西,为社会做点小事情;

  • 另外也研究点多智能体的东西;

  • 偶尔写点随笔、摄影、仰望星空…

AiStudio主页,欢迎互关哟

Github主页,欢迎互关哟

CSDN主页,欢迎互关哟

爸,这下你还敢抽烟么?相关推荐

  1. 人工智能除了下围棋还能干啥?

    人工智能除了下围棋还能干啥?这篇科普文将震撼你的世界观 译者注:人工智能很可能导致人类的永生或者灭绝,而这一切很可能在我们的有生之年发生. 上面这句话不是危言耸听,请耐心的看完本文再发表意见.这篇翻译 ...

  2. IT线下培训班还值得报吗

    最近有朋友私信想入坑IT行业,问IT线下培训班还值得报吗? 老王观点: 假如想跨专业或者跨行进入软件行业的,真心不太建议线下报班了: 一是,软件行业经过十几年的发展,现存从业人员基数已经很大了,有一部 ...

  3. 已经发车的票还能取出来吗_高铁票在车已经开了,但我没上车也没有取票的情况下,还能取出票吗?...

    展开全部 可以取票. 在12306.cn网站使用居民e69da5e887aa3231313335323631343130323136353331333365633961身份证购票,并且在具备条件的乘车 ...

  4. android6.0 sd卡卸载api,android6.0 用户关掉sd卡读取权限的情况下, 还能做到手机缓存么?...

    兄弟,你理解错了. 可以看看官方文档. Android的储存空间分两块:Internal storage和External storage Internal storage 总是可用的,不需要额外权限 ...

  5. 下班后还戴着大厂工牌招摇过市,秀大厂优越感吗?

    码个蛋(codeegg) 第 1115 次推文 作者:行走的印钞机 博客:https://mp.weixin.qq.com/s/wFIwZVJX_OSc4do8IoqlKA 你听说过互联网大厂圈子里的 ...

  6. “离开浪浪山”是假象,80%年轻人下班后还在学习,真实是想先上个山。

    最近,又有一个关于年轻人与职场的新词横空出世-- 浪浪山. 什么是浪浪山? 每个人心中都有一座浪浪山. 浪浪山,其实是人生的一种状态,步入社会时满腔热血,然而很快就被现实给修理了一顿:想要辞职不干出去 ...

  7. 外包公司的三大弊端是什么,在此情况下还建议去外包公司吗

    随着市场经济的发展,外包公司越来越多地涌现出来.人们相信它能够提供更好的服务和更低的成本,因此,外包公司也成为现代企业不可或缺的一部分.然而,与它带来的一系列好处相比,它也存在一些弊端.下面,我们来探 ...

  8. 带饭省下的钱充3个月话费还嫌多!

    前程无忧近日对2830位网友进行了上班成本调查,在有关"上班是否带饭"的提问中,84%的受访者表示"不带饭",尽管"带饭"有诸多好处(省钱. ...

  9. 深入浅出的给大家分析下现在做抖音短视频还来得及吗?

    2500字,需要一些耐心用心读完,让自己对于未来更清晰一些! 大家好,我是@我赢助手短视频运营,专注于短视频运营和创作:今天给大家分享下现在还来得及做短视频吗?深入浅出的给大家分析下这个问题. 首先大 ...

最新文章

  1. SPSS聚类分析:K均值聚类分析
  2. 爱国者D5移动电源改造
  3. arcgis api for javascript 距离与面积量算
  4. 有特殊步长适应的自适应差分脉码调制语音编码系统
  5. 【ArcGIS微课1000例】0007:基于数字高程模型DEM生成剖面线、剖面图
  6. libsvm中数据归一化的重要性
  7. OpenCV3学习(3)——视频文件的读取与写入
  8. 随想录(工业软件和消费级软件的区别)
  9. 实战百度竞价恶意点击心得
  10. mysql表索引类型修改_MySQL常用的建表、添加字段、修改字段、添加索引SQL语句写法总结...
  11. 30.Linux/Unix 系统编程手册(上) -- 线程:线程同步
  12. Anroid 开发so文件找不到问题-例高德地图SDK提示com.autonavi.amap.mapcore.MapCore.nativeNewInstance问题
  13. 四旋翼无人机飞控系统设计(方案篇)
  14. zigbee芯片cc2430资料
  15. 几款重复文件查找工具对比
  16. 选择单页设计的理由是什么?
  17. 协程问题:Can only use Waiter.switch method from the Hub greenlet
  18. 巨斧砍大树-sdut
  19. cocos creator切换场景闪退_#Cocos Creator# 为什么音乐音效在场景切换的时候自动停止了?...
  20. Mirror for Samsung TV for mac(三星智能电视投屏软件)

热门文章

  1. #135. 二维树状数组 3:区间修改,区间查询
  2. Splay(单点修改+查询)
  3. oracle字符集查看、修改、版本查看
  4. JetPack——网络库封装
  5. Qt学习(八):QT中TCP传输文件
  6. 码这么多字只为搞懂如何在Python和Java中使用JSON
  7. java callable 详解_Java多线程详解(七)------Callable接口介绍
  8. bitmap xml大小 安卓_一张壁纸让安卓用户手机系统崩溃,包括三星、小米、一加等...
  9. SOLID 设计原则
  10. 关于“指针的指针”的认识(值传递、指针传递区分)