
铁路基础设施检测这几年越来越多人往深度学习上靠但真正能把模型稳定跑到现场的其实没想象中那么多。尤其是像隧道仰坡排水沟这种拍摄环境差、目标小、病害类型又杂的场景从数据到训练再到部署每一步都有不少坑。这篇内容我打算基于一个实际做过的项目——基于 Faster-RCNN 和 ResNet50 的铁路隧道仰坡排水沟病害识别——把整个思路、踩坑和落地细节完整拆开讲一遍。这套系统解决的问题很直接在隧道仰坡排水沟的巡检图像里自动检测出裂缝、破损、堵塞、渗水这几类典型病害替代人工看图找病害的环节把结果输出成结构化的检测报告方便工务段按图复核处理。适合正在做类似工业视觉检测项目的人参考尤其是刚接触目标检测、想把模型从实验室推到真实环境里的开发者。1. 项目背景与方案选型思路1.1 为什么隧道仰坡排水沟病害识别不能靠传统图像处理隧道仰坡排水沟表面看着是个很简单的混凝土结构但真要在图像里把病害找出来传统方法非常吃力。传统视觉方案最早都尝试过边缘检测加形态学处理比如Canny算子找裂缝轮廓再用阈值判断裂缝宽度。这套逻辑在干净的高速公路路面图像上还能勉强工作但放到隧道环境下就完全不行了。隧道仰坡的光线是灾难性的洞口段有强逆光洞内段基本靠辅助照明阴影和反光混在一起混凝土表面还有水渍、泥浆和青苔。用固定阈值去分割一天拍出来的图可能把水渍当裂缝、把青苔当剥落误检率根本压不住。另一个问题是病害形态本身就不是标准的几何形状。裂缝有横向、纵向、网状、龟裂排水沟破损可能是小块剥落也可能是整段压碎堵塞可能是淤泥、碎石或者杂物。传统特征工程要针对每一种形态设计特征人力成本极高换个隧道的光照条件特征又要重新调。所以项目一开始就把方向定在深度学习目标检测上。深度学习模型直接从标注数据里学病害的视觉特征对光照变化和形态变化的鲁棒性比手工特征强得多这也是当前工业视觉落地时最务实的选择。1.2 单阶段与两阶段检测器的选型权衡目标检测这一块主流路线无非是单阶段和两阶段之争。单阶段的代表是YOLO系列、SSD两阶段的代表就是Faster-RCNN系列。很多人上来就选YOLO理由是速度快、部署简单。但在这个项目里我选了Faster-RCNN原因很简单病害检测对误检的容忍度极低。排水沟病害有个特点它是固定基础设施的缺陷一旦漏检可能导致排水不畅、仰坡积水甚至影响隧道结构安全。而误检太多会导致现场复核工作量爆炸工务段根本不愿意用。Faster-RCNN走的是“先提候选区域、再做分类回归”的两步策略在精度上特别是小目标检测能力上比同期的单阶段模型有明显优势。排水沟病害很多是小目标比如一条细微裂缝可能只占图像面积的百分之几YOLO这类模型在小目标上的漏检率明显更高。当然两阶段模型的代价是推理速度慢。实测下来单张图在GPU上的推理时间大概在80到120毫秒跟YOLO的20到30毫秒没法比。但巡检车的图像采集节奏是“停车拍照”或者“低速连续拍摄”对实时性的要求并不极端。现场要的是“回去之后能把图里面的病害找全”而不是毫秒级响应。因此在精度优先、速度够用的场景下Faster-RCNN是更合理的选型。1.3 为什么要选ResNet50做特征提取骨干Faster-RCNN的特征提取骨干可以换最常用的是VGG16、ResNet系列。我选ResNet50而不是更深更宽的ResNet101也不是更浅的ResNet34或者MobileNet这个选择是基于对模型容量、训练难度和推理资源三者的平衡。ResNet50主要有两个好处。第一残差结构解决了深层网络退化问题。混凝土表面的裂缝和渗水痕迹在图像纹理上非常接近需要更深层的网络才能提取出足够区分度的语义特征。ResNet50的50层深度在病害特征表达上明显优于VGG16这类纯堆叠结构也比ResNet34这类浅层网络更充分。第二ResNet50是工业界的“万能油”结构。它在ImageNet上有成熟的预训练权重迁移学习效果稳定各种推理框架对它的优化都很成熟。ResNet101虽然理论上精度更高但参数量大了近一倍训练时间和显存消耗都显著增加在隧道病害这种类间差异不是特别大的任务里收益并不明显。MobileNet这类轻量网络倒是推理快但特征表达能力在细微裂缝检测上还是差一些。最终系统使用ResNet50作为Faster-RCNN的骨干网络配合FPN特征金字塔结构来增强小目标检测能力。FPN在后面的细节部分会展开讲这个组合在精度和速度上的表现最均衡。2. 数据准备与工程化处理2.1 图像采集与隧道环境特殊性模型效果的上限由数据决定这个说法在工业项目里尤其真实。排水沟病害识别系统的数据来源主要是两类设备一类是轨道巡检车上的高速工业相机一类是人工巡检用的手持拍摄设备。两类设备拍出来的图像分辨率和视角差异很大我处理的原始图像大多是1920x1080也有部分是4000x3000的高清大图。隧道环境的特殊性问题在数据采集阶段就必须充分考虑。第一个问题是光照极度不均匀。隧道口段会有大面积亮光洞内则是灯照区域和阴影区域混杂。这就要求图像采集阶段尽量使用均匀补光设备同时在标注阶段把光照变化作为重要考量。这个项目里使用的采集方案是两侧45度角补光加顶部柔光尽可能减少阴影对混凝土表面纹理的干扰。第二个问题是水渍反光。排水沟里常年有水表面反光会形成高亮区域跟渗水病害的视觉特征非常接近。单靠RGB图像很难区分这个项目在病害定义里把“渗水”和“水渍”做成了两类需要在标注时靠语义上下文判断比如是否有流水痕迹、是否有钙化析出物等。采集回来的原始图像不能直接扔给标注团队。第一轮要做的是清洗去掉严重模糊、过度曝光、完全黑暗的图去掉重复帧。巡检车连续拍摄时相邻帧重合度极高如果不抽帧训练集里全是高度相似的图片会让模型过拟合到特定场景。2.2 标注规范与病害类型定义标注是目标检测项目里最耗时也最容易出问题的环节。排水沟病害不像行人、车辆那样定义清晰它有很多边界模糊的情况。如果标注规范一开始不明确后面训练出来的模型一定会混乱。这个项目的病害类别最终定为四类裂缝、破损、堵塞、渗水。裂缝的定义是混凝土表面出现的线状开裂标注时需要用四边形框紧紧贴合裂缝主体区域不能把背景混凝土框进去太多。破损的定义是沟体表面出现剥落、缺角或坍塌这类目标面积通常较大标注框可以适当外扩。堵塞的定义是排水沟内被淤泥、碎石或杂物填塞标注框需要覆盖堵塞物的主要堆积范围。渗水的定义是沟壁出现明显水流痕迹、析白或潮湿区域标注时需要结合周围环境上下文判断。标注过程中的一个关键规则是一定要把“密集小目标”拆开标注。排水沟裂缝经常出现整面墙都是细碎裂缝的情况标注人员容易偷懒随手画一个大框把一片裂缝全框进去。这样做出来的训练数据会让模型学到一个错误逻辑——大框代表整片病害。正确的做法是在保证可辨识的前提下把密集裂缝拆分到小框里尽量让每个框对应一条独立的裂缝或一个局部区域。标注质检也有讲究。这个项目采用了两轮质检机制第一轮由标注员自查重点检查目标是否漏标第二轮由熟悉隧道结构的技术人员复查重点检查病害类型是否标错。第二轮质检尤其重要因为水渍和渗水、泥浆和堵塞在视觉上相似度很高只有懂业务的人才能准确区分。2.3 数据增强与训练集划分隧道病害图像的数据量一般不会特别大一个中等规模的隧道项目能凑到几千到一万张有效标注图就很不错了。这个量级直接训练一个深层检测网络很容易过拟合数据增强是必须做的一步。增强策略要符合场景物理规律不能盲目乱用。比如水平翻转完全合理因为排水沟左右对称但垂直翻转就不行因为现实中不会倒着拍。颜色抖动可以用因为不同隧道的光照和色温确实有差异但过度的色彩变换会导致模型把颜色当成病害特征反而影响泛化。这个项目实际采用的增强组合是水平翻转、小角度旋转±10度、亮度和对比度随机调整、小幅随机裁剪缩放。训练集划分上我习惯的做法是按隧道划分而不是按图像划分。如果同一个隧道的图像既出现在训练集又在验证集模型很容易靠“记忆”背景环境来识别病害验证分数虚高。按隧道划分可以让验证集真正检验模型的泛化能力。划分比例上训练集、验证集、测试集大概按7:2:1来分配。测试集严格独立只用于最终效果评估用来调参和选模型的只能是验证集。实际操作中我发现很多人急着调参验证集跑几轮就当成最终结果来汇报后面在测试集上一塌糊涂这个习惯一定要改。3. 模型搭建与训练全流程3.1 Faster-RCNN结构与FPN对排水沟病害的意义把Faster-RCNN拆开看核心就是两个部分区域候选网络RPN和检测头网络。RPN负责在图像上生成可能包含目标的候选框检测头负责对每个候选框做分类和精确回归。ResNet50负责提取整个图像的特征图供RPN和检测头共享使用。这里必须提一下FPN特征金字塔网络它对排水沟病害检测的重要性甚至超过主干网络本身。隧道巡检图像里的病害目标尺寸差异很大堵塞和破损常常是大目标裂缝和早期渗水则是小目标。如果没有FPN最后的特征图经过多次下采样后浅层的高分辨率细节已经丢失了小目标基本上就没法检测了。FPN的做法是从ResNet50的不同层分别引出特征把深层语义信息自上而下融合到浅层特征中让每一层特征都既有细节又有语义。这样一来RPN可以在多个尺度的特征图上做候选框生成小裂缝在高分辨率特征层上被捕捉大面积破损在低分辨率语义层上被识别。增加FPN之后排水沟裂缝的召回率提升了大概8到10个百分点这也验证了结构选型的价值。3.2 训练环境与关键参数配置训练环境的配置这里分享一组实测稳定的方案供参考深度学习框架选用PyTorch版本对应CUDA环境。Faster-RCNN在PyTorch生态里有比较成熟的实现做训练脚本的定制很方便。GPU使用显存16G以上的单卡。ResNet50FPN的模型结构输入图像缩放到1333x800时训练显存占用大概在8到12G之间。如果只有8G显存需要把batch size降到2同时开启梯度累积。优化器用SGD初始学习率0.005动量0.9权重衰减0.0001。这里不选Adam的原因是SGD在检测任务上的收敛稳定性更好最终精度通常也略高。batch size设置为4单卡训练每个epoch做300次迭代。学习率使用阶梯式下降在第8个和第11个epoch分别乘以0.1。整个训练过程大概12到14个epoch。锚框设置做了针对性调整。Faster-RCNN默认的锚框尺寸是8、16、32、64、128但在排水沟场景里长条形的裂缝框比例很特殊。我在锚框比例里增加了1:3和3:1两种长宽比用来匹配裂缝的细长形态这个改动对裂缝检测的提升非常直接。3.3 训练过程观察与调参记录训练过程中的观察和调参往往是决定模型最终效果的分水岭。这里记录几个关键阶段的现场情况。初始阶段前两三个epoch的loss下降非常快从初始值快速降到正常范围的1/10左右。这个阶段如果loss不减通常不是模型问题而是数据处理出了问题常见的是标注框坐标越界或者图像通道顺序错误需要马上停掉排查。训练中期loss曲线会进入一个平滑下降期。我这里监控的是总loss同时也会分开看RPN loss和RCNN loss。如果RPN的loss居高不下说明候选框生成质量有问题优先检查锚框设置和正负样本比例。如果RCNN的loss降不下去说明分类和回归头学习不好优先考虑骨干网络是否需要解冻更多层。训练后期主要工作是防止过拟合。我在每个epoch结束后跑一次验证集记录每个类别的AP值。当验证集AP不再上升甚至开始下降而训练集AP还在小幅上升时就说明过拟合已经开始了。判断依据很清楚不要恋战直接取验证集最优的那一版模型权重。调参过程中还有一处值得记录正样本IoU阈值。Faster-RCNN默认的RPN正样本IoU阈值是0.7但在排水沟这种细长目标的场景下候选框稍微偏移一点IoU就可能掉到0.5以下。我最终把RPN正样本IoU阈值从0.7放宽到了0.6同时保留检测头0.5的IoU阈值不变。这个参数调整的效果很显著裂缝的召回率提高了代价是候选框数量增加推理时间多了10毫秒左右权衡下来完全值得。4. 部署与实机推理的落地细节4.1 推理链路架构设计模型训练好只是第一步真正到了生产部署阶段需要考虑的东西完全是另一个维度。这个项目的推理链路设计成三个环节图像获取、批量推理、结果落库。图像获取环节从巡检车的存储系统里定时拉取新增的巡检图像。图像分辨率大直接丢给模型推理会出现两个问题一是大图单次推理显存不足二是原始图像中排水沟只占画面的一部分直接整图推理会把大量无效背景也送入网络。实际做法是做切图处理把原始大图按1280x720的大小切块切块之间保留64像素的重叠区域防止病害刚好被切在边缘。切块后每一块独立送入模型推理推理完再把结果映射回原图坐标。推理环节为了提升速度我把模型导出成ONNX格式再用推理引擎做加速。这个过程中最容易出问题的是动态尺寸和锚框生成。Faster-RCNN的输入尺寸如果是动态的导出后推理时容易报错或变慢稳妥的做法是固定输入尺寸为1333x800推理前把切好的图像统一缩放。后处理环节也有不少细节。模型输出的原始预测框需要经过非极大值抑制NMS去重然后再根据置信度阈值过滤。置信度的选择不能拍脑袋我用验证集做了阈值扫描画出每个类别的置信度-召回率曲线。最终裂缝、破损、堵塞、渗水四类的置信度阈值分别定为0.5、0.55、0.5、0.6。渗水类阈值调高是因为渗水和水渍的视觉相似度高低阈值会带来大量误检。4.2 现场验证与效果评估现场验证需要拿到真实巡检数据上跑一遍而不是只在测试集上打分数。我把模型部署到一台工控机上接入了一个隧道段的1000张现场图像作为模拟验收数据。验收指标重点关注两块检出率和误检率。检出率等于正确检出的病害数量除以人工复核确认的实际病害总数误检率等于误检目标数量除以模型输出目标总数。跑完一轮的结果大致记录如下表格数据根据项目意见摘录病害类型检出率误检率主要失分点裂缝85%18%细小裂缝与小阴影混淆破损91%12%深色水渍区剥落边缘难判断堵塞93%9%碎石堆与淤泥堆易误检渗水82%22%低速流水纹理被当成裂缝从表格可以看出渗水这个类别的误检率最高。分析失败案例后发现问题主要出在渗水和水渍在静止图像上几乎无法区分。现场复核人员反馈如果只看单帧图像有时候人也分不清到底是渗水还是水渍需要查看连续帧是否有动态水流痕迹。后来在推理链路里增加了一个连续帧关联环节同一位置在多帧图像中重复检测到“渗水”才确认为渗水病害。加了这一步之后渗水误检率从22%降到了11%。4.3 部署环境与性能指标控制部署环境的硬件配置这个项目用的是GPU工控机和CPU备用机各一台的方案。GPU工控机作为主力推理节点CPU备用机作为降级方案。正常运行时GPU推理单帧耗时约100毫秒加上切图、IO和前后处理耗时一张4000x3000的大图完整处理大约需要4到5秒。这个速度对巡检后批处理场景完全够用。如果项目对实时性要求更高CPU部署完全走不通Faster-RCNN在CPU上单张图要跑5秒以上。可以考虑两个优化方向一是切图时把重叠区域减小减少推理次数二是把骨干网络换成ResNet34牺牲少量精度换取约30%的速度提升。这个项目里因为对精度要求更高没有采用后一种方案。部署阶段还有一个容易忽略的问题就是显存泄漏。PyTorch模型在长时间连续推理时如果代码里没有做好梯度释放和显存清理很容易在几个小时后出现显存溢出。生产环境的推理脚本里必须显式添加torch.no_grad、torch.cuda.empty_cache和周期性重启机制。我在项目上线前做了24小时连续推理压力测试就是靠这个版本迭代把显存稳定性调好的。5. 常见问题与排查技巧5.1 病害漏检与误检的针对性排查漏检和误检是工业检测项目最常被问的两个问题我把实际排查经验整理成一张速查表直接对照处理表格数据常见问题问题表现可能原因排查与解决路径裂缝漏检多小目标特征丢失、锚框比例不合适检查FPN是否启用增加1:3长宽比锚框提高输入分辨率渗水误检多水渍与渗水视觉相似增加连续帧关联判断提高渗水置信度阈值补充标注负样本堵塞漏检集中在淤泥颜色与背景相似度高增加局部对比度增强预处理补充数据时加入不同湿度环境的图片破损误检多阴影与剥落区域混淆检查采集补光方向用破损边缘的连续性做后处理过滤所有类别漏检率均高训练数据不足或标注质量差优先扩充数据对标注做二次质检检查正负样本比例5.2 训练不稳定和loss不收敛的处理训练过程中遇到的另一个典型问题是loss不收敛或者训练中途爆炸。我遇到过的最常见原因有三个。第一个是学习率过大。SGD初始学习率如果设在0.01以上很容易在训练初期就把权重更新到不稳定的区域表现为loss在前几个epoch不降反升。处理方式是把学习率降低到原来的十分之一同时确认有没有做梯度裁剪梯度裁剪阈值可以设在10左右。第二个是标注框问题。部分标注框的坐标超出了图像边界训练时边界回归的loss会变得极大连带把整体loss拉高。排查方法是在数据加载阶段加一个坐标合法性检查把所有越界框强制裁剪到图像范围内。第三个是正负样本极端不平衡。如果一张图中病害目标极少RPN生成的正样本数量就会极少导致RPN loss的梯度噪声很大。这个场景下可以适当降低RPN正样本IoU阈值增加正样本数量或者使用Focal Loss来缓解类别不平衡。5.3 推理环节的显存与速度优化推理环节的常见问题是显存占用过高和速度不达标。除了前面提到的切图和固定尺寸输入之外还有几个更细的优化点。批量推理比单张推理更高效。把多张切图拼成一个batch一起送进模型吞吐量能提升好几倍。刚开始测试的时候使用batch size 8推理显存占用比单张推理大约增加了40%但处理总时长缩短了接近70%效果明显。另一个优化点是关闭批量归一化层的统计量更新。模型推理时使用的是训练阶段统计好的均值和方差不需要在推理时重新计算。在框架层面正确切换train/eval模式把这些层的参数固定不仅速度有提升推理结果的稳定性也更好。最后一个技巧是控制特征图的存储粒度。Faster-RCNN在推理时RPN生成的候选框数量可以直接限制把每张图最多保留的候选框数从默认的300降到150对小目标密集的场景召回率影响很小但推理时间能减少约15%。前提是确保候选框排序使用分类置信度而不是仅用目标得分。6. 写在最后个人经验与扩展方向这个项目做下来我最大的感受是深度模型在工业视觉里的落地难点往往不在模型本身而在模型的“前后端工程”。数据采集是否符合物理规律标注标准是否与现场判定一致推理链路能否在一个连续运行的环境里稳定工作这些才是决定项目成败的关键。从模型角度说Faster-RCNN和ResNet50的组合在精度上的优势是可以被验证的它把排水沟病害识别这个任务的检测精度做到了可用水平。如果你所在的项目对速度要求更高又有足够的数据保证精度可以考虑用YOLO系列作为替代。但如果你遇到的是小目标密集、背景杂乱、误检代价高的检测任务Faster-RCNN加ResNet50加FPN这套组合仍然是值得优先尝试的基线。这个系统后续还可以扩展的方向也比较明确。一是加入连续帧时序建模利用视频流里病害的动态特征来区分渗水和水渍这块已经在工程上验证过有效可以继续加深。二是加入定量分析能力从检测框的几何尺寸推算裂缝宽度和破损面积把检测结果直接输出成维护工单的定量依据。三是用轻量化网络做初筛再让Faster-RCNN在候选区域上做精细识别结合两种模型的优势。最后分享一个小体会工业检测项目的验收标准从来不是论文里的mAP而是现场复核人员打开检测图集后有没有眼前一亮。做技术方案的时候多站在这个角度看问题很多选型决策都会变得清晰。