基于YOLO与SpringBoot的安全锥检测系统实战全记录

发布时间:2026/9/9 1:37:23
基于YOLO与SpringBoot的安全锥检测系统实战全记录 最近在做智慧工地相关的东西赶上现场安全巡检这块需求最头疼的其实是眼前那些不起眼却极其重要的安全设施——锥桶。平时我们叫它安全锥、反光锥施工路段、厂区作业、隧道维保全都靠它把人车隔离在危险区之外。传统的监控方案基本上就是摄像头拍下来然后让保安盯着屏幕看十几个画面轮播一个走神就可能漏掉关键情况。把“基于YOLOv8/YOLOv10/YOLOv11/YOLOv12与SpringBoot的安全锥检测系统”这套东西做完之后整个流程就完全不一样了视频帧自动抽出来YOLO把锥桶识别出来并打框后端用SpringBoot做业务串联前端走前后端分离的Web界面实时展示再到千问和DeepSeek这对大模型组合来做场景研判输出一段“当前区域防护是否到位”的文字结论。整套系统既能做离线图片分析也能接视频轮巡适合智慧工地、交通巡查、园区安防这类需要低成本快速落地的场景。这篇就是我整理出来的项目全记录。系统本身并不复杂但牵扯的技术栈很杂模型训练、后端接口、前端页面、大模型调用全都得考虑。我会从需求梳理开始讲再把YOLO系列怎么选、SpringBoot怎么集成、大模型怎么接入一个个讲清楚最后把现场踩过的坑一并列出来。1. 项目背景与整体技术架构1.1 为什么要单独做一个安全锥检测系统先说需求来源。工地现场每天会摆放大量锥桶普通监控系统只能记录画面不会告诉你“哪个区域少了锥桶”。而安全锥这类设施恰恰是防撞隔离的第一道防线摆放不到位、被车辆撞倒、或者晚上反光条老化失效都可能导致安全事故。人工巡检方式有几个明显痛点第一覆盖面不足一位安全员管不了整个园区第二巡检记录靠纸质或Excel事后追溯难第三夜班时段人眼疲劳漏判概率高。所以客户实际要的不是一个能识别100种物体的通用模型而是能专门针对锥桶这类小目标做到稳定识别、快速反馈、并且能和管理系统打通的检测服务。安全锥检测看起来比通用目标检测要简单目标外观也比较固定但真正落地时问题不少锥桶体积不大在远端摄像头里可能只占几十个像素颜色多样有橙红色、黄色、带反光条的光照变化剧烈白天强光、夜间反光背景复杂路面、绿化带、围挡、人车都可能干扰。这决定了我们最好基于YOLO做微调训练而不是拿一个预训练模型直接硬跑。1.2 YOLO系列几个版本怎么选YOLO是我一直比较偏好的检测方案部署轻、速度够快、社区案例多。现在标题里写了YOLOv8、YOLOv10、YOLOv11、YOLOv12这里我把四个版本在实际项目里的表现做个对比。版本核心改进工程成熟度备注YOLOv8Anchor-Free、C2f模块、Decoupled Head最高Ultralytics官方支持资料最多适合作为基线模型YOLOv10引入One-to-Many Head与One-to-One Head训练完推理时无需NMS较高省掉NMS后处理推理延迟更低适合高并发场景YOLOv11在C3K2模块、C2PSA注意力机制上做了优化中等准确率和速度平衡得不错文档逐步完善YOLOv12引入Area Attention和可变形卷积注意力机制进一步改进中等对工程兼容性要求高适合追求指标的同学尝试安全锥这种目标属于地面静态小目标尺寸变化大远小近大。我建议以YOLOv8作为稳妥基线把v12当作实验版本去比精度和速度。如果检测目标是几十类通用物品为了省NMS后处理时间可以用v10如果目标种类少、算力一般v8s的性价比反而是最高的。1.3 整体技术栈与数据流向这套系统采用的是标准的前后端分离架构核心组件如下Java SpringBoot负责业务接口、鉴权、任务调度、历史记录、调用Python推理服务、调用大模型API。Python推理服务加载YOLO权重提供图片检测接口返回检测框、类别和置信度。Vue3前端登录、监控页面、检测结果列表、统计面板、配置管理。MySQL存用户、检测记录、分析结论。Redis缓存热点数据、任务状态。千问与DeepSeek对检测结果做场景化自然语言分析。整个链路里最核心的数据流是前端上传图片或者定时从摄像头抓帧 - SpringBoot生成任务ID - Python推理服务做YOLO检测 - 检测结果回写MySQL - 前端轮询拿结果并绘制检测框 - SpringBoot再携带检测结果请求大模型接口 - 大模型返回文本分析 - 前端展示分析结论。这样设计的好处是各个模块职责分离模型可以独立迭代换模型不影响业务层大模型接口被单独封装一切业务逻辑都暴露成SpringBoot的REST接口前端只跟后端交互。2. 系统核心功能拆解与开发前置准备2.1 核心功能模块与接口定义在动手写代码之前一定要把功能边界和接口约定理清楚。我整理了下面这些核心模块用户登录与权限JWT登录区分管理员和普通巡检账号。图片检测上传图片返回目标数量、坐标列表、检测耗时支持安全锥缺失预警。视频检测定时抽取RTSP流帧检测后生成事件记录。历史记录查询按时间、区域、风险等级筛选支持查看检测结果截图。AI分析把检测结果结构化数据喂给大模型生成巡检小结和整改建议。配置管理切换YOLO模型版本、设置大模型API密钥、调整检测阈值。接口层面统一返回JSON结构包含code、message、data三个字段。分页接口固定传pageNum和pageSize。上传图片接口用MultipartFile接收文件检测接口提交后立即返回taskId前端轮询查询状态避免长时间HTTP阻塞。2.2 工程目录结构与职责划分后端工程我建议按业务模块划分而不是按技术层划分这样多人协作时冲突少。参考目录结构如下safety-cone-backend ├── src/main/java/com/example/safetycone │ ├── controller │ │ ├── AuthController.java │ │ ├── DetectController.java │ │ ├── HistoryController.java │ │ └── AnalysisController.java │ ├── service │ │ ├── DetectService.java │ │ ├── AiAnalysisService.java │ │ └── UserService.java │ ├── client │ │ ├── YoloInferenceClient.java │ │ ├── QwenClient.java │ │ └── DeepSeekClient.java │ ├── entity │ ├── mapper │ └── config │ ├── CorsConfig.java │ ├── RedisConfig.java │ └── AsyncConfig.java ├── src/main/resources │ ├── application.yml │ └── mapper └── pom.xmlPython推理服务我单独放一个工程目录上也不用复杂fastapi入口、yolo_detector、prompt_builder这几个文件就够了。最关键的是把YoloInferenceClient和DeepSeekClient这类外部依赖全部封装成独立Client不要散落在Service里。后面换模型、换大模型服务商只改一个类就好。2.3 开发环境与依赖管理Java版本我用JDK17SpringBoot用2.7.x。SpringBoot版本太高容易碰到依赖兼容问题尤其在集成一些老版本数据库驱动或者加密组件时。如果创建项目总是超时先在Maven的settings.xml里配置国内镜像。Python环境建议用Python3.10CUDA版本根据显卡来定。我踩过比较典型的坑是在老显卡上装CUDA如果显卡不支持就不要硬装直接用CPU推理把batch压小一点单帧延迟高一些但能用。显卡这一块比如RX580这种卡确实能跑YOLOv8但是训练非常慢推荐训练用云GPU推理用小批量CPU或GPU都能扛住。前端我使用Vue3ViteElementPlusNode版本18以上。多目标检测的结果展示用Canvas绘制检测框比直接用DOM渲染更流畅。3. YOLO数据集处理与模型训练全流程3.1 数据集来源与标注格式安全锥数据集主要来自两个渠道一是工地现场自己拍白天、夜晚、雨天、不同角度各拍几百张二是从公开数据集中筛出包含锥桶的图片像KITTI这类自动驾驶数据集偶有出现锥桶的目标框但是原始格式是KITTI的txt格式需要转换成YOLO格式。这里补充一下KITTI转YOLO的要点KITTI每一行是类别、截断、遮挡、观察角度、bbox坐标而YOLO需要的是归一化后的中心点坐标和宽高所以写脚本时先解析KITTI的left/top/right/bottom再除以图片宽高得到cx、cy、w、h。标注工具用LabelImg或Roboflow。YOLO标注格式每行如下class_id cx cy w h比如一张宽1920、高1080的图片有一个锥桶检测框左上角(500, 300)右下角(620, 700)标签为0那么转换后的内容是0 0.2917 0.4630 0.0625 0.3704这里的cx (500620)/(21920)cy (300700)/(21080)w (620-500)/1920h (700-300)/1080。新手最容易在对齐坐标系时出错要先确认图片宽高和框坐标是否同步缩放。3.2 数据增强与训练集划分安全锥在不同距离下的尺度差异很大训练数据里一定要包含小目标样本。光靠原始图片不够我给处理流程加了这些增强策略Mosaic增强把四张图拼接成一张提升模型对复杂背景的适应能力。随机翻转上下左右翻转注意翻完后标签坐标要同步变换。HSV扰动调整色相、饱和度、明度模拟早晨和傍晚的光线。随机缩放与裁剪模拟远景里锥桶变小的情况。训练集、验证集、测试集按8:1:1划分划分时要保证同一场景的画面尽量只出现在一个集合里否则容易高估模型泛化能力。3.3 模型配置文件与训练参数用Ultralytics训练时第一步是准备数据集yaml。train: /data/safety_cone/train/images val: /data/safety_cone/val/images nc: 1 names: [safety_cone]这里类别数量按实际需求设置如果只想判断“有没有锥桶”nc1就够了。如果要分类标识反光锥桶和普通锥桶nc就要对应改成2。训练命令我实际跑过的是yolo detect train datacone.yaml modelyolov8s.pt imgsz640 batch16 epochs100 lr00.01如果训练loss不降优先检查学习率是否过大或者调整到0.001重试。安全锥背景比较简单100个epoch完全足够不用硬跑300轮。训练结束看weights/best.pt和last.ptval集上的mAP50如果能到0.9以上这个模型就可以进测试流程了。3.4 训练过程中的损失函数观察YOLO的损失函数由三部分组成分类损失、定位损失、置信度损失。定位损失在YOLOv8里主要是CIoU Loss用于衡量预测框和真实框的重合程度分类损失用BCEDFL损失用于分布聚焦。训练日志里box_loss、cls_loss、dfl_loss三个值是逐步下降的如果box_loss反复震荡说明数据或者学习率可能有问题。我遇到过一个比较有迷惑性的现象loss下降很顺利但验证集的mAP不高。后来排查发现是训练图片里锥桶出现频繁背景也大量出现相似颜色物体模型学到的是“颜色纹理”而不是“锥桶结构”。解决办法是增加负样本把没有锥桶但颜色相似的道路图也放进训练集。3.5 模型导出与推理加速训练完成后最好导出成ONNX再部署不直接依赖PyTorch推理这样启动速度和推理速度都好一些。导出命令yolo export modelbest.pt formatonnx imgsz640如果机器支持TensorRT且性能要求极高可以再走一步trt导出但工程复杂度会上去建议先ONNX起步。Python推理服务里用onnxruntime加载模型比Ultralytics原生的predict接口要轻量很多并发处理能力也更强。4. SpringBoot集成YOLO推理与大模型分析4.1 SpringBoot如何调用Python推理服务后端与Python推理服务之间用REST接口通信SpringBoot侧使用RestTemplate或WebClient。Python服务我建议用FastAPI接口定义如下app.post(/detect) async def detect(file: UploadFile File(...)): image await file.read() boxes detector.predict(image) return {success: True, boxes: boxes}返回的boxes里每一项包含x1、y1、x2、y2、confidence、class_id、class_name。SpringBoot拿到之后转换成实体类存储。这里有几个值得注意的点。一是图片传输尽量用字节流而不是Base64Base64会放大30%以上的体积高并发时网络开销明显二是每个检测请求尽量不要同步等待把任务丢进线程池前端轮询结果三是Python推理服务要做好并发控制YOLO推理不是线程安全的我用一个全局队列加线程池来控制并发度。4.2 接入千问与DeepSeek的大模型分析大模型在这里不是做目标检测的而是对检测结果做文本理解和研判。当YOLO返回检测框之后SpringBoot会把结构化数据整理成文本再请求大模型。举个例子假设检测到3个安全锥分布于画面左下角和右下角我可以构造成这样的Prompt你是一名施工安全巡检专家。下面是某作业区域YOLO目标检测的结构化结果 检测时间2025-01-12 14:32:10 检测目标safety_cone 目标数量3 目标位置分布左下角2个右下角1个中心区域0个 请分析该区域的安全防护情况判断安全锥是否覆盖了关键风险点 输出格式问题概述风险等级整改建议。控制在150字以内。千问我用DashScope的APIDeepSeek走OpenAI兼容接口。代码上可以做成一个AIAnalysisService内部根据配置决定调用哪一家模型两家都返回统一的结论对象。为了避免每次查询都打大模型接口检测结果第一次分析完成后就把结论写进MySQL并在Redis里做缓存设置TTL为2小时。4.3 大模型接口调用的工程细节调用外部大模型最怕延迟和不稳定。实际项目里我不能让前端一直挂着等大模型返回所以把大模型分析做成了异步任务。检测完成后先返回“分析中”状态前端在展示时显示一个加载动画等异步回调完成再刷新页面。外部API调用的一个核心兜底逻辑是大模型返回的内容必须能解析。我在Prompt里强制让模型返回JSON格式同时在代码里做了容错如果JSON解析失败就把原始文本原样存下来不让整个接口报错。还遇到过限流的情况尤其是并发请求量上来之后大模型接口会返回频率超限。这边处理办法很简单引入信号量控制并发调用数量超出的请求排队等待而不是直接打爆API。5. Web交互界面设计与前后端联调5.1 前端页面功能规划前端我用Vue3搭建整体页面分成五个区块登录页账号密码登录登录成功后把token存到localStorage。监控大屏左侧摄像头列表中间是图片或视频检测区域检测框实时绘制在Canvas上。检测详情弹窗点击风险记录后展示大模型的分析结论。历史记录页支持按日期范围、风险等级筛选检测记录。配置中心更换模型版本、设置检测置信度阈值、配置大模型API模式。页面设计上不用追求花哨关键是把“检测数量、目标框、AI分析结论”这三类信息展示清楚。安全锥数量直接用数字卡片展示并用红黄绿状态灯反映风险等级。5.2 图片检测与视频检测的实现思路图片检测流程比较简单前端用FormData上传图片SpringBoot接口接收后保存文件同时创建检测任务返回taskId。前端每隔2秒轮询一次任务状态状态为SUCCESS时获取检测结果并在Canvas上绘制检测框。视频检测这里我走了两条路。一种是对RTSP流做HLS转发的路子后端用FFmpeg把RTSP流转成HLS切片前端播放视频同时后端定时抽帧跑检测。这种方式界面流畅但是工程量偏大。另一种是简单的“定时截图”方案后端每隔5秒抓取一帧直接检测并把画好框的JPEG推给前端前端每秒刷新图片。实际工地场景里第二种方案完全够用代码量少而且稳定得多。5.3 前后端分离联调与跨域处理开发环境最常遇到的是跨域问题。解决方式我选择在后端统一配置CorsFilter允许前端开发服务器的来源地址。生产环境则用Nginx做反向代理前端请求同域下的/apiNginx再把请求转发到SpringBoot服务。生产部署时需要注意三个细节一是前端静态资源用Nginx托管并通过Nginx配置gzip压缩二是SpringBoot服务以JAR包方式运行端口通过环境变量注入不要把端口硬编码三是图片上传目录要持久化到宿主机不能放在容器里否则重启就丢文件。5.4 关于数据库表设计检测记录方面的表结构比较简单但一定要考虑好查询维度。我建了下面这几张表user用户ID、用户名、密码密文、角色、最近登录时间。detect_task任务ID、任务类型、图片路径、检测状态、创建时间。detect_result结果ID、任务ID、目标类别、坐标、置信度。ai_analysis分析ID、任务ID、风险等级、分析结论、原始JSON。数据库设计这里提醒一句项目里涉及密码等敏感字段一定要加密存储大模型APIKey这类配置不要写死在application.yml里使用环境变量注入或者用Jasypt把yml里的密文解密。热词里有人提到“springboot yml密文”说的就是这个场景。6. 实测过程中的高频问题与排查方法6.1 YOLO训练与部署的“翻车”经验第一训练不收敛。安全锥数据集不大如果直接把batchsize开到64显存不够不说模型还可能振荡。建议batch从16开始学习率保持0.01。第二导出ONNX失败。常见原因是torch版本和onnx版本不匹配升级onnx到最新版再试试。另外imgsz必须是32的倍数设置成640是最稳妥的。第三老显卡/AMD显卡跑不起来。很多同学的电脑是RX580这种卡本身不是不能跑但要装对应的ROCm或者老版本CUDA支持。实在折腾不明白就直接用CPU推理把图片压缩到640x640一张图大概几百毫秒用于实时性要求不高的轮询场景足够了。6.2 SpringBoot项目常见问题SpringBoot创建项目超时是IDE拉取Spring Initializr元数据失败把Maven和Gradle仓库地址改成国内镜像即可。SpringBoot版本太高导致依赖冲突尤其是碰到tomcat、activemq这类构件推荐统一用2.7.x版本。还有一个比较实用的技巧如果项目里加了mybatis-plus或者JPA希望表不存在时自动建表JPA可以直接配置ddl-autoupdatemybatis-plus可以用自动填充和DDL脚本初始化。但是生产环境我不建议依赖自动建表表结构还是通过SQL脚本管理更稳妥。6.3 前后端联调的隐蔽坑前端轮询太频繁会拖垮后端接口建议每次轮询间隔至少1秒最好2秒。图片上传请求体太大导致超时SpringBoot需要手动调大spring.servlet.multipart.max-file-size参数。WebSocket和鉴权放在一起时前端的token要通过query参数传递因为部分WebSocket客户端不认自定义Header这块排查起来比较隐蔽。6.4 大模型接入的不确定性处理大模型在整条链路里属于“锦上添花”的模块它的输出不能作为唯一判断依据。如果大模型API挂了系统核心的YOLO检测功能仍然必须可用。我在设计时默认把大模型分析结果做成可降级的调用失败时不阻塞主流程只记录异常日志前端提示“AI分析暂时不可用已展示原始检测结果”。使用DeepSeek或千问时要留意不同模型的版本差异。DeepSeek的对话模型对长Prompt的响应质量不错但有时会输出不稳定的格式为了防止解析失败我要求模型必须按Markdown格式的固定模板输出代码里再做一个正则提取。千问则在不同地域节点的接口域名有区别建议把请求超时时间设置为15秒并开启重试机制。7. 几句实在话这个项目做下来最大的感受是目标检测模型只是整条链路里的一环真正决定系统好不好用的反而是接口设计、异步任务调度和大模型Prompt这些外围工程细节。YOLOv8、v10、v11、v12这些版本差别没有想象中大先选一个稳定的版本把流程跑通再根据精度和延迟数据去换模型是成本最低的路线。如果你也准备做类似的安全锥或小目标检测系统建议一开始就把数据集标准化做好把大模型设计成可降级的模块把视频检测和前端联调的时间预留充分。这套思路不仅适用于安全锥换生产帽、安全绳、车辆违停等目标框架完全可以复用。