ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于深度学习的头盔佩戴检测系统:从YOLO目标检测到Web可视化部署

基于深度学习的头盔佩戴检测系统:从YOLO目标检测到Web可视化部署 简介基于深度学习的电动自行车头盔佩戴检测系统是一套面向毕业设计场景的完整工程适用于计算机视觉方向学生进行目标检测模型训练、推理与界面整合的实践练习。压缩包共包含187个文件大小约134.14MB主体包括55个Python源码文件、32个编译缓存、22个YAML配置与7个模型权重文件同时附带网页检测界面、数据库脚本及容器部署配置能支撑从模型训练到应用上线的全流程开发。该项目由导师指导并通过评审98分源码经过本地编译与严格调试可稳定运行目前已有66人学习参考。除核心代码外还提供使用手册、训练样例图、批处理工具和完整目录结构便于快速理解头盔佩戴检测的数据处理、模型训练、界面呈现等实现思路适合正在完成毕业设计或课程项目的学生直接复用、二次开发。1. 基于深度学习的头盔佩戴检测为什么值得拿它做毕设底座论被翻牌子的频率基于深度学习的电动自行车头盔佩戴检测系统在毕业设计里排得进前三。早晚高峰路口的监控画面里哪些车主戴了头盔、哪些没有靠人眼盯不住只能交给计算机视觉去判断。这套Python源码加全套资料的毕设项目评审分98分代码是导师指导后严格调试过的能直接运行。它不只是一个训练脚本而是前端ECharts图表、Dockerfile部署配置、使用手册都齐的一套工程。最适合正在做目标检测大作业、毕业设计或者想找个完整案例练深度学习落地的同学直接从环境搭建一路复现到页面展示。2. 系统架构与选型逻辑从模型检测到Web图表展示的数据链路2.1 头盔检测的任务本质与模型选型理由头盔佩戴检测从算法视角看是二分类目标检测任务输入一帧路面图像输出若干带类别标签的检测框类别只有“佩戴头盔”和“未佩戴头盔”两种。为什么强调“目标检测”而不是“图像分类”因为真有人把这个毕设简化成整图二分类的思路——整张图丢进CNN输出0或1。图片拍摄角度正、背景干净的演示场景能跑通一到真实监控视角立即翻车画面里人挤人遮挡严重整图分类能告诉你“图里有违规行为”却说不清“到底是哪个人没戴”。目标检测输出的是(x1, y1, x2, y2, conf, cls)这样的结构化结果每个框对应一个具体的人后端才能去做精确计数、区域告警、和球机联动。这个任务定义上的差别直接决定了后续所有技术栈。模型选型上我见过不少一开始就冲Faster R-CNN去的精度上限确实高但推理延迟在纯CPU环境下压不住监控路数一多就排队SSD在小目标上的召回率又偏低而监控画面里一颗人头往往只占几十个像素属于典型小目标场景。YOLO系在推理速度和小目标召回之间做了均衡工具链也最完整训练完导出ONNX、转TensorRT都有现成方案。对毕设来说还有一个隐性好处——这个系统的模型训练与前端展示解耦前端只消费后端返回的统计结果就算你后续想换更强的检测算法Web页面和接口一行都不用动。| 方案 | 人头定位 | 小目标召回 | CPU推理帧率 | 工具链成熟度 | 推荐度 | | Faster R-CNN | 强 | 中 | 2-5 FPS | 一般 | 不推荐毕设首选 | | SSD | 中 | 偏弱 | 8-12 FPS | 一般 | 不推荐 | | YOLO系 | 强 | 强 | 15-30 FPS | 高 | 推荐 | | 整图分类 | 无定位能力 | 无 | 高但不适用 | 低 | 不推荐 |选深度学习算法不能只看论文里的mAP还得看部署工具链。你代码里跑得再花哨换台机器跑不起来答辩现场就翻车了。2.2 项目目录结构与各文件职责压缩包打开第一眼不是一堆模型文件堆在那里而是清晰的工程分层。把关键文件拉出来逐个看能推断出作者的设计思路| 文件 | 类型 | 在系统里的职责 | | index.html | 页面入口 | 前端唯一页面承载统计卡片、图表容器与页面结构 | | EB_Helmet.css | 样式表 | 定义布局、卡片配色、图表区域尺寸换答辩风格就改这里 | | jquery-3.6.0.js | 脚本库 | DOM操作与AJAX轮询请求 | | echarts.min.js | 图表库 | 渲染佩戴/未佩戴统计柱状图、趋势曲线 | | train.jpg | 演示图片 | 单图推理的默认测试样例用来验证服务是否跑通 | | Dockerfile | 部署配置 | 把检测服务容器化换机器不动环境 | | clean.bat | 工具脚本 | 清理__pycache__等临时文件 | | 手册.docx | 说明文档 | 选题背景、接口说明、使用步骤 | | .gitkeep | 占位文件 | 空目录也能被git版本控制说明作者有规范习惯 |这个文件组合透露了几个关键设计决策。前端用jQuery而不是Vue/React对这类项目是合理的核心在算法前端只有一个页面没必要引入构建工具链。jQuery发AJAX请求、查接口、渲染DOM几十行代码就够。答辩时老师问“前端怎么和后端通信”从$.get讲到JSON字段两分钟能讲透换成Vue全家桶反而把简单问题复杂化。clean.bat这种脚本看起来不起眼实际开发时很有用。检测项目跑几轮训练会生成大量__pycache__和临时权重文件打包发压缩包之前跑一下体积能小不少。拿到资源以后第一次运行前先跑一遍避免旧缓存干扰这是我惯用的做法。2.3 检测结果输出与前端数据契约后端检测服务和前端页面之间通过一个JSON结构对接。很多人在这个接口设计上翻车后端返回的字段和前端对不上页面全是NaN。我一般会先约定好数据契约再各写各的。单帧检测结果汇总后字段应该是这样| 字段 | 类型 | 含义 | | total_count | int | 画面里识别到的人头总数 | | helmet_count | int | 佩戴头盔人数 | | no_helmet_count | int | 未佩戴头盔人数 | | average_confidence | float | 全部框的平均置信度 | | timestamp | string | 检测时间用于趋势图横轴 |对应的后端汇总逻辑# 把 YOLO 输出的原始检测框转成前端所需的统计字段 def summarize_result(detections): helmet_count 0 no_helmet_count 0 conf_sum 0.0 for box in detections: # box 格式: [x1, y1, x2, y2, conf, cls_id] x1, y1, x2, y2, conf, cls_id box if cls_id 0: helmet_count 1 elif cls_id 1: no_helmet_count 1 conf_sum conf total helmet_count no_helmet_count return { total_count: total, helmet_count: helmet_count, no_helmet_count: no_helmet_count, average_confidence: round(conf_sum / total, 4) if total else 0, timestamp: time.strftime(%Y-%m-%d %H:%M:%S), }这里的cls_id 0和1对应训练配置里names: [helmet, no_helmet]的顺序顺序一旦定义训练和推理都必须保持一致否则统计口径直接错乱。前端拿到JSON后定时轮询而不是长连接推送因为检测是周期性进行的// 每 2 秒轮询一次检测统计接口刷新 ECharts 图表 function refreshStats() { $.get(/api/stats, function (data) { if (data.code ! 0) { console.warn(接口返回异常, data.msg); return; } $(#total_count).text(data.total_count); var rate (data.helmet_count / data.total_count * 100).toFixed(1); $(#helmet_rate).text(rate %); helmetChart.setOption({ series: [{ data: [data.helmet_count, data.no_helmet_count] }] }); }).fail(function () { console.error(检测服务未启动或接口路径不对); }); } $(document).ready(function () { refreshStats(); setInterval(refreshStats, 2000); });轮询间隔2秒是折中值。检测本身跑在CPU上每帧可能要100ms左右轮询太快前端图表会闪太慢数据又像卡死。$.get默认不会强缓存但如果你把URL写死部分浏览器还是会拦截请求联调时优先排除这一步。3. 环境搭建与源码复现从Python环境检查到Docker部署的完整路径3.1 环境准备Python虚拟环境、CUDA与依赖安装拿到的源码能不能跑第一步往往不是训练而是环境。现在很多人用codex这类AI编程工具直接生成训练脚本代码倒是生成得快但真正卡死人的往往不是代码本身而是环境配置——这也是python安装教程最容易断片的地方。先说最基本的单独用一个虚拟环境别直接用系统Python。项目里依赖的torch、opencv版本可能与系统其他项目冲突venv隔离能省掉大量“改了一个环境把另一个项目搞挂”的麻烦。# 创建并激活虚拟环境 python -m venv .venv source .venv/bin/activate # Windows 用 .venv\Scripts\activate # 先探测 torch 是否可用再决定后续操作 python -c import torch; print(torch.__version__, torch.cuda.is_available())torch.__version__会打印类似2.0.1cpu或2.0.1cu118的版本号。cpu结尾说明你手上是CPU版cuda.is_available()输出False。遇到这个情况先别急着重装多半是驱动和PyTorch的CUDA版本没对齐。用nvidia-smi看一下Driver Version和CUDA Version列驱动支持的版本比PyTorch需要的低时升级驱动比重装PyTorch更快。依赖清单通常写在requirements.txt里如果压缩包里没有直接看Dockerfile的pip install那一行那就是作者真实跑通的依赖集合。# 有 requirements.txt 就一把装齐 pip install -r requirements.txt # 没有清单时按常见技术栈补齐 pip install torch torchvision opencv-python pip install flask pyyaml tqdm装完后先跑一个最简单的单图推理把train.jpg喂进去确认模型权重能加载再进行后续训练或前端联调。这一步能快速区分“环境问题”和“代码问题”省得在错误方向上排查半天。环境问题在深度学习项目里是十有八九的玄学先跑通再谈优化。3.2 数据集目录检查与训练/推理入口定位这一步是动手深度学习和看理论的分水岭。很多人拿到项目就直接train.py跑起来结果报错全是数据集路径不对。主流的检测训练框架对数据目录有固定要求先核对一下目录结构最稳# 查看数据集前 20 个文件确认 images 与 labels 目录是否成对出现 find datasets -type f | head -20 # 查看类别定义文件 cat datasets/data.yaml以最常用的YOLO格式为例data.yaml长这样# 这个顺序非常重要cls_id 0 就是 helmet1 就是 no_helmet train: datasets/images/train val: datasets/images/val nc: 2 names: [helmet, no_helmet]names顺序一旦确定训练产出的best.pt里的类别索引就固定了。推理脚本里用了错误顺序的话错得极其隐蔽——检测框位置正常但计数统计全反。遇到这种问题先回来看data.yaml别去调模型。训练命令这块常见做法是python train.py --data datasets/data.yaml --epochs 100 --batch-size 16 --imgsz 640 --device 0--epochs是训练轮数毕设数据量小50到100轮足够--batch-size根据显存调整16是16G显存较稳的值显存小就降到8--imgsz是输入图像resize尺寸默认640如果监控画面里人头目标很小试着调到1280精度会涨但训练时间和显存也会涨--device 0表示用第一张GPU没有GPU就改成cpu同时把DataLoader的num_workers改成0否则Windows下会报多线程错误。推理入口一般在根目录下叫detect.py或run.py跑通之后把权重换成你训练完的best.ptpython detect.py --source train.jpg --weights runs/train/exp/best.pt \ --conf-thres 0.25 --iou-thres 0.45 --device 0训练脚本默认把每个epoch的权重存到runs/train/exp/下演示和论文最好用best.pt而不是last.pt。last是断点续训用的可能保存的是过拟合或中断时那个epoch的状态。这个细节吃过亏答辩演示用错权重被评委当场问住过。3.3 Docker化部署Dockerfile解读与构建命令Dockerfile是这套资料里很加分的一块。你可以完全不学Docker直接本地跑但会了Docker答辩现场不会因为换电脑而跑不起来——环境被完整固化在镜像里。一个贴合这类检测项目的Dockerfile模板# CPU 推理场景选 slim 基础镜像体积小、依赖干净 FROM python:3.8-slim WORKDIR /app # 先拷贝依赖清单并安装利用 Docker 层缓存 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple # 再拷贝项目代码 COPY . . # 检测服务监听端口具体端口看源码里的 app.run EXPOSE 8080 CMD [python, app.py]两个细节值得说。一是COPY分两步走先拷贝requirements.txt装依赖再COPY整个项目这样改代码后重新构建时依赖层不会失效构建时间大幅缩短。二是pip加了清华镜像源国内服务器构建时不容易超时。docker build -t eb_helmet:latest . docker run -d --name helmet-server -p 8080:8080 eb_helmet:latestDocker运行起来后浏览器直接访问http://localhost:8080就是系统页面。打不开时先docker logs helmet-server看日志再检查宿主机端口有没有被占用。Windows下写的Dockerfile换行符是CRLF偶尔会导致RUN执行报错把文件转成LF再build我遇到过一次折腾了半小时才发现。3.4 推理参数解读置信度阈值、IoU阈值与检测效果的关系| 参数 | 常用值 | 调参方向 | | conf_thres | 0.25 | 漏检多就往下调误检多就往上调 | | iou_thres | 0.45 | 目标密集可以调到0.5防止重复框 | | imgsz | 640 | 小目标多就调高到1280速度会下降 | | device | 0 / cpu | 无GPU就用cpu并配合num_workers0 |置信度阈值是最值得解释的。头盔检测的误报来源是远处行人背包、垃圾箱的颜色纹理被当成头盔。把conf_thres从0.25调到0.4误报会明显下降但也会把一些遮挡严重、模糊的真头盔漏掉。调这个参数的顺序我一般是先盯着检测结果图看5分钟记录误报和漏报各占多少再决定方向而不是无脑往上加。IoU阈值影响的是NMS阶段。阈值越低两个重叠目标越容易被当成同一个导致两个人挨太近时只出一个框头盔计数偏低。在学校做演示时画面里的人一般不多但真实路口的密集车流里这个参数对统计准确率影响很大也是论文里可以写一页实验对比的点。4. 前端可视化页面的实现逻辑ECharts图表、页面结构与接口联动4.1 index.html的页面骨架与静态资源加载顺序页面是系统给评委的第一印象也是很多人拿到源码后会第一个打开的文件。index.html的骨架很简单统计卡片显示总数和佩戴率图表区显示柱状图静态资源按顺序加载。一个符合这套项目的页面骨架示意!DOCTYPE html html langzh-CN head meta charsetUTF-8 title电动自行车头盔佩戴检测系统/title link relstylesheet hrefEB_Helmet.css !-- jquery 必须在 echarts 之前加载因为 echarts 初始化要用到 $ -- script srcjquery-3.6.0.js/script script srcecharts.min.js/script /head body div classstat-cards div classcard span总检测人数/span strong idtotal_count0/strong /div div classcard span佩戴率/span strong idhelmet_rate0%/strong /div /div !-- 图表容器必须显式给高度ECharts 拿不到高度会一直白屏 -- div idhelmet_chart stylewidth: 100%; height: 480px;/div /body /html静态资源加载顺序是一个容易忽略的细节。jquery-3.6.0.js必须在echarts.min.js前面因为页面里初始化图表时通常会用$(document).ready()如果echarts先加载、jQuery还没就位初始化代码执行到一半就报错。CSS样式文件放在head里避免页面闪出无样式内容。EB_Helmet.css的内容一般是统一样式比如卡片栅格、图表区域边距、配色变量。答辩时想换一个更正式的主题改这个文件里几处颜色变量就行不需要动HTML结构和JavaScript。4.2 ECharts 图表初始化与配色逻辑ECharts图表是演示时的重头戏。柱状图展示佩戴/未佩戴人数一眼能看出整体佩戴率。初始化代码// 在 DOM 渲染完成后初始化容器没渲染出来时 ECharts 会拿不到宽度高度 var helmetChart; $(document).ready(function () { helmetChart echarts.init(document.getElementById(helmet_chart)); helmetChart.setOption({ title: { text: 当前画面佩戴情况 }, tooltip: { trigger: axis }, xAxis: { type: category, data: [佩戴头盔, 未佩戴头盔] }, yAxis: { type: value, minInterval: 1 }, series: [{ type: bar, data: [0, 0], barWidth: 80, itemStyle: { color: function (params) { // 绿色代表佩戴红色代表未佩戴答辩演示时视觉反馈更直接 return params.dataIndex 0 ? #2f9e44 : #e03131; } } }] }); });几个参数值得说。minInterval: 1保证y轴刻度不会出现0.5人这个细节看着不起眼但真见过一个翻车现场y轴显示0.5人评委当场质疑数据真实性。barWidth固定80像素避免宽度自适应时柱子忽宽忽细。itemStyle里的color回调让佩戴和未佩戴两类数据分别用绿色和红色这和交通场景里“合规是绿、违规是红”的直觉一致。setOption是可以重复调用的不用每次刷新数据都重建整个图表。前面2.3节里的refreshStats只更新series.data图表会自动diff并做过渡动画效果比整图重建流畅得多。ECharts这个机制在数据轮询场景是精心设计的数据更新频繁时性能差距很明显。4.3 前端联调与缓存问题定位前端页面写完了最难的是后端还没就绪时怎么调试。我一般会在本地放一个mock JSON文件把接口路径指向它让页面把数据渲染出来再切回真实接口。mock数据格式{ code: 0, total_count: 12, helmet_count: 9, no_helmet_count: 3, average_confidence: 0.87, timestamp: 2025-01-01 00:00:00 }用浏览器直接打开这个JSON能确认页面拿到的字段是不是预期的。等后端检测服务跑起来后再把请求地址切回真实服务。真实接口返回了但图表不更新优先检查浏览器Network面板看请求状态码是不是200。另一个高频问题是浏览器缓存——接口URL不变部分浏览器会直接使用缓存结果导致图表数据看起来“卡住”在Network面板勾选Disable cache后重新刷新立刻就能分辨是接口没返回还是前端没更新。调试阶段还有一个习惯值得推荐所有对外接口统一返回{code, data}而不是纯数组。前端判断data.code 0再处理业务数据排查问题时能少写一堆if。这套项目里的后端接口如果还没统一格式改起来也不难在Flask的route返回处包一层dict就行。5. 避坑记录运行头盔检测毕设源码时最常遇到的五个问题5.1 加载权重报 missing keys/unexpected key多卡训练的权重如何单卡加载现象训练好的best.pt加载到模型里控制台打印一长串missing keys和unexpected key然后推理时模型输出全是背景框或置信度极低。原因训练时用了nn.DataParallel模型被包了一层保存的checkpoint里所有key都带module.前缀而推理脚本里用的是单卡模型两层对象的key对不上。这是多卡训练转单卡推理的经典问题也是毕设代码里出现频率最高的bug之一。解决加载前清洗一遍键名把module.前缀去掉。import torch # 加载权重先 map_location 到 cpu避免 GPU 显存不够导致加载直接崩 ckpt torch.load(best.pt, map_locationcpu) sd ckpt.get(state_dict, ckpt) # 兼容两种保存格式 new_sd {} for k, v in sd.items(): if k.startswith(module.): new_sd[k[len(module.):]] v else: new_sd[k] v model.load_state_dict(new_sd)map_locationcpu是另一个坑。很多人模型加载失败不是因为key而是因为脚本默认加载到cuda:0而评测机器上根本没有GPU。整包checkpoint里可能包含epoch、optimizer状态不是纯state_dict所以用ckpt.get(state_dict, ckpt)做兼容这一步很实用。5.2 CUDA不可用装错PyTorch版本不如先查驱动现象训练脚本跑起来但GPU利用率0%epoch耗时几小时。检查torch.cuda.is_available()返回False。原因两个方向。一个是pip默认源装的是CPU版PyTorch版本号后缀cpu一个是驱动太旧装不了对应CUDA版本的PyTorch。解决先判断是哪种再对症下药。# 打印 torch 版本和 CUDA 可用状态 python -c import torch; print(torch.__version__, torch.cuda.is_available()) # 查看驱动支持的 CUDA 版本 nvidia-smi如果torch版本号以cpu结尾重装GPU版# cu121 代表 CUDA 12.1按你驱动支持的最高版本选 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121如果nvidia-smi显示的CUDA Version停留在11.x而PyTorch是cu121这时先升级显卡驱动更直接。驱动这层升到12.x后PyTorch不用动。这个问题排查顺序很重要见过有人把PyTorch卸了又装三四遍最后发现是驱动老得离谱。先查驱动再重装软件能省下大量时间。5.3 OpenCV中文路径返回Noneimdecode的正确打开方式现象cv2.imread(D:/监控数据/测试图片/train.jpg)返回None但文件确实存在路径也复制得很仔细。原因OpenCV的imread在Windows下不支持非ASCII路径中文目录名会解析失败。很多毕设的路径里带着“数据集”、“图片”这类中文目录一踩一个准。解决改用numpy配合cv2.imdecode。import cv2 import numpy as np # 错误写法路径里有中文时一定返回 None # img cv2.imread(D:/数据集/测试图片/train.jpg) # 正确写法先以二进制读入再交给 OpenCV 解码 img cv2.imdecode(np.fromfile(D:/数据集/测试图片/train.jpg, dtypenp.uint8), cv2.IMREAD_COLOR)写文件也有对应的问题cv2.imwrite保存到中文路径会静默失败解决办法是cv2.imencode后配合tofile写入。这条经验是只要路径里可能出现中文就不要用imread/imwrite直接封装一个兼容函数所有检测和保存操作统一走它。我在自己项目里会单独建一个文件存放这类工具函数。5.4 Docker构建时pip超时换国内源和排OOM现象docker build过程中pip install长时间卡住最后报错exit code 137构建失败。原因基础镜像默认用PyPI官方源国内网络访问不稳定。exit code 137有两个方向一是pip下载超时被杀死二是容器构建内存超限被内核干掉两者处理方式完全不同。解决Dockerfile里的pip install加国内镜像源RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple如果换源后仍然exit 137用docker system df查磁盘占用用dmesg查有没有OOM记录。opencv-python这类带二进制大文件的包有时候内存会吃到2G以上构建时限制一下内存上限docker build --memory4g -t eb_helmet:latest .还要确认Docker Desktop的Resources配置里内存没给太低。这个坑在老款4G内存笔记本上特别容易触发换台8G内存的机器构建往往又好了。Docker日志里不一定会直接告诉你OOM排查必须主动去看系统日志。5.5 ECharts图表白屏容器高度与初始化时机现象页面打开正常接口也返回了数据Network里全是200但图表区域就是空白控制台也不报错。原因最常见的两个一是图表容器div没有显式高度ECharts初始化时计算到的canvas高度是0二是初始化代码在DOM还没渲染完就执行了document.getElementById拿到的是null。解决给容器固定高度把初始化放到$(document).ready里// 容器高度优先在 CSS 或行内样式里显式指定 // div idhelmet_chart stylewidth: 100%; height: 480px;/div $(document).ready(function () { var chart echarts.init(document.getElementById(helmet_chart)); chart.setOption({ // 图表配置 }); });ECharts拿不到宽高时不会报错而是默默画一个看不见的canvas这种黑匣子行为最坑人。排查时右键检查元素看canvas元素的实际高度是不是0一秒定位。还有场景是页面里多个tab切换后图表宽度变成0此时要调用chart.resize()重新计算尺寸$(window).on(resize, function () { chart.resize(); });6. 进阶玩法把单图检测升级成实时摄像头监控与自动告警毕设做到单图检测加Web统计已经能拿不错的分数但想要在“后续怎么落地”的问题上有底气最值得做的升级是把输入源从单图换成视频流再接一个自动告警。摄像头监控场景下检测模型不变要改的是三块输入源改RTSP拉流、循环读帧、检测到未佩戴时推送告警。import cv2 import time import requests # 以 RTSP 协议接入摄像头地址按实际摄像头配置替换 cap cv2.VideoCapture(rtsp://admin:password192.168.1.64:554/stream1) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) model load_model() # 复用项目里的模型加载逻辑 while True: ret, frame cap.read() if not ret: # 网络波动丢帧等一帧再继续避免空帧崩溃 time.sleep(0.5) continue results infer(frame) # 单帧检测返回检测框列表 no_helmet [box for box in results if box.cls 1] if no_helmet: # 有未佩戴者时把时间和数量推送给自己写的告警接口 requests.post(http://127.0.0.1:5000/alert, json{ time: time.strftime(%Y-%m-%d %H:%M:%S), no_helmet_count: len(no_helmet) }, timeout1) # 在本地窗口画出检测框方便现场调试 # draw_boxes(frame, results)cap.set设置分辨率注意RTSP地址里账号密码在正式演示的代码里要打码。requests.post加了timeout1防止告警服务卡死把检测主流程阻塞主流程里任何网络请求都不该无限等待。这段代码放进论文就是“告警模块”配合半页截图系统从单机演示变成准实时监控方案含金量直接提升。我记得第一次给路侧客户做交付时监控端跑了快半小时一次告警都没触发排查到最后发现是告警服务本身的依赖没装全控制台一点提示也没有。从那以后每次交付前都会强制走一遍完整流程启动检测服务、模拟一次未佩戴样本、确认告警推送能收到再交给对方。这个习惯替我拦下了好几次翻车现场。希望帮到你。本文还有配套的精品资源点击获取
返回列表