引言
工业安防领域对 AI 视觉检测的需求日益迫切------火焰识别、安全帽检测、区域入侵告警等场景看似标准,但真正要在一个化工园区内实现多品牌摄像头统一接入、边缘实时推理、告警闭环处理,会面临大量工程细节。本文将从技术选型、系统架构、核心代码实现、到 NPU 部署和优化策略,完整复盘一套基于 YOLO + RK3588 的工业 AI 监控系统的构建过程,并给出中肯的"锐评"和优化路线图。
一、需求分析:8 项核心功能
这套系统瞄准化工园区、智慧工地的安监痛点,覆盖以下检测能力:
- 火焰检测 -- 罐区、装置区、泵房、装卸区早期火焰识别
- 烟雾检测 -- 电缆沟、配电室、仓库、密闭空间烟雾识别,区分粉尘/雾气
- 未佩戴安全帽识别 -- 生产区、巡检、检修、装卸作业实时告警
- 人员区域入侵/越界检测 -- 重大危险源、高压区、罐区、危化仓库禁入报警
- 离岗/睡岗/脱岗检测 -- 中控室、机柜间、压缩机房关键岗位无人值守告警
- 消防通道/安全出口占用检测 -- 消防车通道被车辆货物堵塞告警
- 人员违规行为(抽烟/玩手机/未穿工服) -- 防爆区、动火区、装卸区违规抓拍
- 视频设备异常诊断 -- 摄像头遮挡、黑屏、断线、移位、模糊、强光自动上报
所有功能统一使用 YOLO 目标检测 作为算法基座,并在边缘端(RK3588)完成推理,支持多品牌摄像头 RTSP 拉流。
二、技术选型与架构设计
2.1 为什么选择 YOLO + RK3588?
- 算法成熟度:YOLOv5/v8 在工业安防领域是最主流的目标检测方案,8 项功能均可通过微调数据集实现,难度属于"简单~中等"。
- 边缘部署:RK3588 自带 6TOPS NPU,支持将 PT 模型转换为 RKNN 格式,可实现毫秒级推理,不需依赖云端 GPU。
- 多品牌兼容:采用标准 RTSP 协议,通过 FFmpeg 拉流,适配海康、大华、宇视等主流摄像头。
- 开发效率:Spring Boot 单体架构足够承载管理后台与实时监测调度,搭配 C 语言推理服务实现高性能检测,前后端分离,部署灵活。
2.2 系统架构

(示意图:前端→Spring Boot 管理后台→C 推理服务→RK3588 NPU)
- 前端:Vue/React 管理界面,展示实时监控、告警列表、系统资源看板
- 后端:Spring Boot 3 + SQLite(边缘轻量数据库),负责设备管理、算法绑定、告警记录、流媒体转换
- 推理引擎:C 语言 HTTP 服务(基于 RKNN API 和 libmicrohttpd),接收图片路径,返回检测结果
- 媒体处理:FFmpeg 实现 RTSP→MJPEG 预览、RTSP 抽帧、图片序列合成录像
- 硬件:RK3588 开发板(运行 Linux),连接多个摄像头
2.3 核心流程
摄像头 RTSP → FFmpeg 抽帧 (RtspFrameGrabber)
→ 帧图像文件 → Java 服务调用 C 推理 HTTP 接口
→ 返回检测框 → 告警去重 (AlarmDeduplicator)
→ 证据生成 (抓拍图 + 前后帧合成 MP4)
→ 告警入库 → 前端推送
三、关键代码实现剖析
3.1 数据库设计(SQLite,边缘友好)
系统包含 4 张核心表:camera、models、algorithms、camera_algorithm_binding、alarm_record。表结构通过 Spring Boot 启动时自动创建,并添加了关键索引(如告警时间、状态)。
这种设计支持 "一个摄像头绑定多个算法",例如罐区同一路视频既做火焰检测又做入侵检测。
sql
-- 摄像头算法绑定关系表(简化版)
CREATE TABLE camera_algorithm_binding (
id INTEGER PRIMARY KEY AUTOINCREMENT,
camera_id INTEGER NOT NULL,
algorithm_id INTEGER NOT NULL,
recognition_params TEXT, -- JSON: 检测区域坐标、阈值
alarm_enabled INTEGER DEFAULT 1,
running_status TEXT DEFAULT '运行中',
...
);
3.2 算法-摄像头动态绑定与监测启动
CameraAlgorithmBindingServiceImpl.startYoloMonitoring() 是整个系统的"开关"函数:
根据绑定 ID 获取摄像头 RTSP 地址,解析报警区域参数,然后调用 FrameCaptureService.startCaptureWithConfig() 启动实时监测线程。
java
public boolean startYoloMonitoring(Integer id) {
CameraAlgorithmBinding cb = getInfoById(id);
Camera camera = cameraService.getDetail(cb.getCameraId());
AlarmZoneConfig zoneConfig = parseAlarmConfig(cb.getRecognitionParams());
frameCaptureService.startCaptureWithConfig(camera, zoneConfig);
updateRunningStatus(id, "运行中");
return true;
}
3.3 RTSP 抽帧与帧缓冲(环形队列)
RtspFrameGrabber 通过 FFmpeg 以固定帧率将 RTSP 流抽成单帧 JPEG 图片(覆盖模式,避免磁盘写爆),然后通过 Java 的 WatchService 监听文件修改事件,将新帧推入 CircularFrameBuffer 环形缓冲区。
这个设计保证了检测线程始终能从缓冲区拿到最新的几帧,同时支持回溯生成报警录像。
java
// 单帧覆盖模式 FFmpeg 命令
ffmpeg -rtsp_transport tcp -i rtsp://... -vf fps=5 -update 1 current_frame.jpg
3.4 YOLO 推理客户端与 C 服务交互
Java 端 YoloDetectorClient 通过 HTTP GET 请求将图片路径、报警区域坐标、输出目录传给 C 推理服务,C 服务加载 RKNN 模型完成前处理、推理、后处理,返回 JSON(包含检测框和抓拍图路径)。
C 服务核心实现要点:
- 图像预处理:letterbox 缩放 + 填充到 640x640
- 推理:使用 RKNN API,三尺度特征图解码(YOLOv5 head)
- 后处理:移除多余 sigmoid(RKNN 输出已包含),NMS 去重
- 报警区域判断:仅当目标中心点落入指定区域且类别符合时才计为违规
- 抓拍图绘制:在违规目标周围画红色边界框,并自动保存到输出目录
c
// 检测接口伪代码
if (strncmp(url, "/detect", 7) == 0) {
char* json = detect_and_draw(img_path, ax1, ay1, ax2, ay2, out_dir);
// 返回JSON:{"code":0, "violation":2, "boxes":[...], "snapshot":"/path/to/snapshot.jpg"}
}
3.5 告警去重策略
工业现场最忌"告警风暴"。AlarmDeduplicator 采用"类别 + 中心坐标距离 + 时间窗口"三重抑制:
- 计算检测框中心点,若与缓存中某目标距离小于 80 像素且 5 分钟内曾报警,则忽略
- 缓存自动清理过期记录
- 使用
synchronized确保线程安全(边缘场景摄像头数量有限,简单同步即可)
java
public synchronized boolean shouldAlarm(Integer cameraId, DetectionBox box) {
String key = makeKey(box);
// 遍历同摄像头的历史记录,判断是否接近
for (Map.Entry<String, LocalDateTime> entry : history.entrySet()) {
if (isClose(entry.getKey(), box)) {
return false; // 抑制
}
}
history.put(key, LocalDateTime.now());
return true;
}
3.6 证据留存:抓拍图 + 录像合成
触发告警后,系统从帧缓冲区取出前后几秒的图片序列,调用 VideoRecorder.imagesToMp4() 通过 FFmpeg 合成为 MP4 录像。同时抓拍图已由 C 服务直接生成(带框),两者路径一同存入 alarm_record 表。
前端可直接通过 /api/alarm/{id}/snapshot 和 /api/alarm/{id}/video 接口访问。
3.7 系统监控与 NPU 使用率
SystemMonitorUtil 使用 OSHI 库获取 CPU、内存、磁盘信息,并针对 RK3588 读取 /sys/kernel/debug/rknpu/load 文件,解析三核平均使用率。这解决了前期 NPU 使用率始终为 0 的问题,让运维人员能实时看到推理负载。
四、从"空框架"到"可运行"的演进与锐评
4.1 已完成的关键里程碑
- ✅ 端到端监测流水线 从摄像头绑定到告警入库全链路跑通
- ✅ NPU 推理落地 C 服务调用 RKNN 模型,真实利用硬件加速
- ✅ 告警去重与证据链 抑制重复报警,抓拍图与录像完整可追溯
- ✅ 模型转换工具链 Python Flask 服务支持 PT→ONNX→RKNN,带 WebSocket 进度通知
- ✅ 多品牌摄像头接入 通过 RTSP 统一管理,FFmpeg 转换预览流
4.2 仍待补齐的"硬伤"
-
缺少置信度阈值业务过滤
尽管 C 端已有基础阈值,但未按告警类型(如火焰、安全帽)设置差异化阈值,低分误检仍可能触发报警。
-
RTSP 断流无自动重连
FFmpeg 进程退出后不会自动重启,工业网络抖动会导致监测中断。
-
视频设备异常诊断功能缺失
摄像头遮挡、模糊、移位等诊断代码为零,无法满足 P1 优先级的运维需求。
-
告警推送渠道未实现
告警仅入库,未对接微信/短信/声光报警器,现场人员无法第一时间获知。
-
硬编码路径残留
模型更新接口中仍写死测试路径,模型文件管理混乱。
-
缺乏 API 文档和参数校验
所有接口无验证,输入异常可能直接导致 500 错误。
4.3 下一步优化清单(按优先级)
| 优先级 | 任务 | 说明 |
|---|---|---|
| P0 | 增加按告警类型的置信度阈值配置 | 在应用层过滤低分告警 |
| P0 | 为 RtspFrameGrabber 添加自动重连 |
监测 FFmpeg 退出,延迟 5 秒重启 |
| P1 | 实现基础视频异常检测(模糊、遮挡) | 使用拉普拉斯方差、画面标准差 |
| P1 | 接入企业微信/短信告警推送 | Webhook 实现,成本低 |
| P2 | 训练专用模型(安全帽、火焰、烟雾等) | 利用转换服务生成 RKNN 文件 |
| P3 | 增加全局异常处理和参数校验 | 使用 @RestControllerAdvice 和 Validation |
| P3 | 完善模型版本管理界面 | 支持回滚、批量下载 |
五、总结
这套 YOLO + Spring Boot + RK3588 的 AI 监控系统,已经从方案设计走到了可实际运行的初版产品。它证明了在化工园区这类苛刻场景下,用成熟的目标检测算法配合边缘 NPU 实现实时安防是完全可行的。尽管还有多项工程细节需要打磨,但其清晰的架构分层、解耦的推理服务、务实的去重策略,为后续迭代打下了坚实基础。
对于有类似需求的开发者,这套系统可以直接作为参考实现,根据自己的现场需求裁剪功能、补充数据集、完善告警联动,就能快速落地一套工业级安监平台。
欢迎交流:如果你有任何关于边缘 AI 部署、YOLO 调优或工业安防系统的疑问,欢迎在评论区留言讨论。