端侧 YOLO 检测结合大模型告警
文章目录1. 先写成 JSON2. 先说结论3. 事件字段与上一篇对齐4. 写入事件前先做过滤5. 核心模块event_writer.py6. 先用假数据把事件写入跑通7. 接到现有 YOLO / TensorRT 循环7.1 最小插入方式7.2 视频循环里还要注意7.3 和 detect_trt.py 的分工8. JSON 稳定后再接解释层9. 常见坑9.1 每帧都写 JSON9.2 类别名混乱9.3 先接大模型事件还不稳定9.4 截图路径写了但文件不存在9.5 把 EventWriter 写死进引擎代码深处9.6 多目标同一帧全部写成事件9.7 事件目录与检测工作目录不一致10. 验收清单11. 小结12. 相关阅读摘要上一篇把端侧应用封装成「检测 → 事件 → 小模型解释」。卡点通常不在解释脚本而在检测结果仍停在画框上下游拿不到稳定输入。本文写如何把现有 YOLO / TensorRT 检测输出自动写成events/*.json字段约定、阈值过滤、冷却去重、截图保存以及怎样接到已有推理循环。适合已经跑通 Orin 检测闭环准备接大模型解释层的人。可与 Orin 上目标检测 大模型做端侧应用、Orin 上目标检测最小闭环 一起看。建议目录可与上一篇共用mkdir-p~/orin-edge-app/{events,scripts,out,logs,snapshots}cd~/orin-edge-app# 本文新增event_writer.py / demo_from_detections.py / watch_and_explain.sh文件作用scripts/event_writer.py过滤、冷却、写 JSON、可选存截图scripts/demo_from_detections.py用一组假检测结果验证事件写入逻辑scripts/watch_and_explain.sh监听到新事件后调用解释脚本可选1. 先写成 JSON很多检测程序到这一步就停了屏幕上有框终端打印了检出 N 个目标下一帧继续画对值班系统和大模型解释层来说这还不够。它们需要的是可消费的记录什么时间、哪路相机、什么类别、置信度多少、要不要重复报。图1. 画框是给人看的events/*.json才是给下游系统看的。所以本篇目标很具体不重写整个检测工程只在“得到 boxes / scores / cls_ids”之后多写一步把结果保存成事件文件。2. 先说结论步骤做什么1复用上一篇的事件字段保证解释层不用改2只对白名单类别 高置信度目标写事件3同一相机、同一类别加冷却避免短时间重复告警4把结果写成 JSON同时可选保存截图路径5JSON 稳定后再接explain_event.py事件层是检测和大模型之间的稳定接口。先过滤和冷却再谈解释否则语言模型会被误报灌爆。先用假检测数据把事件写入跑通再挂到真实detect_trt.py循环。图2. 检测输出 → 过滤 → 冷却 → 写成 JSON。3. 事件字段与上一篇对齐继续使用这套字段与上一篇一致便于直接喂给解释脚本字段来源event_id相机 时间 序号ts告警时刻camera_id/line_id配置写入defect类别名由 cls_id 映射confidence检测分数bbox[x1,y1,x2,y2]取整即可repeat_count_1min冷却窗口内计数snapshot_path可选截图kb_hint可选先留空或写固定提示示例{event_id:cam01-20260804-093000-001,ts:2026-08-04T09:30:00,camera_id:cam01,line_id:line-A,defect:scratch,confidence:0.91,bbox:[100,120,240,260],repeat_count_1min:2,snapshot_path:snapshots/cam01_20260804_093000.jpg,kb_hint:}4. 写入事件前先做过滤图3. 白名单、阈值、冷却决定事件质量。规则建议默认说明类别白名单只保留缺陷类COCO 通用模型先自己映射关心的类置信度阈值如0.50起可比可视化阈值更高减少垃圾事件冷却时间如同相机同类1030s防止同一缺陷每帧都写文件没有这三个规则大模型解释层会变成“误报扩音器”。5. 核心模块event_writer.py保存为scripts/event_writer.py#!/usr/bin/env python3把检测结果写成 events/*.json。 输入约定 boxes: Nx4, xyxy scores: N cls_ids: N from__future__importannotationsimportjsonimporttimefromdataclassesimportdataclass,fieldfromdatetimeimportdatetimefrompathlibimportPathfromtypingimportDict,Iterable,List,Optional,Sequence,Tupleimportcv2importnumpyasnpdataclassclassEventWriterConfig:events_dir:PathPath(events)snapshots_dir:PathPath(snapshots)camera_id:strcam01line_id:strline-Aclass_names:Dict[int,str]field(default_factorydict)allow_classes:Optional[set]None# 空全开建议填缺陷类名集合conf_thres:float0.5cooldown_sec:float15.0save_snapshot:boolTruekb_hint:strclassEventWriter:def__init__(self,cfg:EventWriterConfig):self.cfgcfg self.cfg.events_dir.mkdir(parentsTrue,exist_okTrue)self.cfg.snapshots_dir.mkdir(parentsTrue,exist_okTrue)self._last_fire:Dict[Tuple[str,str],float]{}self._repeat_1min:Dict[Tuple[str,str],List[float]]{}self._seq0def_classname(self,cls_id:int)-str:returnself.cfg.class_names.get(int(cls_id),str(int(cls_id)))def_allowed(self,name:str)-bool:ifnotself.cfg.allow_classes:returnTruereturnnameinself.cfg.allow_classesdef_repeat_count(self,key:Tuple[str,str],now:float)-int:arr[tfortinself._repeat_1min.get(key,[])ifnow-t60.0]arr.append(now)self._repeat_1min[key]arrreturnlen(arr)defwrite_detections(self,boxes:Sequence[Sequence[float]],scores:Sequence[float],cls_ids:Sequence[int],frame_bgr:Optional[np.ndarray]None,)-List[Path]:返回本帧新写入的事件文件路径。written:List[Path][]nowtime.time()tsdatetime.now().strftime(%Y-%m-%dT%H:%M:%S)stampdatetime.now().strftime(%Y%m%d_%H%M%S)forbox,score,cls_idinzip(boxes,scores,cls_ids):iffloat(score)self.cfg.conf_thres:continuenameself._classname(int(cls_id))ifnotself._allowed(name):continuekey(self.cfg.camera_id,name)lastself._last_fire.get(key,0.0)ifnow-lastself.cfg.cooldown_sec:# 冷却期内仍计入 1 分钟重复次数但先不写新文件self._repeat_count(key,now)continueself._last_fire[key]now repeatself._repeat_count(key,now)self._seq1event_idf{self.cfg.camera_id}-{stamp}-{self._seq:03d}snapshot_pathifself.cfg.save_snapshotandframe_bgrisnotNone:snapself.cfg.snapshots_dir/f{self.cfg.camera_id}_{stamp}_{self._seq:03d}.jpgcv2.imwrite(str(snap),frame_bgr)snapshot_pathstr(snap)x1,y1,x2,y2[int(round(float(v)))forvinbox]event{event_id:event_id,ts:ts,camera_id:self.cfg.camera_id,line_id:self.cfg.line_id,defect:name,confidence:round(float(score),4),bbox:[x1,y1,x2,y2],repeat_count_1min:repeat,snapshot_path:snapshot_path,kb_hint:self.cfg.kb_hint,}outself.cfg.events_dir/f{event_id}.jsonout.write_text(json.dumps(event,ensure_asciiFalse,indent2)\n,encodingutf-8)written.append(out)returnwrittendefdemo_boxes():无引擎时的本地自测数据。boxesnp.array([[100,120,240,260],[300,80,400,180]],dtypenp.float32)scoresnp.array([0.91,0.32],dtypenp.float32)cls_idsnp.array([0,2],dtypenp.int32)returnboxes,scores,cls_ids这段代码保持独立不绑定某一版 TensorRT 封装只要提供boxes/scores/cls_ids就能用。6. 先用假数据把事件写入跑通保存scripts/demo_from_detections.py#!/usr/bin/env python3不依赖引擎先验证 EventWriter 是否正常写出事件。frompathlibimportPathimportsys sys.path.append(str(Path(__file__).resolve().parent))fromevent_writerimportEventWriter,EventWriterConfig,demo_boxes# noqa: E402defmain()-None:cfgEventWriterConfig(events_dirPath(events),snapshots_dirPath(snapshots),camera_idcam01,line_idline-A,class_names{0:scratch,1:dent,2:person},allow_classes{scratch,dent},# person 会被过滤conf_thres0.5,cooldown_sec5.0,save_snapshotFalse,kb_hint历史相似导轨毛刺可能导致周期性划痕,)writerEventWriter(cfg)boxes,scores,cls_idsdemo_boxes()foriinrange(3):pathswriter.write_detections(boxes,scores,cls_ids,frame_bgrNone)print(fround{i1}written{[str(p)forpinpaths]})if__name____main__:main()cd~/orin-edge-app python3 scripts/demo_from_detections.pylsevents/catevents/*.json|head预期第 1 轮写入scratchperson因白名单被滤低分目标因阈值被滤第 2、3 轮若在冷却期内不再重复写同相机同类文件确认这一点后再接到真实检测循环排障会轻松很多。7. 接到现有 YOLO / TensorRT 循环图4. 在得到 boxes 之后插入 EventWriter不必重写引擎加载。以 Orin 上目标检测最小闭环 里的流程为例你已经有preprocess → infer → postprocess → boxes/scores/cls_ids → draw只需在draw前后加上事件写入。关键不是改 TensorRT 初始化而是确认一件事引擎负责推理事件模块负责“哪些结果值得留下”。7.1 最小插入方式# 放在检测主程序同目录或把 scripts 加进 PYTHONPATHfrompathlibimportPathfromevent_writerimportEventWriter,EventWriterConfig writerEventWriter(EventWriterConfig(events_dirPath(events),snapshots_dirPath(snapshots),camera_idcam01,line_idline-A,# 按你的类别映射改若是自训缺陷模型这里写缺陷名class_names{0:scratch,1:dent},allow_classes{scratch,dent},conf_thres0.5,cooldown_sec15.0,save_snapshotTrue,))# ... 推理得到 boxes, scores, cls_ids, frame ...pathswriter.write_detections(boxes,scores,cls_ids,frame_bgrframe)forpinpaths:print(f[event]{p})7.2 视频循环里还要注意若你用的是视频或相机循环下面几条比“会不会写 JSON”更容易踩坑每帧都可能有框但不代表每帧都该写事件冷却就是为这个场景准备的。没有冷却解释队列和磁盘都会先被打满。截图保存必须限频1080p 连续存 JPEG几小时就能把小容量系统盘写满。事件可以留截图可先关或只在成功写出事件时存。类别映射一定要显式写清不要默认把cls_id当缺陷名。自训模型还好办若临时用 COCO 权重做联调更要在配置里写明“演示映射”避免后面误当成业务类别。告警阈值可以高于可视化阈值画面上0.25能看到框不代表就要写事件。事件阈值建议更严例如0.5起先保证下游干净。先统计“每分钟事件数”接大模型前先看真实运行 10 分钟会写出多少 JSON。若已经上百条先调白名单和冷却不要先开解释。7.3 和detect_trt.py的分工更稳的结构是两个文件文件职责detect_trt.py/ 相机循环读帧、推理、画框、展示event_writer.py过滤、冷却、写出事件不要把事件逻辑塞进 TensorRT 封装类深处。下次换导出方式、换后处理事件层还能原样复用。COCO 预训练权重做质检 demo 时常见做法是优先改用自训缺陷模型或临时把某个类映射成演示缺陷名但配置和日志里必须写清楚这是演示映射8. JSON 稳定后再接解释层图5. 事件接口稳了上一篇的explain_event.py才能真正进工作流。可选监听到新文件就解释先串行别一上来高并发。保存scripts/watch_and_explain.sh#!/usr/bin/env bashset-euopipefailEVENTS_DIR${1:-events}MODEL${MODEL:-qwen2.5:7b}PROMPT${PROMPT:-prompts/explain_alarm.txt}OUT_DIR${OUT_DIR:-out}mkdir-p$OUT_DIR# 需要 inotifywaitsudo apt-get install -y inotify-toolsinotifywait-m-eclose_write--format%w%f$EVENTS_DIR|whileread-rf;docase$fin*.json)base$(basename$f.json)echo[explain]$fpython3 scripts/explain_event.py\--event$f\--prompt$PROMPT\--model$MODEL\--out$OUT_DIR/${base}.txt||echo[explain failed]$f;;esacdonechmodx scripts/watch_and_explain.sh# 先确保 explain_event.py 与 prompts/explain_alarm.txt 已按上一篇就位# ./scripts/watch_and_explain.sh events没有inotify-tools时也可以简单轮询python3 -PY from pathlib import Path import time, subprocess seenset() while True: for p in sorted(Path(events).glob(*.json)): if p in seen: continue seen.add(p) outPath(out)/(p.stem.txt) print(explain, p) subprocess.run([ python3,scripts/explain_event.py, --event,str(p),--out,str(out) ], checkFalse) time.sleep(1) PY9. 常见坑9.1 每帧都写 JSON结果磁盘爆、解释队列堵、值班端重复告警过多。处理冷却 更高告警阈值。先看ls events | wc -l不要凭感觉。9.2 类别名混乱cls_id0直接当缺陷名解释层会不知所云。处理显式class_names映射并在日志里打印映射后的defect。9.3 先接大模型事件还不稳定模型会把垃圾输入组织成很像样的废话。处理先ls events cat人工看 20 条确认字段和类别都对再接解释。9.4 截图路径写了但文件不存在解释或复盘时对不上。处理检查cv2.imwrite是否成功磁盘满时先关截图只留 JSON。9.5 把 EventWriter 写死进引擎代码深处后期换 Ultralytics / TensorRT 版本会很痛。处理保持“推理后钩子”这种薄接入。9.6 多目标同一帧全部写成事件一帧里 8 个同类框可能对应同一物理缺陷的多次响应。处理同一帧内可先按类别取最高分或提高冷却不要无脑全写。9.7 事件目录与检测工作目录不一致检测在~/orin-detect跑事件写到别处解释脚本找不到。处理在配置里写绝对路径或统一到~/orin-edge-app/events。10. 验收清单检查项通过标准假数据脚本能写出至少 1 个 JSON字段齐全白名单不关心的类不会写成事件冷却短时间重复框不会狂写文件真检测接入有框且超阈值时出现新 JSON解释衔接任选一个 JSON 能跑通explain_event.py# 快速抽查最近事件ls-ltevents|headpython3 -PY import json,glob filessorted(glob.glob(events/*.json)) print(count,len(files)) if files: print(json.load(open(files[-1],encodingutf-8))) PY11. 小结把端侧 YOLO 检测结果接到大模型告警本质是补上检测与大模型之间的接口层统一字段阈值 白名单过滤冷却去重写成 JSON并可选取景再交给解释脚本先让检测结果变成可消费事件端侧大模型才接得上否则再强的模型也只是对着空气聊天。12. 相关阅读Orin 上目标检测 大模型做端侧应用Orin 上目标检测最小闭环Orin 上跑本地大模型适合什么场景本地大模型跑通了为什么还是不好用相关链接Ultralytics YOLOv8Ollama OpenAI compatibility如果这篇对你有帮助欢迎点赞、收藏也欢迎关注后续更新。

相关新闻

Claude Code CLI:提升开发效率的命令行工具详解

Claude Code CLI:提升开发效率的命令行工具详解

1. Claude Code 命令行工具概述Claude Code CLI(命令行界面)是一个功能强大的开发辅助工具,它通过简洁的命令语法为开发者提供了高效的工作流。这个工具最初是为了解决IDE环境中常见的重复性操作问题而设计的,现在已发展成为支持多…

2026/10/7 5:02:20 阅读更多 →
Java集合框架面试核心考点与深度解析

Java集合框架面试核心考点与深度解析

1. Java集合面试题全面解析作为Java开发者,集合框架是面试必考的核心知识点。我在技术面试中经常遇到候选人因为对集合理解不够深入而错失机会的情况。本文将系统梳理Java集合框架中的高频考点,结合我作为面试官的实际经验,分享那些真正能打动…

2026/10/14 20:26:28 阅读更多 →
Office自动化部署终极指南:LKY_OfficeTools一键搞定办公软件安装

Office自动化部署终极指南:LKY_OfficeTools一键搞定办公软件安装

Office自动化部署终极指南:LKY_OfficeTools一键搞定办公软件安装 【免费下载链接】LKY_OfficeTools 一键自动化 下载、安装、激活 Office 的利器。 项目地址: https://gitcode.com/GitHub_Trending/lk/LKY_OfficeTools 还在为繁琐的Office安装过程头疼吗&…

2026/10/12 4:29:35 阅读更多 →

最新新闻

C++类和对象(下)初始化列表、类型转换、static、友元、内部类、匿名对象

C++类和对象(下)初始化列表、类型转换、static、友元、内部类、匿名对象

一.再探构造函数之初始化列表• 之前实现构造函数时,初始化成员变量都是在函数体内赋值,构造函数初始化还有一种方式:初始化列表。初始化列表的使用方式是:在函数定义处的参数列表后(在声明和定义分离时就在真正定义的…

2026/10/14 21:16:56 阅读更多 →
全球纯油车份额跌破50%,油车时代真的要终结了?

全球纯油车份额跌破50%,油车时代真的要终结了?

这些年,伴随着全球新能源汽车的高速发展,燃油车式微的话题早就屡见不鲜,但是除了中美等国,各地的新能源汽车替代似乎也还没有那么快,但是就在最近全球纯油车份额跌破50%的消息传来,让人不禁想问这油车时代真…

2026/10/14 21:16:56 阅读更多 →
EtherCAT 主站拓扑判定的三级防护:从去抖到振荡检测

EtherCAT 主站拓扑判定的三级防护:从去抖到振荡检测

从 EtherCAT 主站拓扑判定说起:工业级“稳定”不是简单延时 做工控协议栈的人大概都懂,真正难的不是“能通”,而是“通了之后怎么证明它是真的通了”。在自研 EtherCAT 主站时,遇到一个很典型的工程问题:**如何判断从站…

2026/10/14 21:16:56 阅读更多 →
Python aiida-cp2k 包完全指南与实战案例

Python aiida-cp2k 包完全指南与实战案例

1. 引言aiida-cp2k 是 AiiDA(Automated Interactive Infrastructure and Database for Computational Science)生态中用于 CP2K 材料模拟软件的插件包。它把 CP2K 的输入输出与 AiiDA 的数据管理、工作流调度和计算追踪能力结合起来,让科研人…

2026/10/14 21:16:56 阅读更多 →
自动化表单收集与数据整理:‘龙虾Claw’轻量级工具实践

自动化表单收集与数据整理:‘龙虾Claw’轻量级工具实践

最近把团队内部用了几个月的“龙虾Claw”自动化表单收集工具整体重构了一遍,顺手把设计思路和踩坑过程整理成这篇记录。它解决的是一个很具体的场景:日常统计工作中反复出现的表单下发、填写、催缴、汇总、核对这一整条链路的自动化。如果你也在做类似的…

2026/10/14 21:16:56 阅读更多 →
合规数据可视化与PHP后端实战:构建彩票数据管理系统

合规数据可视化与PHP后端实战:构建彩票数据管理系统

简介:PHP模拟私彩程序平台源码包,由作者小满制作,面向具备一定PHP基础、希望了解彩票业务逻辑与Web交互开发的读者。项目使用原生PHP构建,核心功能涵盖投注、开奖、结果展示、奖金计算及用户账户管理,并配有页面样式与…

2026/10/14 21:15:55 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →