ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

YOLO+SpringBoot安全锥检测系统全栈实战

YOLO+SpringBoot安全锥检测系统全栈实战 先交代一下背景。去年我参与一个道路施工安全管理平台时客户提了一个非常具体、听起来甚至有点“小题大做”的需求系统能不能自动识别现场摆放了多少个安全锥、有没有倒伏、收工后有没有漏在路面上。当时我第一反应是用YOLO做目标检测就行但真做下去才发现这只是整个链路里最简单的一环。后面的SpringBoot服务封装、前后端分离的web界面、大模型对检测结果的语义分析、数据集的整理与格式转换每一块都需要踩坑和取舍。这篇文章就是把我做这个“基于YOLOv8/YOLOv10/YOLOv11/YOLOv12与SpringBoot的安全锥检测系统”的完整思路、技术选型、实操步骤和踩坑记录整理出来。项目涉及四种YOLO版本的选择对比、SpringBoot后端与Python推理服务的对接、Qwen千问视觉模型与DeepSeek文本模型的智能分析分工以及一套可运行的前后端分离web交互界面同时也包含YOLO数据的标注与转换流程。无论你是想复现一个类似的工业检测系统还是刚接触YOLOSpringBoot这套企业级组合这篇文章都可以给你一个直接可参考的落地路径包括我不小心踩过的坑和你可能会踩的坑。1. 项目整体设计与技术选型思路1.1 安全锥检测到底在解决什么问题安全锥也叫锥形交通标、路锥在道路施工、临时交通管制、赛事安保、物流园区、停车场管理中无处不在。传统管理方式完全依赖人工巡检施工前要摆锥、施工中要检查锥有没有被车撞倒、收工后还要清点有没有遗漏。这个问题看起来小但真出事故就是大事尤其夜间或恶劣天气下漏在现场的安全锥对过往车辆是实实在在的隐患。从系统角度拆解需求可以分成三层第一层是“看见”也就是能准确识别出图片或视频帧里有没有安全锥以及锥的具体位置。这是目标检测模型的活对应YOLO系列。难点在于安全锥在画面里往往是小目标距离摄像头远的时候可能只有几十个像素而且道路场景里阳光直射、雨天反光、夜间低照度都会让模型误检漏检。第二层是“管理”识别出锥之后要落到业务流程里比如记录检测时间、保存现场图片、统计锥的数量变化、生成巡检报告。这一层是典型的Web系统功能需要稳定的后端服务和可操作的界面对应SpringBoot、MySQL、Vue这套组合。第三层是“理解”检测结果是一堆坐标框和置信度但人真正想知道的不是“第3个框置信度0.92”而是“现场锥桶摆放是否合规、有没有倒伏、整体风险怎么样”。这一层就需要大模型介入用千问做多模态视觉理解用DeepSeek做文本归纳和报告生成。我这个项目的定位就是把这三层全部打通做一个从图片上传到最终生成巡检报告的完整闭环系统而不是只训练一个模型就完事。1.2 技术栈选型为什么是YOLO系列加SpringBoot加大模型选型的时候其实纠结过很久主要是在“用什么做检测”和“怎么把检测能力变成产品”这两件事上。检测部分从小到大列过很多备选OpenCV传统图像处理、Faster R-CNN、YOLO系列、还有最新的DETR和RT-DETR。传统图像处理我直接排除安全锥在不同光线、不同角度下颜色和形状变化太大阈值调参根本守不住。Faster R-CNN精度不错但推理速度慢部署也重做实时性要求高的现场巡检不合适。YOLO系列是目前平衡最好的方案单阶段架构推理快、训练生态成熟、V8之后有统一的ultralytics仓库标注格式、训练命令、模型导出都是开箱即用。这也是我把四个版本都纳入项目的原因。后端为什么选SpringBoot而不是继续用Python全家桶有两个很现实的原因。第一企业级项目的运维习惯是Java那一套MySQL、Redis、Nginx、Linux服务器的组合运维团队更熟出了问题好交接。第二Python推理服务和Java业务服务需要清晰边界SpringBoot可以很好地承担业务编排、用户权限、数据存储、接口暴露这些职责而Python只专注做模型推理和大模型调用职责单一后续模型更新只需要重启Python服务不会影响整个业务系统。大模型方面之所以同时用千问和DeepSeek是因为它们分工不同。千问系列有多模态模型Qwen2-VL可以直接接收图片输入适合对现场图片做视觉理解比如判断锥桶是否倒伏、位置是否异常。DeepSeek在中文文本生成和结构化输出上表现很稳定适合把检测记录整理成巡检报告、回答用户的自然语言查询。两者配合视觉能力解决“看图说话”文本能力解决“把话说清楚”。1.3 系统架构与模块划分整个系统采用前后端分离架构按功能划分为五个模块前端展示层基于Vue3 Element Plus构建包含图片上传、检测结果展示、历史记录查询、数据统计大屏等页面。前端只通过HTTP/WebSocket接口访问后端不直接接触AI模型。后端业务层SpringBoot应用负责用户认证、图片文件管理、检测任务调度、检测记录持久化、大模型分析结果处理和WebSocket推送。对外提供RESTful API和WebSocket端点。AI推理层一个独立的Python服务我用的FastAPI加载训练好的YOLO权重接收图片后返回检测框、类别、置信度列表。SpringBoot通过HTTP调用这个服务。大模型分析层在推理返回结果后将图片和结构化检测信息发送给Qwen2-VL和DeepSeek API获得语义分析文本和结构化报告。数据存储层MySQL存检测记录和用户数据Redis做缓存和任务队列本地文件系统或OSS存原始图片。这种分层的好处非常明显。前后端分离意味着前端和后端可以并行开发我甚至可以先用Mock数据把界面调通再逐步接入真实检测服务。AI推理层独立出来意味着模型训练、升级完全不影响业务代码可以说换权重就换权重。大模型分析层也做成了可插拔想换其它大模型随时可以换接口。2. YOLO模型版本对比与数据准备2.1 YOLOv8/YOLOv10/YOLOv11/YOLOv12关键差异与选型建议这个项目标题里放了四个YOLO版本并不是为了凑数而是确实需要做对比选型因为每个版本适合的场景完全不同。我逐个梳理一下它们的区别。版本核心改进点优势适用场景YOLOv8Anchor-Free检测头C2f结构ultralytics统一框架生态最成熟、文档最多、训练部署资料丰富稳定性最好生产环境首选、新手入门、快速落地YOLOv10One-to-One匹配机制去掉了NMS后处理推理管线更简洁端到端设计减少了后处理耗时速度更快对速度有硬性要求、边缘设备部署YOLOv11改进C3k2模块、引入C2PSA注意力机制优化了训练策略在相近参数量下精度比V8更高FLOPs控制得比较好精度优先、需要处理小目标YOLOv12引入区域注意力机制有跨层特征融合优化能更好捕捉长距离依赖复杂背景下的目标定位更准复杂道路场景、光照变化大、遮挡多的情况在安全锥这个具体场景里我的实测经验是如果你要上线一套系统且团队对YOLO不是特别熟优先选YOLOv8s因为遇到问题随便搜一下就有答案坑基本都被前人踩平了。如果检测实时性要求高后端推理节点配置一般用YOLOv10n或YOLOv10s可以省掉NMS这一步的耗时。如果检测距离远、安全锥在画面上很小YOLOv11的C3k2和注意力机制表现更好。YOLOv12在强光、阴影、锥桶被部分遮挡时误检率会低一些但训练和推理对算力的要求也更高部署前要先确认硬件扛得住。我最终项目里同时保留了四个版本的训练配置和模型导出脚本通过一个配置文件切换。线上主推YOLOv11s备选YOLOv8s作为降级方案这样既保证了精度上限也保证了容灾能力。2.2 安全锥数据集的采集、标注与增强安全锥不是一个冷门类别网上能找到一些公开数据集但大多数是欧洲、美国的锥桶样式颜色、反光条设计和我们常见的橙色工程锥差别不小。为了保证实际场景准确率我选择自建数据集采集和标注花了大概一周时间。采集阶段我用了三个来源手机在施工路段实拍、行车记录仪截图、网络公开图片注意使用有授权许可的图片。实拍的时候要刻意覆盖不同时间段白天顺光、白天逆光、傍晚、夜间开灯照明。天气方面尽量覆盖晴天、阴天、雨天雨天的地面反光对检测影响很大必须纳入训练。角度上除了平视视角还要有俯拍无人机或高位摄像头、侧拍和近距离特写。标注阶段类别我分了三类normal_cone正常摆放的安全锥、fallen_cone倒伏的安全锥、light_cone带警示灯的安全锥。如果只分成一个大类模型虽然能检测到锥但无法区分是否倒伏后续的智能分析就少了一个关键信息。每张图我会标注得比较细倒伏的锥、半遮挡的锥、只露出底座的锥都单独标出来让模型学的是“任何状态下的锥”而不是“完整的锥”。总标注量是2400多张通过增强扩到6000多张。数据增强用ultralytics自带的增强参数就够了我配置了水平翻转、随机旋转、HSV色域扰动、随机缩放和马赛克增强。特别要注意的是hsv_h和hsv_s的调节安全锥是醒目的橙色过强的色域变化会把颜色特征污染掉我实测把hsv_h控制在0.015以内效果最好太大会让橙色锥在增强后变成红色甚至紫色反而降低泛化能力。YOLO数据集格式是每个标注txt和图片同名每行五个数值class_id center_x center_y width height坐标均为归一化值除以图片宽高。比如一张宽1920、高1080的图片中一个安全锥的左上角坐标是(400, 300)、右下角是(520, 600)那么标注行就是0 0.23958 0.41667 0.06250 0.27778这个格式很简单但也是后面数据转换的核心目标。2.3 从KITTI等公开标注格式转换为YOLO格式很多开发者会先用公开数据集做预训练再在自己数据集上微调这时候就必然会遇到格式转换问题。KITTI标注是每行一个目标格式为类型 截断率 遮挡 角度 xmin ymin xmax ymax ...需要把xmin/ymin/xmax/ymax转换为YOLO的归一化中心坐标和宽高。转换公式如下center_x (xmin xmax) / 2 / image_width center_y (ymin ymax) / 2 / image_height box_width (xmax - xmin) / image_width box_height (ymax - ymin) / image_height我用Python写了一个批量转换脚本处理KITTI格式的txt文件并生成YOLO格式的txtimport os def kitti_to_yolo(label_file, img_width, img_height): yolo_lines [] class_map {Car: 0, Pedestrian: 1, Truck: 2} # 按需定义类别映射 with open(label_file, r) as f: for line in f: parts line.strip().split() if len(parts) 8: continue cls_name parts[0] if cls_name not in class_map: continue xmin float(parts[4]) ymin float(parts[5]) xmax float(parts[6]) ymax float(parts[7]) # 边界截断防止坐标超出图片范围 xmin max(0, min(xmin, img_width - 1)) xmax max(0, min(xmax, img_width - 1)) ymin max(0, min(ymin, img_height - 1)) ymax max(0, min(ymax, img_height - 1)) if xmax xmin or ymax ymin: continue center_x (xmin xmax) / 2 / img_width center_y (ymin ymax) / 2 / img_height box_w (xmax - xmin) / img_width box_h (ymax - ymin) / img_height yolo_lines.append(f{class_map[cls_name]} {center_x:.6f} {center_y:.6f} {box_w:.6f} {box_h:.6f}) return yolo_lines有一个特别容易踩的坑是图片的EXIF信息。手机拍摄的照片默认带旋转信息直接读取像素会得到旋转前的宽高导致坐标对不上。我处理的时候统一用OpenCV读取图片后重新保存一遍OpenCV会去掉EXIF旋转信息同时也保证图片被解码为正常的RGB/BGR顺序然后再读取标注做转换否则训练出来的模型会出现“锥桶是歪的”这种奇葩错误。2.4 训练流程、损失函数与评估指标数据准备好之后训练阶段要重点盯几个地方。首先是data.yaml配置path: ./datasets/cone_data train: images/train val: images/val names: 0: normal_cone 1: fallen_cone 2: light_cone训练命令用ultralytics的统一入口yolo detect train datacone.yaml modelyolov8s.pt epochs100 imgsz640 batch16 device0如果想训练YOLOv11只需把model参数换成yolov11s.ptultralytics仓库会根据名称自动下载预训练权重无需改其它代码。这个统一接口是YOLO系列生态最大的优势。YOLO系列损失函数主要由三部分组成分类损失用BCEBinary Cross Entropy边界框回归损失在V8及之后使用CIoU和DFLDistribution Focal Loss的组合V10虽然去掉了NMS但训练时的损失函数主体逻辑基本一致只是匹配策略改成了One-to-One。对普通工程开发者来说不需要深入改损失函数但要明白一个概念mAP50反映的是整体检测精度而mAP50-95更严格强调框的贴合程度。安全锥检测我主要看mAP50因为业务上更关心“有没有检测到”而不是“框是不是完全贴合”当然要追求好的效果mAP50-95也尽量往0.7以上走。训练过程中我会实时盯PPrecision和RRecall。安全锥这个场景中漏检比误检更致命所以我会刻意把conf_threshold调低到0.20.25宁可多框几个疑似目标也不能让倒伏的锥漏掉后续大模型分析时再去过滤噪声。硬件方面必须提醒一句训练一定要用NVIDIA显卡显存建议8GB以上。AMD RX 580这类显卡推理还能凑合但训练效率非常低因为主流深度学习框架对ROCm的支持远不如CUDA成熟折腾半天可能连依赖都装不完。如果手头只有AMD显卡建议只用CPU做小数据集快速验证正式训练还是用云GPU或者换NVIDIA卡这不是品牌偏好是生态差距。3. SpringBoot后端与前端协作实现3.1 后端整体接口设计与数据模型SpringBoot作为业务中台接口设计要简洁清晰我按功能拆成四组上传与检测POST /api/upload接收图片保存后返回图片IDGET /api/detect/{imageId}触发检测同步等待Python推理服务返回异步保存检测结果。记录查询GET /api/records分页查询历史检测记录支持按时间、按检测结果类型筛选GET /api/records/{id}获取单条记录的完整信息和AI分析结果。统计报表GET /api/stats/overview返回检测总数、安全锥总数、倒伏率、趋势数据供前端大屏展示。实时推送/ws/detect是WebSocket端点检测完成后后端主动推送结果前端收到后自动更新。检测记录表设计也很关键字段类型说明idbigint主键image_urlvarchar原始图片地址result_image_urlvarchar标注了检测框的图片地址yolo_resultjsonYOLO返回的检测框原始结果ai_summarytext千问生成的视觉分析文本ai_reporttextDeepSeek生成的巡检报告statustinyint检测状态0处理中、1成功、2失败creator_idbigint操作用户create_timedatetime创建时间注意yolo_result和ai_summary一定要分开存因为大模型可能调用失败或超时如果混在一起检测记录会跟着不可用主流程就断了。这里有个后端细节SpringBoot接收多部分文件时默认最大请求体只有1MB很多现场图片随便一拍就三四MB不调配置就会报错。所以要提前在application.yml中调大限制spring: servlet: multipart: max-file-size: 20MB max-request-size: 50MB同时Nginx层也要同步修改client_max_body_size否则前端上传大图时会在Nginx就被拦下连SpringBoot都到不了。3.2 Python推理服务封装与通信方式SpringBoot本身不直接加载YOLO模型原因很简单Java环境跑PyTorch模型非常别扭依赖大、调试难、性能也不理想。更合理的做法是把Python推理单独封装成一个微服务我用FastAPI实现因为相比Flask它天然支持异步和类型校验性能也更好。核心检测接口代码如下from fastapi import FastAPI, File, UploadFile import cv2 import numpy as np from ultralytics import YOLO app FastAPI() model YOLO(best.pt) app.post(/detect) async def detect_image(file: UploadFile File(...)): image_bytes await file.read() image cv2.imdecode(np.frombuffer(image_bytes, np.uint8), cv2.IMREAD_COLOR) results model.predict(image, conf0.2, imgsz640) boxes [] for r in results: for box in r.boxes: x1, y1, x2, y2 box.xyxy[0].tolist() conf float(box.conf[0]) cls int(box.cls[0]) boxes.append({ x1: x1, y1: y1, x2: x2, y2: y2, confidence: round(conf, 4), class_id: cls }) annotated_frame results[0].plot() _, encoded_img cv2.imencode(.jpg, annotated_frame) result_image_base64 base64.b64encode(encoded_img).decode(utf-8) return {boxes: boxes, result_image: result_image_base64}启动的时候建议用uvicorn detect_service:app --host 0.0.0.0 --port 8000 --workers 2每个worker会加载一份模型到内存。这里有个取舍workers开太少并发上不去开太多显存或内存会爆。我实践下来在8GB显存显卡上跑YOLOv11s2个worker比较稳妥单GPU场景跑推理时不用再叠加训练任务。SpringBoot调用这个服务的代码使用RestTemplate或WebClient因为推理可能耗时几秒接口超时时间要设置为30秒以上不能使用默认的5秒超时。通信格式直接用JSON虽然比gRPC慢一点但胜在调试方便配合Postman可以独立测试Python服务不用经过SpringBoot。3.3 WebSocket实时推送与前后端交互检测流程是异步的前端点击“开始检测”后SpringBoot转发请求给Python服务推理需要13秒不可能让前端傻等HTTP响应。这里我用WebSocket做主动推送流程是前端上传图片成功后建立WebSocket连接并携带用户ID。后端收到检测完成事件后通过SimpMessagingTemplate向该用户频道推送检测结果。前端监听到消息后刷新页面上的检测结果区域不需要重新加载整个页面。SpringBoot端配置WebSocket支持核心是继承WebSocketHandler或者用Spring的STOMP协议。我为了省事直接用原生WebSocket ServerEndpoint但更推荐用Spring的STOMP方案因为自带心跳检测和断线重连机制移动端网络不稳定时不容易掉线。前后端分离模式下跨域配置是必踩的坑。开发环境前端跑在localhost:5173后端跑在localhost:8080端口不同必定跨域。我在后端加一个CorsFilter允许前端域名访问生产环境下前端和后端通过Nginx同域反代就不需要跨域了所以开发和生产要拆两套配置。3.4 Web交互界面的设计与实现要点前端我选择Vue3 Vite Element Plus ECharts这套组合在后台管理类项目中非常主流组件全、社区资料多、招人容易。页面规划了三块。检测工作台是核心页面左侧是图片上传区域支持拖拽上传和本地上传预览。上传后系统自动调用检测接口右侧实时显示标注后的图片下方表格罗列每个检测框的位置和置信度。检测完成后再往下是AI分析区域展示千问生成的现场描述和DeepSeek生成的建议。整个页面用卡片式布局状态流转通过Loading控件和按钮禁用态体现避免用户重复点击。历史记录页做的是表格筛选器时间范围、检测结果类型、关键词搜索都支持。点击某条记录可以进入详情弹窗弹窗里是原始图、标注图、检测框数据、AI分析文本的四栏布局。这个页面看似简单但在真正的巡检流程里用处很大管理者需要回溯“昨天下午这个路段安全锥情况到底怎么样”。统计大屏页用的是ECharts核心图表包括每天检测数量柱状图、安全锥倒伏率趋势折线图、不同类型锥桶占比饼图、最近7天报警次数列表。数据从/api/stats/overview接口拉取。大屏页要注意图表配色和单位统一倒伏率要显示百分比并保留一位小数报警次数要按日期排序否则前端看着乱业务方会不认账。我开发时是先做了完整的页面和Mock接口再逐步把Mock替换成真实后端。这样前后端可以并行开工后端不用等前端前端也不用等模型训练完。这套协作方式在团队开发中也值得推广避免互相卡进度。4. 千问DeepSeek大模型智能分析模块4.1 大模型在这个系统里到底承担什么角色YOLO的输出是结构化的数值框坐标、类别、置信度。这对系统来说是“可用信息”但对终端用户来说不够直观。一个施工安全员不会关心置信度是0.91还是0.88他想知道的是“现在现场倒了几只锥”“有没有锥滚到行车道上”。把检测结果翻译成人话这就是大模型的活。所以大模型和YOLO是互补关系YOLO负责“看得准”大模型负责“说得懂”。两者结合后系统能回答三类问题现状描述图片里检测到多少个锥其中几个倒伏分布如何。风险判断是否有锥桶靠近行车道、是否有锥桶倒伏且长时间未恢复。报告生成一键生成某时间段的巡检报告包含统计数据、问题汇总和改进建议。4.2 千问多模态视觉分析的接入与提示词设计千问系列我用的是Qwen2-VL它能直接输入图片和文本输出自然语言分析。在实际系统中我选择把YOLO标注后的图片传给千问因为标注框已经画在图上视觉模型能直观看到每个锥桶的位置和状态减少歧义。调用方式我用的是DashScope提供的OpenAI兼容接口方便和现有代码统一。核心逻辑是图片转base64然后拼一个精心设计的prompt。Python服务端调用示例import base64 import requests import json def call_qwen_vl(image_path, detect_summary): with open(image_path, rb) as f: image_base64 base64.b64encode(f.read()).decode(utf-8) prompt f 你是一位道路施工安全巡检专家。请根据图片和分析数据描述现场情况 1. 图片中检测到多少个安全锥其中正常摆放、倒伏、带灯各多少。 2. 安全锥是否影响交通通行是否有明显安全隐患。 3. 用简洁中文总结控制在150字以内。 检测数据{json.dumps(detect_summary, ensure_asciiFalse)} response requests.post( https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions, headers{Authorization: fBearer {API_KEY}}, json{ model: qwen-vl-plus, messages: [ {role: user, content: [ {type: image_url, image_url: {url: fdata:image/jpeg;base64,{image_base64}}}, {type: text, text: prompt} ]} ] }, timeout30 ) return response.json()[choices][0][message][content]提示词设计是第一要务。我一开始用“请描述图片内容”这种开放式prompt千问会把反光条、地面纹理、远处车辆都讲一遍但业务需要的是安全锥相关细节。后来改成结构化prompt要求它逐项回答数量、状态、安全风险输出质量立刻上来了。注意要求它限制字数不限制的话大模型容易啰嗦后续展示和存储都不方便。还有一个细节传给大模型的图片最好压缩到长边不超过1024像素。原始照片动辄4000多像素base64编码后可能有十几MBAPI传输慢、费用也高。我用OpenCV先缩放到1024以内再base64视觉分析结果几乎不受影响但接口响应时间从8秒降到了2秒。4.3 DeepSeek接入与文本报告生成DeepSeek在这个项目里负责的是纯文本任务把历史检测记录归纳成巡检报告或者回答用户用自然语言发起的数据查询。相比千问DeepSeek的上下文理解能力和中文组织能力更强做文本类任务更合适。接入方式也走OpenAI兼容接口我用的是deepseek-chat模型。核心设计是让DeepSeek从数据库中的检测记录生成结构化报告并强制它输出JSON方便前端直接解析。调用示例def generate_report_with_deepseek(records): system_prompt 你是道路施工安全管理助理。请根据检测记录生成结构化巡检报告。严格按照JSON格式输出字段包括total_cones, fallen_cones, risk_level, suggestions。 user_content 以下是最近7天的检测记录汇总 json.dumps(records, ensure_asciiFalse) response requests.post( https://api.deepseek.com/v1/chat/completions, headers{Authorization: fBearer {DEEPSEEK_API_KEY}}, json{ model: deepseek-chat, messages: [ {role: system, content: system_prompt}, {role: user, content: user_content} ], temperature: 0.3, response_format: {type: json_object} }, timeout30 ) return response.json()[choices][0][message][content]temperature设置非常关键报告生成场景我控制在0.2到0.3之间太低显得机械太高会开始“发挥想象力”编造不存在的锥桶数量。另外要明确要求JSON格式DeepSeek虽然聪明但偶尔也会输出带解释文字的JSON我在后端解析时做了容错处理先尝试json.loads如果失败就删除注释行后再解析再失败就手动截取{到最后一个}之间的子串。这个正则提取方案看起来粗暴实际使用中成功率极高。4.4 成本控制、缓存与降级策略接大模型API最怕什么怕它贵、怕它慢、怕它不稳定。我在设计时做了三层防护。第一层是调用时机控制。不是每次YOLO检测都调用大模型只在用户主动点击“智能分析”时才触发。自动分析只针对检测结果异常比如发现有倒伏锥的记录这样把API调用量压到很低。第二层是结果缓存。同一个图片上传两次检测结果和大模型分析都是一样的没必要重复花钱。我用图片文件的MD5作为缓存keyRedis里存分析结果有效期设为一周。头像、实拍施工照片这类重复率不高但在测试阶段非常有用避免反复消耗API额度。第三层是失败降级。大模型接口超时或返回异常时系统会自动降级为只展示YOLO结构化检测结果并提示“AI分析暂时不可用”。主业务不阻断这是上线前就必须做好的兜底。实际线上运营中DeepSeek和千问都有过不稳定的时候如果没有降级策略整个AI分析区域就是一片空白体验很差。5. 部署实践与常见问题排查5.1 前后端分离项目的完整部署流程部署架构分四层Nginx负责前端静态资源托管和反向代理SpringBoot jar包运行在Java环境上Python推理服务独立跑在8000端口MySQL和Redis作为基础设施。部署步骤我梳理成清单方便照抄前端项目执行npm run build生成的dist目录拷贝到服务器Nginx的html目录下。配置Nginxlocation /指向前端静态文件location /api/反向代理到SpringBoot的8080端口同时设置client_max_body_size 20m。SpringBoot使用mvn package打包服务器执行nohup java -jar xx.jar --spring.profiles.activeprod app.log 21 启动。Python推理服务使用uvicorn启动建议用systemd管理方便设置开机自启和崩溃重启。MySQL建库建表Redis确保密码配置正确SpringBoot连接串和Python服务地址写死在prod配置文件里。启动顺序很关键先MySQL和Redis再启动Python推理服务确认/detect接口能通最后启动SpringBoot最后再把Nginx流量切过去。我踩过一次坑Python服务还没就绪就启动SpringBoot导致SpringBoot启动时健康检查失败整个应用直接退出。5.2 安全问题与性能优化这个系统带Web界面不能只考虑功能安全也要过一遍接口认证SpringBoot用JWT做登录鉴权除登录接口外其它接口都拦截校验Token。WebSocket连接也要带Token在握手阶段校验不能让任何人随便建连。文件上传校验只允许jpeg/png/webp格式同时限制文件大小防止恶意上传超大文件拖垮服务。大模型Prompt注入这个容易被忽略用户输入的文本会拼进Prompt给DeepSeek如果用户输入“忽略之前的指令”之类的话可能诱导模型输出意外内容。我在后端对用户输入做了长度限制和关键词过滤同时对大模型输出不做直接HTML渲染而是转成纯文本或JSON再交给前端避免XSS问题。检测结果的越权访问查询记录接口必须校验当前用户是否拥有该记录的访问权限不能只靠前端隐藏按钮后端要做二次校验。性能优化方面YOLO推理是最大瓶颈。除了模型选型还可以在SpringBoot层做并发控制同时在Python推理服务里用进程池管理模型副本避免每来一个请求都重新加载权重。实测中YOLOv11s在单张NVIDIA T4上推理一张640x640图片大约200ms加上网络传输和SpringBoot处理整体端到端延迟在700ms左右完全够用。5.3 常见问题速查表做这类集成项目问题基本集中在环境、传输和模型三块。我把实际踩过的坑整理成了速查表问题现象原因解决办法上传图片返回413Nginx或SpringBoot请求体限制太小调大client_max_body_size和multipart.max-file-sizeSpringBoot调用Python服务超时HTTP客户端默认超时时间过短设置连接超时5秒读取超时30秒以上检测结果中文乱码JSON传输编码问题请求头固定Content-Type: application/json; charsetutf-8YOLO推理结果为空安全锥太小置信度被过滤降低conf到0.2或把imgsz提到960前后端联调跨域报错端口不同导致CORS未配置开发环境配置CorsFilter生产用Nginx同域反代WebSocket频繁断开缺少心跳机制前端每30秒发送心跳后端30秒无消息主动断开并重连DeepSeek返回非JSON文本模型偶尔输出解释性文字正则提取JSON块或设置response_format为json_object训练时显存OOMbatch占用过高调小batch到8或4同时降低imgsz还有一个我印象很深的问题YOLO标注数据集的类别ID和模型训练时不一致导致在线推理时类别全乱了。这个排查了很久才发现是数据配置里类别顺序写错。强烈建议给每个类别起一个可读性强的名字并在训练后写一个简单的类别映射自检脚本打印训练集和推理用的类别ID做一个死锁式的强校验。5.4 踩坑心得与改进空间这套系统做完我最深的体会是真正难的不是写好一个YOLO模型而是把模型嵌入到一套完整业务系统里还要保证稳定可运维。前端、后端、Python服务、大模型API每个环节都有各自的坑任何一个地方掉链子整个系统体验都会崩。几个值得改进的方向现在是图片上传检测下一步可以接RTSP摄像头做视频流实时检测YOLO推理放到独立GPU服务器上通过消息队列做异步解耦。智能分析部分也可以做定时巡检每天固定时间自动拉取当天的检测数据让DeepSeek生成日报推送到企业微信或钉钉。数据层面可以收集更多极端天气下的图片持续迭代模型精度。最后再分享一个小经验训练YOLO模型时一定要在训练前拿20张真实现场图做快速验证而不是直接训练完就上线。模型过拟合训练集这回事表现往往就是“训练集mAP很高现场图上一塌糊涂”。快速验证能帮你提前发现风格差异、光照差异、标注错误这些问题省下重训的时间和算力。这个习惯我后来用到所有目标检测项目里几乎每次都救了我。
返回列表