【公共场所吸烟检测吸烟】爸,你还敢抽烟么
该项目针对公共场所禁烟效果不佳问题,基于PaddleX训练模型,结合语音播报实现控烟。先处理数据集,修改XML文件适配格式,清理冗余文件并划分训练、验证、测试集(7:2:1)。用PPYolo模型训练300个epoch,第277个效果最佳,map约76。导出模型后部署,通过摄像头检测,阈值≥0.3时播放禁烟语音。

不抽烟,也没有烟,所以只能以这种形式代替了
爸,这下你还敢抽烟吗?/邪笑
我爸:这锅我不背!!
项目背景
2014年11月24日,卫生计生委起草了《公共场所控制吸烟条例(送审稿)》向社会公开征求意见。送审稿明确,所有室内公共场所一律禁止吸烟。此外,体育、健身场馆的室外观众坐席、赛场区域;公共交通工具的室外等候区域等也全面禁止吸烟。而《公共场所控制吸烟条例》实施后,卫计委将考虑为控烟条例设置举报电话,同时开展监测评估,鼓励全社会参与戒烟活动。但有很多人秉持“多一事不如少一事”的原则:“欸,有点电话就不打,我就忍着!”,导致社会公共场所禁烟效果普遍不佳。
因而“公共场所,禁止吸烟”的标牌,也渐渐沦为了摆设。
项目介绍
本项目基于PaddleX进行模型训练,并利用inference导出后部署在本地,并使用百度大脑合成后进行“公共场所,禁止吸烟”的语音播报。首先导入使用PaddleX时所需的模块
In [9]!pip install paddlex!pip install paddle2onnx登录后复制 In [65]
# 进行数据集解压!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两个文件夹,分别存放.webp和.xml文件。为了能够顺利使用PaddleX进行数据集划分和模型训练,需要将原本数据集修改为符合PaddleX数据集格式的数据集。In [53]# 这里修改.xml文件中的登录后复制 In [55]元素!mkdir dataset/Annotations1import xml.dom.minidomimport 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) + '.webp' # xml文件对应的图片路径 with open(os.path.join(sv_path, xmlFile), 'w') as fh: dom.writexml(fh) cnt += 1
# 这里修改.xml文件中的登录后复制 In [56]元素!mkdir dataset/Annotations2import xml.dom.minidomimport 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) # 分离出文件名a for n in names: n.firstChild.data = a + '.webp' with open(os.path.join(sv_path, xmlFile), 'w') as fh: dom.writexml(fh)
# 这里修改.xml文件中的登录后复制 由于在上述数据处理过程中我们产生了很多冗余的文件,故需将其删除。并将其更改为适合PaddleX的数据集格式。In [57]元素!mkdir dataset/Annotations3#!/usr/bin/env python2# -*- coding: utf-8 -*- import osimport xml.etree.ElementTree as ET origin_ann_dir = '/home/aistudio/dataset/Annotations2/'# 设置原始标签路径为 Annosnew_ann_dir = '/home/aistudio/dataset/Annotations3/'# 设置新标签路径 Annotationsfor 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,则修改name else: object.find('name').text = "smoke" tree.write(new_ann_path)#tree为文件,write写入新的文件中。 print("OK1")
!rm -rf dataset/Annotations!rm -rf dataset/Annotations1!rm -rf dataset/Annotations2!mv dataset/Annotations3 dataset/Annotations!mv dataset/images dataset/JPEGImages登录后复制
在原始数据集中,存在.webp文件和.xml文件匹配不对等的情况,这里我们根据.webp文件名删除了在Annotations文件夹中无法匹配的.xml文件,使得.webp和.xml能够一一对应。
In [59]import osimport shutilpath_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: pass else: print(i) os.remove(os.path.join(path_JPEGImage,i))登录后复制 因为懒(有现成的为啥还要自己写呢~),所以就用了PaddleX 自带的划分数据集的命令,这里我们训练集、验证集、测试集的比例为7:2:1。
In [60]!paddlex --split_dataset --format VOC --dataset_dir /home/aistudio/dataset/ --val_value 0.2 --test_value 0.1登录后复制登录后复制
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/setuptools/depends.py:2: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses import impDataset Split Done.Train samples: 3403Eval samples: 972Test samples: 486Split files saved in /home/aistudio/dataset/登录后复制
当然,从一般情况来说,这一步完成之后就可以进行模型训练了。但其实在实际过程中,若进行模型训练,在训练过程中会报错。具体报错,大家感兴趣的可以实地体验一下(嘿嘿嘿)。这里就需要用到我们在开头所提到的check.py文件。执行以下命令,会输出图片读取有误的图片路径。我们用rm -rf命令将其与其对应的.xml文件删除。
In [61]%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/datasetWrong img file: JPEGImages/790_strawberry.webpWrong img file: JPEGImages/791_strawberry.webpWrong img file: JPEGImages/000143.webpWrong img file: JPEGImages/000144.webpWrong img file: JPEGImages/000120.webpWrong img file: JPEGImages/780_strawberry.webpWrong img file: JPEGImages/845_strawberry.webpWrong img file: JPEGImages/smoke132.webpCorrupt JPEG data: 1 extraneous bytes before marker 0xdbWrong img file: JPEGImages/000325.webpWrong img file: JPEGImages/000193.webp登录后复制 In [62]
!rm -rf JPEGImages/000120.webp!rm -rf JPEGImages/000143.webp!rm -rf JPEGImages/791_strawberry.webp!rm -rf JPEGImages/smoke132.webp!rm -rf JPEGImages/780_strawberry.webp!rm -rf JPEGImages/000193.webp!rm -rf JPEGImages/845_strawberry.webp!rm -rf JPEGImages/000325.webp!rm -rf JPEGImages/000144.webp!rm -rf JPEGImages/790_strawberry.webp!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划分数据集的命令。
In [63]!rm -rf val_list.txt!rm -rf train_list.txt!rm -rf test_list.txt!rm -rf labels.txt登录后复制 In [64]
!paddlex --split_dataset --format VOC --dataset_dir /home/aistudio/dataset/ --val_value 0.2 --test_value 0.1登录后复制登录后复制
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/setuptools/depends.py:2: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses import impDataset Split Done.Train samples: 3396Eval samples: 970Test samples: 485Split files saved in /home/aistudio/dataset/登录后复制 In [25]
%cd /home/aistudio/登录后复制
/home/aistudio登录后复制
模型训练
在使用PaddleX进行模型训练的过程中,我们使用目前PaddleX适配精度最高的PPYolo模型进行训练。其模型较大,预测速度比YOLOv3-DarkNet53更快,适用于服务端。大家也可以更改其他模型尝试一下。这里我训练了大概300个epoch(别问,问就是没算力了也懒得续点了……)其中第277个epoch效果最佳,map大概在76。(有算力的童鞋可以试着调参或者继续往下面去试试)
In [27]import osos.environ['CUDA_VISIBLE_DEVICES'] = '0'from paddlex.det import transformsimport paddlex as pdx# 定义训练和验证时的transforms# API说明 https://paddlex.readthedocs.io/zh_CN/develop/apis/transforms/det_transforms.htmltrain_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-vocdetectiontrain_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.htmlnum_classes = len(train_dataset.labels)# API说明: https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#paddlex-det-ppyolomodel = 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.htmlmodel.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三个文件,分别表示模型的网络结构、模型权重和模型的配置文件(包括数据预处理参数等)。
In [ ]!paddlex --export_inference --model_dir=PaddleDetection/output/ppyolo/epoch_277 --save_dir=./inference_model登录后复制
简单部署尝试
下面我们简单地部署体验了一番。这里打开了设备摄像头进行视频流预测,并设置了在阈值>=0.3的时候会播放“公共场所,禁止吸烟!”
在本项目中可以看到存在“cigarette.mp3”和“dad.mp3”的音频文件。“dad.mp3”的具体内容这里卖个关子。大家下载下来体验一下就知道了hhh。
而这里的音频,使用的是百度大脑的语音合成API,具体的大家可以去百度大脑正式看看,在本项目中就不予展示了。
In [ ]import cv2import paddlex as pdxfrom 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'): break else: breakcap.release()登录后复制 相关攻略
零基础学习Python可从安装环境开始。前往官网下载最新稳定版,安装时勾选添加PATH选项。验证安装后,创建 py文件并写入print()函数输出文本。通过命令行运行文件,观察输出结果。理解代码按顺序执行,注意括号与引号的正确使用。初期不必死记语法,通过修改代码并运行来建立动手反馈的实践感。
Trae的AI功能深度适配FastAPI与Flask框架。针对FastAPI,它能精准识别异步架构与类型注解,提供模型定义、路由补全及异步数据库建议;在Flask中,则侧重理解装饰器链、请求上下文与ORM操作,辅助完成权限控制与数据库提交等典型模式。此外,Trae具备跨框架语义索引能力,可感知项目结构、依赖变更与工具函数调用,提升开发效率。
Trae在Python数据分析与机器学习项目中主要通过四种方式提供支持:利用Auto模式自动生成并执行端到端分析脚本;通过AgentCLI命令行自动化机器学习建模流程;对现有代码进行智能调试与优化;借助语音交互快速构建数据处理函数。这些功能覆盖了从需求描述到代码生成、模型构建及代码优化的全流程。
在Python编程中,你是否也曾编写过类似的统计代码? 统计词频 count = {} for word in words: if word in count: count[word] += 1 else: count[word] = 1 实际上,这种高频的计数需求,完全可以通过Python内置
Trae稳定支持Python3 10至3 13版本,3 9及以下版本无法运行。Python3 14处于实验性支持阶段,核心功能可能受限。当存在多个3 10以上版本时,Trae优先选择虚拟环境中的解释器,其次为最高系统版本。此外,Trae仅兼容64位Python解释器,不支持32位架构。
热门专题
热门推荐
公安部就电子数据取证规则公开征求意见,拟将网络安全等行政案件纳入适用范围,并规范取证流程与核心概念。新规特别明确了获取密码、调取通讯内容等特殊程序,需经严格审批并保障当事人权利。配套法律文书也同步优化,以构建更规范且注重权利保障的取证体系。
理想L9和LIvis的定价策略刚掀起波澜,小鹏GX的最终价格就给出了更猛烈的回应——从近40万元的预售价直降至27万元起。用小鹏产品矩阵负责人吴安飞的话说,这叫“9系的产品,8系的价格”。 这12万元的下调,效果堪称立竿见影。发布会次日,小鹏集团港股股价一度大涨超8%。更关键的是市场订单:上市12小
5月21日,环塔拉力赛新疆且末赛段大营迎来了一位备受瞩目的访客——知名零售企业胖东来的创始人于东来。他专程前往长城汽车车队营地,与参赛车手及后勤团队进行了深度交流。据悉,于东来此次自驾越野之旅已历时一月,随行车队中包含多款国产越野车型。经过实地驾驶与多维度对比,他对以长城汽车为代表的国产越野车品质给
比特币官方入口在哪里?一个核心门户的权威指南 说起比特币,很多人第一反应是去找它的“官网”或“官方App”。但这里有个关键点需要先理清:比特币本质上是一种去中心化的全球数字货币,它不属于任何一家公司或机构,而是由一个庞大的、遍布全球的社区共同维护。因此,它并没有传统意义上由某个企业运营的“官方网站”
Ring-2 5-1T是什么 在当今大模型技术激烈竞争的赛道上,追求更长的上下文处理能力和更强大的深度推理性能已成为核心焦点。近日,蚂蚁集团旗下的inclusionAI团队重磅开源了Ring-2 5-1T模型,这是一个参数规模高达万亿级别的混合线性思考大语言模型。该模型基于先进的Ling 2 5架构





