ARTICLE DETAIL

资讯详情

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

计算机视觉在轨道交通的落地实践:从巡检到客流的场景选型与部署

计算机视觉在轨道交通的落地实践:从巡检到客流的场景选型与部署 简介这份文档面向轨道交通智能化方向的研究人员、工程技术人员及高校相关专业师生系统梳理计算机视觉技术在轨道交通领域的应用路径与落地方法。内容从技术基础讲起涵盖图像采集与数字化、图像增强与复原、图像分割与特征提取以及传统图像处理、深度学习和目标检测识别等常用算法并介绍视觉系统的硬件组成与软件架构。在此基础上文档重点展开三大应用场景信号系统中的信号灯状态识别、信号机故障检测、列车定位与轨迹跟踪、轨道占用与闭塞状态监测线路维护中的轨距水平检测、轨道变形与表面缺陷识别、道岔转换状态与关键部件缺陷检测、桥梁隧道结构健康监测以及运营管理中的客流量实时监测与分析等。资源包为1个docx文档约170KB目录层级完整、章节编号清晰便于按模块检索与引用。已有31人学习适合作为课题调研、方案设计或论文写作的参考材料。1. 计算机视觉在轨道交通的落地切口从巡检到客流哪些场景真能省人凌晨一点的地铁车辆段巡检工打着手电筒沿着车底走一列车几百个紧固件、几十米线缆靠人眼扫一遍要四十分钟漏检几乎是必然。这就是计算机视觉在轨道交通领域最真实的落地切口——不是造一个炫酷的 AI 大屏而是把「人眼盯不过来」的重复性检查交给摄像头加模型。轨道交通是个特殊行业封闭场景、固定机位、光照可控、目标类别少但安全等级极高这几点决定了它比开放道路的自动驾驶更容易做出可用效果。适合读这篇的人有三类做工业质检想转轨交的算法工程师、地铁/铁路系统里负责智能运维的技术负责人、以及拿计算机视觉大作业选题卡壳的学生。下面按「场景选型 → 数据与标注 → 模型训练 → 部署排错」的路径把这条线讲透。2. 轨道交通视觉任务的场景拆解与选型逻辑2.1 四类主流任务巡检、客流、异物、行为轨道交通里能落地的视觉任务基本逃不出这四类每类的技术难点完全不同选错方向后面全是坑。车辆/隧道巡检是当前需求最刚性的。车底走行部、受电弓、接触网、隧道管片裂缝这些目标的特点是「缺陷样本极少、正常样本海量」属于典型的小样本异常检测。常见做法是用目标检测框出部件位置再对部件做分类或分割判断缺陷。受电弓碳滑板磨耗检测是经典案例用语义分割把碳滑板区域抠出来再算磨耗量。客流分析包括进出站人数统计、站台拥挤度、扶梯逆行检测。这类任务目标密集、遮挡严重用检测加跟踪ByteTrack、OC-SORT 这类比单纯检测更稳。站台门区域的客流密度估计用密度图回归比逐人检测更抗遮挡。异物侵限检测是安全红线轨道上有无遗落物、有无人员闯入。难点在于「异物」定义开放你没法穷举所有异物类别所以主流方案是背景建模加变化检测或者用无监督异常检测而不是训一个「异物分类器」。行为识别包括乘客摔倒、翻越闸机、遗留物检测。时序信息是关键单帧检测会误报需要 3D 卷积或时序 Transformer 建模动作。选型的第一原则先问这个场景漏检的代价是什么。巡检漏检一个螺栓可能出人命那就必须上高召回模型加人工复核客流统计差几个人无所谓可以牺牲精度换速度。这个判断决定了后面所有参数。2.2 为什么轨交场景比开放道路更适合视觉落地很多人做计算机视觉入门时被 cs231n 那套开放场景带偏觉得视觉就是处理复杂多变的环境。轨交恰恰相反它的「受控」是最大优势。第一机位固定。摄像头装在车顶、站台、隧道壁上位置和角度长期不变这意味着你可以用背景建模、可以用固定的 ROI 裁剪省掉大量检测算力。第二光照可控。隧道内补光、站台照明都是工程化的不像室外有逆光、雨雾、昼夜剧变。第三目标类别收敛。轨交关心的目标就那么几十类不需要 ImageNet 那种千类泛化能力。这三点合起来意味着轨交视觉项目可以用更小的模型、更少的数据达到可用精度。我见过用 YOLOv5s 在自建 3000 张数据集上把受电弓检测做到 0.98 mAP 的案例这在开放场景几乎不可能。所以别一上来就追大模型先把场景优势吃干净。2.3 硬件与算力选型边缘盒子还是中心服务器轨交现场的网络条件往往很差隧道里没信号把视频流传回中心不现实。所以主流架构是边缘推理 中心汇总。边缘侧一般用 Jetson 系列Orin NX、Xavier NX或者国产的瑞芯微 RK3588、寒武纪 MLU 系列。选型看三点算力TOPS、功耗轨交设备舱散热有限、以及是否支持你要用的推理框架TensorRT、ONNX Runtime、RKNN。硬件典型算力适用任务注意点Jetson Orin NX100 TOPS多路检测分割功耗 25W需散热设计Jetson Xavier NX21 TOPS单路检测已逐步停产慎选新项目RK35886 TOPS NPU轻量检测需转 RKNN算子支持有限中心服务器 T4/A1065-250 TOPS离线复核、训练不用于实时边缘选边缘盒子的血泪经验别只看标称算力要看你的模型在它上面的实测帧率。厂商标的 TOPS 是理论峰值实际跑你的模型可能只有三分之一。买之前一定要拿自己的模型去实测。3. 数据采集与标注轨交视觉项目最容易翻车的一环3.1 数据采集的现场约束与采集脚本轨交现场采集数据不是拿个手机就能拍。车辆段、隧道、站台都有作业窗口和安全规定通常要申请天窗点夜间停运后的作业时间。采集时要注意同一部件在不同光照、不同角度、不同磨耗状态下都要覆盖否则模型只认一种状态。如果现场采集受限可以用仿真数据补充。但要注意仿真到真实的域差异仿真图训练的模型直接上真实场景往往掉点严重需要做域适应或者用真实数据微调。下面是一个从视频抽帧并去重的采集脚本现场录完视频后用它快速建初始数据集import cv2 import os import numpy as np from skimage.metrics import structural_similarity as ssim def extract_frames(video_path, out_dir, sample_interval30, ssim_thresh0.95): 从视频抽帧用 SSIM 去重避免抽出大量相似帧 sample_interval: 每多少帧取一帧候选 ssim_thresh: 相似度高于此值则丢弃越小保留越多 os.makedirs(out_dir, exist_okTrue) cap cv2.VideoCapture(video_path) last_kept None idx 0 saved 0 while True: ret, frame cap.read() if not ret: break if idx % sample_interval 0: gray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) gray cv2.resize(gray, (320, 180)) # 缩小加速 SSIM if last_kept is None: keep True else: score ssim(last_kept, gray) keep score ssim_thresh if keep: cv2.imwrite(os.path.join(out_dir, fframe_{idx:06d}.jpg), frame) last_kept gray saved 1 idx 1 cap.release() print(f共处理 {idx} 帧保存 {saved} 张) extract_frames(inspection.mp4, dataset/raw, sample_interval30, ssim_thresh0.95)逻辑说明sample_interval控制抽帧密度巡检视频一般 25-30fps每 30 帧取一张约等于每秒一张足够覆盖。ssim_thresh是去重阈值0.95 意味着两张图相似度超过 95% 就丢弃后一张避免连续静止画面产生大量冗余。这个参数要根据现场运动速度调摄像头移动快就调低到 0.9静止机位可以调到 0.98。3.2 标注规范轨交缺陷标注的四个约定标注质量直接决定模型上限。轨交缺陷标注有几个行业约定必须遵守第一缺陷边界要按物理边界标不按视觉边界。比如裂缝标注要标到裂缝实际延伸的端点不能因为光照暗看不清就少标一截。第二区分「缺陷」和「疑似缺陷」。轨交安全要求高很多模棱两可的样本要单独标一类让模型学会区分而不是硬塞进正常或缺陷。第三小目标要放大标。螺栓、销钉这类目标在原图上可能只有十几个像素标注时要在放大图上标保证框的精度。第四标注一致性靠规范文档加交叉复核。多人标注时先标 100 张做一致性校验IoU 低于 0.7 的说明规范没对齐要重新培训。用 LabelImg 或 CVAT 标注后导出格式要统一。YOLO 格式是class x_center y_center width height全部归一化到 0-1。转换脚本网上很多但要注意类别索引从 0 开始还是从 1 开始这个坑我踩过标完发现全错位。3.3 数据增强轨交场景该用哪些、不该用哪些数据增强不是越多越好轨交场景有它的特殊性。该用的亮度对比度扰动模拟隧道灯光变化、高斯噪声模拟低照度传感器噪声、小角度旋转±5度模拟安装误差、随机裁剪模拟 ROI 偏移。这些不改变目标的物理语义。慎用的大角度旋转、翻转。轨交部件有明确的方向性受电弓翻转过来就不是受电弓了水平翻转可能让模型学到错误的空间关系。马赛克增强Mosaic在小目标检测上有用但会让缺陷的上下文失真巡检任务要谨慎。不该用的颜色抖动幅度过大。缺陷的颜色往往是判断依据锈蚀是红褐色、油污是黑色把颜色抖没了模型就瞎了。import albumentations as A # 轨交巡检推荐的增强管线 train_transform A.Compose([ A.RandomBrightnessContrast(brightness_limit0.2, contrast_limit0.2, p0.5), A.GaussNoise(var_limit(10.0, 50.0), p0.3), A.Rotate(limit5, border_mode0, p0.5), A.RandomCrop(height512, width512, p0.5), A.HorizontalFlip(p0.0), # 轨交部件有方向性禁用翻转 ], bbox_paramsA.BboxParams(formatyolo, label_fields[class_labels]))参数说明brightness_limit和contrast_limit控制在 0.2 以内太大就失真了。GaussNoise的var_limit上限 50 是经验值再高会淹没小目标。Rotate的limit5是保守值对应摄像头安装的角度误差。HorizontalFlip直接设 p0.0 禁用这是轨交和通用检测最大的区别。4. 模型训练与调参从 YOLO 基线到轨交专用优化4.1 基线模型选择为什么轨交项目多用 YOLO 系轨交视觉项目对实时性要求高巡检车行进中检测、站台实时客流所以单阶段检测器是主流。YOLO 系列从 v5 到 v8、v11工程化程度高、部署工具链成熟是大多数项目的起点。选哪个版本我的建议新项目直接上 YOLOv8 或 v11因为它的 anchor-free 设计对小目标和密集目标更友好且 Ultralytics 的部署链路导出 ONNX、TensorRT最顺。如果现场只有老旧的 TensorRT 版本或者要兼容已有 v5 模型那就继续用 v5别为了追新重做整个部署链。分割任务用 YOLOv8-seg 或 Mask R-CNN。轨交的部件分割受电弓、绝缘子用 YOLOv8-seg 足够速度快。裂缝这种细长目标分割比检测更合适因为框会把大量背景框进去。4.2 训练配置轨交数据集的关键参数下面是一份 YOLOv8 的训练配置针对轨交巡检场景调过from ultralytics import YOLO model YOLO(yolov8s.pt) # 从预训练权重起步 results model.train( datarailway.yaml, # 数据集配置 epochs200, imgsz640, # 轨交小目标多可提到 960 batch16, lr00.01, # 初始学习率 lrf0.01, # 最终学习率系数 momentum0.937, weight_decay0.0005, warmup_epochs3, mosaic0.5, # 马赛克增强概率巡检任务调低 mixup0.0, # 禁用 mixup避免缺陷语义混淆 degrees5.0, # 旋转角度对应安装误差 fliplr0.0, # 禁用水平翻转 flipud0.0, # 禁用垂直翻转 patience30, # 早停耐心值 device0, workers8, )参数说明imgsz640是默认值但轨交小目标螺栓、销钉多建议提到 960 甚至 1280代价是显存和推理时间翻倍要权衡。mosaic0.5比默认的 1.0 低因为马赛克拼接会让缺陷的上下文失真。mixup0.0直接禁用缺陷检测里 mixup 会让正常和缺陷样本叠加产生语义混乱。fliplr和flipud都设 0理由前面讲过轨交部件有方向性。patience30是早停验证集 30 轮不提升就停避免过拟合。轨交数据集通常不大几千张过拟合是主要风险早停加权重衰减是标配。4.3 小样本与类别不平衡的处理轨交缺陷样本天然稀少正常样本一大堆这是最头疼的问题。几种处理方式过采样缺陷样本把缺陷图复制多份配合不同的增强。简单粗暴但有效注意别复制到过拟合。Focal Loss降低易分类样本的权重让模型聚焦难样本。YOLOv8 默认用的就是带 Focal 思想的分类损失但可以调cls损失权重。异常检测路线如果缺陷样本实在凑不够干脆不做有监督检测改用无监督异常检测PatchCore、PaDiM 这类。只用正常样本训练推理时偏离正常分布的就报警。轨交巡检里这条路越来越主流因为正常样本要多少有多少。合成缺陷用正常图加人工合成的缺陷贴图、纹理生成扩充缺陷样本。但合成缺陷和真实缺陷有域差要混着真实样本一起训。我一般会先试有监督如果缺陷样本少于 200 张直接转异常检测路线别硬撑。5. 部署与推理优化边缘盒子上的性能与精度平衡5.1 模型导出与量化ONNX 到 TensorRT 的完整链路训练完的 PyTorch 模型不能直接上边缘盒子要转成推理引擎。Jetson 上走 TensorRTRK3588 上走 RKNN。# 1. 导出 ONNX yolo export modelbest.pt formatonnx opset12 imgsz640 # 2. ONNX 转 TensorRT在 Jetson 上执行 /usr/src/tensorrt/bin/trtexec \ --onnxbest.onnx \ --saveEnginebest.engine \ --fp16 \ --workspace4096 \ --minShapesimages:1x3x640x640 \ --optShapesimages:1x3x640x640 \ --maxShapesimages:4x3x640x640参数说明--fp16开启半精度Jetson 上能提速约 2 倍精度损失通常小于 1%轨交检测可以接受。--workspace4096是 4GB 显存工作区Orin NX 上够用。--minShapes/optShapes/maxShapes定义动态 batchoptShapes是实际推理用的 batch设成 1 是单路实时设成 4 是多路并发。注意INT8 量化要谨慎。INT8 能再提速一倍但需要校准集且对小目标和低对比度缺陷的精度损失可能超过 5%。轨交安全场景我一般只用 FP16不上 INT8除非实测精度掉点可接受。5.2 推理服务封装多路视频流的处理框架边缘盒子上通常要同时处理 4-8 路摄像头需要一个调度框架。核心是「解码-推理-后处理」流水线并行别串行做。import cv2 import numpy as np import tensorrt as trt import pycuda.driver as cuda import threading from queue import Queue class InferWorker(threading.Thread): def __init__(self, engine_path, input_queue, result_queue): super().__init__() self.input_queue input_queue self.result_queue result_queue self.engine self._load_engine(engine_path) self.context self.engine.create_execution_context() def _load_engine(self, path): logger trt.Logger(trt.Logger.WARNING) with open(path, rb) as f, trt.Runtime(logger) as runtime: return runtime.deserialize_cuda_engine(f.read()) def preprocess(self, frame): # letterbox 到 640x640保持长宽比 h, w frame.shape[:2] scale 640 / max(h, w) nh, nw int(h * scale), int(w * scale) resized cv2.resize(frame, (nw, nh)) canvas np.full((640, 640, 3), 114, dtypenp.uint8) canvas[:nh, :nw] resized blob canvas[:, :, ::-1].transpose(2, 0, 1).astype(np.float32) / 255.0 return np.ascontiguousarray(blob[None]) def run(self): while True: frame self.input_queue.get() if frame is None: break blob self.preprocess(frame) # 推理 后处理NMS 等省略细节 outputs self._infer(blob) self.result_queue.put(outputs)逻辑说明每个 worker 线程独立持有一个 TensorRT context从输入队列取帧、预处理、推理、把结果丢进结果队列。主线程负责解码视频流和消费结果。这样解码和推理并行GPU 利用率能拉满。注意 TensorRT 的 context 不是线程安全的一个 context 只能一个线程用多路并发要建多个 context 或者用 CUDA stream 隔离。5.3 精度与速度的取舍轨交场景的实测经验边缘部署最大的矛盾是精度和速度。轨交场景的取舍原则巡检任务优先保精度。巡检车速度慢帧率要求不高5-10fps 够用可以把 imgsz 提到 960用 FP16牺牲速度换召回。漏检一个缺陷的代价远大于多跑几毫秒。客流任务优先保速度。站台客流要实时25fps 起步可以用小模型YOLOv8n 640 分辨率精度差几个百分点无所谓。异物检测走异常检测。不需要高帧率但要求零漏报用 PatchCore 这类方法推理慢点没关系可以隔帧检测。实测数据供参考Jetson Orin NX 上YOLOv8s FP16 640 分辨率单路约 60fps四路并发每路约 15fps。提到 960 分辨率单路约 30fps。这些数字随模型和实现变化务必自己实测。6. 避坑与排查轨交视觉项目里那些让人后悔的坑6.1 现场光照变化导致模型集体失效现象实验室验证 mAP 0.95上线后白天正常、夜间大量漏检或者隧道进出口段误报暴增。原因训练集的光照分布和现场不一致。实验室用的是均匀补光的图现场有逆光、有明暗交界、有车灯眩光。模型学到的是「特定光照下的缺陷」光照一变就失效。解决采集数据时必须覆盖全时段全光照白天、夜间、隧道内、隧道口都要采。训练时加强亮度对比度增强范围拉到 ±0.3。上线前做光照分层的验证集分别看白天和夜间的指标别只看总体 mAP。6.2 标注类别索引错位导致训练全错现象训练 loss 正常下降但推理时框的位置对、类别全错或者所有目标都预测成同一类。原因标注格式转换时类别索引错位。YOLO 格式要求类别从 0 开始但有些标注工具从 1 开始或者转换脚本里class_id没减 1。还有一种情况是data.yaml里的names顺序和标注文件里的索引对不上。解决转换后一定要可视化检查。写个脚本把标注框画回原图人眼确认类别和位置都对。这个检查花十分钟能省几天排查。import cv2 def visualize_yolo(img_path, label_path, names): img cv2.imread(img_path) h, w img.shape[:2] with open(label_path) as f: for line in f: cls, xc, yc, bw, bh map(float, line.split()) x1 int((xc - bw / 2) * w) y1 int((yc - bh / 2) * h) x2 int((xc bw / 2) * w) y2 int((yc bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, names[int(cls)], (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) cv2.imwrite(check.jpg, img) visualize_yolo(frame_000001.jpg, frame_000001.txt, [bolt, crack, oil])6.3 边缘盒子散热不足导致推理降频现象设备刚上电时帧率正常跑半小时后帧率腰斩或者频繁重启。原因轨交设备舱空间封闭散热差。Jetson 这类模块满载功耗 15-25W热量散不出去就触发温度墙自动降频保护。解决选型时留散热余量加装散热片和风扇。软件上可以限制功耗模式nvpmodel或者降低推理频率隔帧推理。实测时一定要连续跑 2 小时以上看帧率稳定性别只测冷启动的峰值。6.4 视频流解码成为瓶颈现象GPU 利用率只有 30%但帧率上不去CPU 某个核跑满。原因用 OpenCV 的cv2.VideoCapture软解码CPU 解码 1080p 多路视频扛不住。GPU 在等数据利用率自然低。解决用硬件解码。Jetson 上用nvdec通过 GStreamer 管线或者 DeepStream 框架。或者用PyNvVideoCodec这类库直接调 NVDEC。软解码换硬解码多路场景帧率能翻倍。6.5 模型更新后旧场景回归现象为了修某个新缺陷类型重新训练新类型检测好了但原来能检的旧类型开始漏检。原因新数据加入后数据分布偏移模型把容量分给了新类型旧类型被「遗忘」。这是持续学习里的灾难性遗忘。解决每次重训都要用全量数据别只用新增数据微调。建一个固定的回归测试集包含所有历史场景每次模型更新后跑一遍指标掉了就不上线。这个回归集是轨交项目的后悔药一定要建。7. 把轨交视觉做扎实的一个进阶习惯建自己的场景回归集前面反复提到回归测试集这里展开讲因为它是我做轨交项目几年下来觉得最值的一件事。轨交视觉项目的模型不是训一次就完事现场会不断冒出新情况新车型、新光照、新缺陷类型。每次迭代都要保证不退化靠的就是一个覆盖全场景的回归集。回归集的构建原则按场景维度分层不按数量堆。具体分这几层光照白天/夜间/隧道内/隧道口、天气晴/雨/雾如果是地面线路、车型不同型号的受电弓、转向架、缺陷类型每种缺陷至少 20 个样本、负样本容易误报的正常情况比如水渍、反光、阴影。每层都要有哪怕每层只有几十张。维护上我习惯用 DVC 或者 Git LFS 管理回归集版本每次模型迭代记录对应的回归指标。指标不只看总体 mAP要分层看某一层掉点超过 2% 就拦下来查原因。这套流程听起来麻烦但比上线后现场出问题再回滚要省事得多。还有一个具体技巧回归集里要放「对抗样本」。就是那些模型历史上误报过的图专门收集起来。这些图是模型的软肋每次训练都拿它们验证能有效防止同类误报复发。我一般会维护一个hard_negatives目录只增不减。最后说个习惯每次现场部署前我都会带一台笔记本到现场用现场的真实摄像头跑一遍模型看实时效果而不是只看离线指标。离线指标再好现场光照、角度、抖动一变可能就是另一回事。这个「现场跑一遍」的习惯帮我拦下过好几次差点上线的翻车模型。轨交这行安全冗余永远不嫌多宁可上线前多花两天验证也别指望上线后打补丁。希望帮到你。本文还有配套的精品资源点击获取
返回列表