ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

输电杆塔无人机巡检实时目标检测:从YOLO训练到TensorRT部署全流程

输电杆塔无人机巡检实时目标检测:从YOLO训练到TensorRT部署全流程 简介这份文档聚焦无人机电力线路杆塔巡检场景提出基于深度学习算法的实时目标检测模型适合电力运维、无人机巡检及计算机视觉方向的研究者与工程师参考。内容系统覆盖了模型建构的关键环节基于Darknet的深层特征提取、针对三个尺度目标的特征交互层设计以及通过K-means聚类重新聚类目标框以改进算法参数的方法同时针对倒断类杆塔样本不均衡问题采用平移、缩放、翻转等图像增广策略进行数据扩充整体思路完整便于读者复现或迁移到其他电力部件检测任务。文档共1个docx文件大小约56KB文字精炼、排版清晰适合直接阅读或作为技术方案素材。测试数据较有说服力改进后的模型在测试集上平均均值精度达到94.09%检测速度约20帧/秒简化版可提升至30帧/秒能够满足实时巡检需求。目前已有137人学习下载适合正在开展无人机电力线路巡检智能化改造、目标检测算法选型或相关课题研究的读者借鉴。1. 输电线路无人机巡检为什么卡在“看图”这一步一条 500kV 线路动辄上百基杆塔传统人工巡检一年最多跑四次无人机把照片拍回来还是得人坐在电脑前一张张看。两小时盯完两百张图眼睛发花绝缘子缺个伞裙、销钉掉了一半这种小目标漏掉是常态。基于深度学习算法的无人机电力线路杆塔巡检实时目标检测模型解决的就是“拍完能当场知道有没有问题”这件事无人机还在塔边上悬停模型已经把缺陷框出来了飞手直接补拍可疑部位不用等落地拷卡、再回办公室翻图。我的建议很直接别一上来就上深度强化学习算法那套在线学习路线边缘算力撑不起闭环训练用轻量目标检测网络YOLO 系 TensorRT/OpenVINO 推理加速才是电力巡检场景里能落地、能复制到整个机队的方案。下面从相机选型讲到量化部署全程可照做。2. 云台相机怎么选像素密度换算与锁定放大倍数2.1 能拍清才能检得准先算像素密度再谈模型很多团队踩的第一个坑是拿消费级云台相机飞一圈回来标注的时候发现绝缘子串在画面里只有十几个像素模型再强也学不出特征。目标检测模型的输入分辨率通常只有 640×640 或 1280×1280原图里目标占不到 30×30 像素下采样后基本就糊成一团了。我一般会先做一个换算估算拍摄距离、相机焦距和目标物理尺寸算出目标在画面里占多少像素。公式很简单像素数 (目标物理尺寸 × 焦距) / (拍摄距离 × 像元尺寸)以常见的 400kV 混凝土杆塔为例绝缘子串长度约 2 米无人机在 30 米外斜向 45° 拍摄实际拍摄距离约 42 米。用 1/1.8 英寸传感器、像元 2.4μm、焦距 100mm 的长焦云台相机计算绝缘子串在感光元件上的投影长度是 (2000×100)/(42000×0.0024) ≈ 1985 像素缩放到 640 分辨率后仍能占到约 60 像素足够训练。如果只有 24mm 广角镜头同样的距离下像素数直接缩到四分之一缩放到 640 后就只剩 15 像素左右这种数据标注出来也是浪费算力。提示建议起步焦距不低于 80mm 等效巡检距离控制在 25~50 米。斜向拍摄时按实际斜距计算不要用水平距离估算否则标注框和模型推理都会偏。2.2 锁定放大倍数与云台增稳飞手操作习惯要改相机选完之后飞手操作习惯比参数更影响检测效果。无人机在悬停时会有漂移长焦端画面抖动非常明显。云台增稳能解决一部分但模型推理时输入画面最好是“相对静止”的前后两帧目标位移超过目标尺寸的一半NMS 后处理就会把同一个目标分裂成多个框。实际项目中我要求飞手采用“悬停-锁定-采集”三步操作无人机飞到塔侧预定位置后先让云台锁定目标区域等待画面稳定 2~3 秒再触发拍摄。搭载 RTK 定位和视觉定位的飞控系统基本能稳住悬停但要记得把云台“跟随”模式关掉切成“自由”模式否则飞机一晃云台跟着转画面中线目标反而跑出视野。这里给一张我们内部常用的选型对照表供参考项目起步方案进阶方案备注可见光传感器1/1.8 英寸2000 万像素1/1.2 英寸2400 万像素大传感器低照度表现更好焦距范围6~120mm 等效10~240mm 等效广角端找塔长焦端检测云台增稳精度±0.01°±0.003°长焦端必须高精度激光测距可选必备用于自动对焦和测距定标锁定放大倍数不是越大越好。我见过有团队用 240mm 等效焦距去拍绝缘子结果塔身都在视野外模型无法判断目标在塔上的相对位置。正确做法是用广角端找到杆塔切到 80~120mm 等效拍摄目标区域让目标占画面三分之一左右这样模型既能看到目标细节又能保留上下文特征。2.3 整机负载与续航边界别把模型跑死在算力板上无人机挂载的设备越多续航越短这是物理规律。检测模型如果跑在机载计算板上整机重量、散热和功耗都要纳入计算。目前常见的做法有两种一是把模型跑在机载 NVIDIA Jetson Orin NX 这类算力板上二是通过 5G/自组网图传把视频流推到地面站推理。前者延迟低但受限于机载供电后者可以上更强的 GPU但依赖网络质量。我一般建议起步阶段用地面站推理机载端只回传视频流等模型稳定后再考虑机载部署。这样前期的数据采集、标注、训练迭代完全不受算力板限制也不会因为算力板过热导致飞机掉续航。等整条链路跑通了再买一台高配机型做机载试验对比端到端延迟和检测率。3. 数据采集与标注规范输电杆塔目标检测的“地基”3.1 飞行航线与拍摄角度设计环绕式采集比平拍有效检测模型的泛化能力很大程度上取决于采集数据的多样性。很多项目用单一角度拍杆塔模型训练出来后换个拍摄角度就检测不到绝缘子以为是自己网络结构不行其实是数据没覆盖到。我定的采集规范是无人机在杆塔周围按 6~8 个方位环绕飞行每个方位采集一组照片俯仰角控制在 -15° 到 -60°即从平视到斜向下看。再加上从塔顶往下拍的“俯视巡检”模式覆盖金具和导线的挂点。这样模型学习到的特征不是某一个固定视角下的形状而是目标在不同姿态下的共性结构。光照条件也要刻意制造多样性顺光、逆光、阴天、中午强光、傍晚低照度各拍一部分。逆光条件下绝缘子串会变成剪影模型如果没有见过这种样本部署时一遇逆光就直接漏检。注意这里说的是用可见光数据训练。若后续想扩展红外热像检测不要把红外数据混进 RGB 训练集两者的特征分布差异太大混合训练会让模型两头不讨好。3.2 标注类别怎么定从“杆塔”到“销钉级”粒度选择标注类别的粒度决定了模型的检测能力上限。只标“绝缘子”很容易但巡检真正关心的是“绝缘子缺失”“均压环变形”“销钉脱落”这些具体缺陷。缺陷检测需要的数据量比目标检测大得多一个新缺陷类别往往要积累几百张正样本才能训稳。我的做法是分两阶段标注。第一阶段只标目标类别杆塔、绝缘子串、均压环、防震锤、导线挂点。第二阶段针对高频缺陷做细分标注比如“绝缘子破损”“均压环歪斜”。分类别时遵循一个原则——宁可粗一点不要乱类别间特征重叠严重时模型会无所适从。目标类别标注建议常见坑杆塔整体外接框框得太大把背景包进来绝缘子串串的整体外接框拆成单个伞裙会导致目标过小均压环环的外接框与绝缘子串紧贴时漏标防震锤单个锤体外接框一对锤子只标一个导线挂点挂点区域框与金具混淆3.3 标注工具与格式选择VOC 还是 COCO标注格式尽量用工程生态最通用的。VOC 格式的 XML 简单易懂几乎所有的检测框架都能直接消费COCO 格式的 JSON 更适合 cocoapi 直接评估 mAP。我给团队的要求是标注工具导出 VOC XML训练脚本里统一转成目标框架所需的格式避免源头改了又改。annotation foldertower_images/folder filenameIMG_20240315_104233.jpg/filename size width4000/width height3000/height /size object nameinsulator_string/name bndbox xmin1200/xmin ymin800/ymin xmax1850/xmax ymax2100/ymax /bndbox /object /annotation代码里标注的目标是绝缘子串坐标直接写的是原图分辨率下的像素位置。注意 xmax/ymax 是包含目标边缘的坐标不是“中心点宽高”结构训练框架读取时一般会自行换算但你做数据增强时要保证对 bndbox 同时做变换。3.4 数据量到底要多少小目标检测的样本估算目标检测的数据量没有统一答案我给一个基于经验的参考单类别目标检测2 万张干净标注图基本是工程级效果每类目标各 3000 个以上标注实例训练出来的模型才有信心部署。这里说的“实例”是标注框的数量不是图片数量一张图里有 3 串绝缘子就算 3 个实例。杆塔巡检的项目普遍数据不够我常用的补救手段是用开源无人机高光谱农业数据集里近似的“杆状物”样本做预训练初始化然后在自己标注的数据上微调。虽然成像谱段不同但低层特征边缘、纹理是通用的比从头训练收敛快得多。实在没有公开数据可用也可以去拍变电站、铁路接触网等相似结构目标做一次粗标注先把模型的“形状感知”能力拉起来。4. 用 YOLOv8n 建杆塔检测模型训练脚本与参数调整4.1 为什么选 YOLO 系而不选两阶段检测器电力巡检场景对实时性有硬要求无人机以 5m/s 巡航如果推理速度低于 10FPS画面都飞过了框才出来飞手根本来不及补拍。两阶段检测器Faster R-CNN 等精度上限高但单张推理耗时普遍在 100ms 以上加上前后处理很难满足边缘设备上的实时要求。YOLO 系是单阶段检测器的代表YOLOv8n 是轻量级配置在 Jetson Orin NX 上跑 TensorRT FP16实测能做到 30ms 左右。这里多说一句YOLOv8n 的 n 是 nano是专门为边缘设备设计的版本参数多一点的 YOLOv8s 模型 mAP 能高 2~3 个点但推理时间翻倍我建议先跑 nano验证流程后再衡量要不要换大的。深度强化学习算法在巡检决策规划里是有价值的比如航迹优化但在实时检测这个环节它既慢又难以收敛不适合。4.2 数据配置与训练启动最小可复现命令我用的框架以 Ultralytics 为例因为它代码生态完整部署导出也方便。首先组织数据集目录结构data/ ├── train/ │ ├── images/ │ └── labels/ └── val/ ├── images/ └── labels/标注文件格式是 YOLO 的 txt每行class_id x_center y_center width height全部用归一化坐标表示。把 VOC XML 转换成这种格式用一个小脚本处理最省事注意 x_center 是 (xminxmax)/2 再除以图片宽度不是直接取 xmin。import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, out_path, img_w, img_h, classes): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.findall(object): name obj.find(name).text if name not in classes: continue class_id classes.index(name) box obj.find(bndbox) xmin int(box.find(xmin).text) ymin int(box.find(ymin).text) xmax int(box.find(xmax).text) ymax int(box.find(ymax).text) x_center (xmin xmax) / 2 / img_w y_center (ymin ymax) / 2 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(out_path, w) as f: f.write(\n.join(lines))这个脚本的关键点是坐标归一化。很多新手在这里出错因为 ymax-ymin 得到的是目标实际高度像素值不除以图片高度的话训练时框的位置和大小就全部错位loss 会居高不下。classes 列表的顺序要和训练配置里的类别顺序完全一致否则类别标签会错位。数据配置完成后训练命令如下。输入尺寸我建议先从 640 开始小目标占比高的话再试 1280代价是训练和推理时间都会翻倍。yolo detect train \ datatower.yaml \ modelyolov8n.pt \ epochs200 \ imgsz640 \ batch16 \ lr00.01 \ patience30 \ projectruns/tower_det \ nametower_nano_640几个参数的调整依据batch16 在单张 12GB 显存上刚好跑满lr00.01 是预训练权重微调的常见起点如果 mAP 在前 30 轮不涨降低到 0.005 再试patience30 表示验证集 mAP 连续 30 轮不提升就早停防止过拟合。4.3 小目标检测的专项优化切图与多尺度杆塔巡检里的小目标问题很突出防震锤、销钉这类目标在 640 分辨率下只有 10~20 像素。这种情况下常规的 mosaic 数据增强效果有限更直接的手段是切图训练SAHI 方案的思想。把原图切成 4 个重叠的 960×960 区域每个区域独立训练和推理最后再把检测框映射回原图坐标。切图推理的代价是计算量增加到原来的 4 倍帧率会掉到个位数。折中方案是用整图跑第一遍置信度低于阈值的区域再用切片跑第二遍只在疑似区域做精细搜索。这个“先粗后精”的策略在项目里实测有效小目标召回率能提升 15 个百分点以上。4.4 训练阶段的坑BN 层在 batch 太小时的漂移如果显卡显存不够把 batch 降到 4 甚至 2批量归一化层的统计量会很不稳定导致验证集上 mAP 剧烈波动。解决办法是固定输入分辨率、增大 batch或者改用冻结 BN 层的微调模式。当我只能用单张 8GB 卡训练时通常把 batch 压在 8 以上图片尺寸降到 480。分辨率降了之后小目标更难学所以要在数据增强里把 mosaic 概率调高让模型看到更多小目标样本。5. 部署与常见问题排查从 PyTorch 模型到边缘推理5.1 训练完怎么部署ONNX 导出与 TensorRT 加速训练出来的 PyTorch 权重不能直接上机先导出为 ONNX 中间格式再转成目标平台的推理引擎。模型导出命令参考yolo export modelruns/tower_det/tower_nano_640/weights/best.pt \ formatonnx \ dynamicFalse \ imgsz640 \ opset12dynamicFalse 是关键参数把输入尺寸固定成 640×640这样后续 TensorRT 优化能拿到静态 shape推理效率最高。如果需要支持多种输入尺寸再单独开 dynamic 并接受性能折损。ONNX 拿到之后英伟达平台用 TensorRT 转换Intel 平台用 OpenVINO 转换转换时开启 FP16 精度import tensorrt as trt logger trt.Logger(trt.Logger.WARNING) builder trt.Builder(logger) network builder.create_network() parser trt.OnnxParser(network, logger) with open(tower_nano.onnx, rb) as f: parser.parse(f.read()) config builder.create_builder_config() config.set_flag(trt.BuilderFlag.FP16) engine builder.build_engine(network, config) with open(tower_nano.engine, wb) as f: f.write(engine.serialize())这段代码是标准的 ONNX 转 TensorRT FP16 引擎流程。注意要在目标设备上执行转换因为 TensorRT 的 kernel 选择依赖具体 GPU 架构换一张卡就要重新转一次这也是很多团队部署时会忽略的坑。5.2 部署后必调的三个参数置信度阈值、NMS IoU、推理批大小模型转成引擎后不能直接用默认置信度阈值 0.25。电力巡检场景里漏报的代价远大于误报所以阈值要往低调。我一般设 conf0.15再从实际结果里逐步上调找到误报可接受的下限。NMS 的 IoU 阈值保持默认 0.45 即可杆塔目标之间的重叠不多调太大反而会让同一目标的重复框合并失败。批大小影响吞吐量。实时视频流场景下 batch1 是最低延迟如果做离线批量处理batch4 可以提升吞吐但显存占用也翻倍。巡检视频建议用 batch1 跑实时推理跳帧检测每 3 帧检测一次来提升有效帧率比强行加大 batch 更实际。5.3 五个高频踩坑记录坑一小目标全部漏检。现象是防震锤和销钉一次都没检出绝缘子倒是正常。原因是输入分辨率 640 下小目标下采样后特征消失。解决升级切图推理或把 imgsz 提到 1280二选一。验证时要用包含小目标的图片单独评估不要只看整体 mAP。坑二无人机晃动导致检测框跳变。现象是前后帧同一目标的框忽大忽小甚至目标丢失后再出现。原因是快门前画面运动模糊模型把模糊目标当成“不确定”区域。解决缩短曝光时间到 1/1000 以上配合云台增稳不要靠调低置信度那会让误报也跟着涨。坑三TensorRT 转换后精度掉得厉害。现象是 FP16 引擎的 mAP 比 PyTorch 低 5 个点以上。原因是某些算子在 FP16 下溢出常见于小数值梯度的归一化层。解决先试 FP16如果掉点严重就回退 FP32或者对归一化层做精度白名单只对卷积层开 FP16。坑四推理帧率达不到 10FPS。现象是 Jetson 上 full pipeline 只有 6FPS。原因是预处理缩放、归一化在 CPU 上做没走 GPU。解决把 resize 和 normalize 用 GPU 算子实现或者用 TensorRT 自带的预处理插件把输入直接喂到 GPU 显存减少 CPU-GPU 拷贝。坑五飞行中偶发内存撑爆。现象是飞了 20 分钟后机载算力板内存持续上涨直到 OOM。原因是推理引擎内部有缓存没有释放视频流输入速率太高时来不及回收。解决限制输入队列长度最简单的方法是跳帧降速把检测频率控制在每秒 3 次以上即可巡检场景不需要全帧率检测。6. 验证与调优技巧一张混淆矩阵比一打 demo 有用模型部署完验证不是对着几张图看效果而是系统性地量化。我每周跑一次全量测试集把结果导出成混淆矩阵逐项看。重点看两类误差目标被误判成背景的漏检、以及背景被误判成目标的误检。如果是前者优先补数据和调阈值如果是后者优先关掉低置信度的区域。还有一个实操技巧把检测结果叠加 XML 坐标画到原图上和人工标注框做 IoU 热力图。IoU 在 0.5 附近的“模棱两可”样本其实是在告诉你标注框本身就不准而不是模型有问题。我做过一次项目发现模型 mAP 卡在 78% 不动排查了一个月最后发现是标注团队把绝缘子串的框上下边界多包了 30%修正标注后 mAP 直接跳到 84%。数据质量的修正收益永远比调参高。最后一招也是最容易被忽略的建立“固定航线复测”机制。每个月挑三条典型线路用相同的航线参数复飞对比同一基杆塔的检测结果差异。如果这个月检测出 30 个缺陷、下个月只检测出 22 个而线路实际没变那一定是模型或环境出了问题需要回查数据集有没有混入新的干扰样本。我个人的习惯是每次部署新版本之前先在历史视频上做一次完整回放统计“漏检缺陷数”“误报数”“平均推理耗时”三个指标。这三项没有恶化再放行。早期我只看均值帧率结果实际飞行中画面一颠簸就翻车后来就再也不信单值指标了——做工程玄学少碰就靠数据说话。希望这个流程对你有用。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进