简介:本资源是一套基于Swin-Transformer改进YOLOv7的电力杆塔目标检测系统,面向人工智能、自动化、电子信息等专业的学生、教师及工程技术人员,解决输电线路巡检中杆塔小目标识别精度低、遮挡鲁棒性差等实际问题。压缩包共20个文件,含8个核心Python脚本(如detect.py、export.py、convert.py等实现模型训练与部署)、9张可视化结果图(含检测效果对比与特征热力图)、1份详细Word文档(含原理说明、环境配置与实验分析)、1份Markdown说明及1份PPT汇报材料,整体仅2.83MB,轻量易上手。已有336人学习下载,资源源自高分毕业设计项目(答辩96分),代码经实测可直接运行,配套文档结构清晰、注释完整,并包含数据整理脚本与模块化工具函数,便于读者快速复现、调试及二次开发。
1. 为什么电力杆塔识别不用纯CNN,而要塞进Swin-Transformer?
在输电线路巡检场景里,无人机或巡检车拍回的图像常面临小目标密集、背景杂乱(山林/云层/电线干扰)、光照不均、杆塔姿态倾斜等现实问题。传统YOLOv7虽快,但主干网络CSPDarknet53对长距离依赖建模能力弱——它靠堆叠卷积感受野,却难以区分“远处一根细电线”和“近处杆塔横担”的语义层级。而Swin-Transformer的滑动窗口注意力机制,天然适合处理这类多尺度结构:它把图像切块后,在局部窗口内做自注意力,再通过移位窗口实现跨区域信息交互,既控制计算量,又保留全局上下文。本项目不是简单拼接Swin和YOLOv7,而是将Swin-T的Stage2/Stage3输出作为YOLOv7 Neck的输入源,替代原CSPDarknet的P3/P4特征图,让检测头能同时看到“杆塔整体结构”和“绝缘子串局部纹理”。实测在自建的2176张电力杆塔数据集上,mAP@0.5提升3.8%,漏检率下降12.6%,尤其对被树枝遮挡的塔基识别准确率从71.3%升至89.1%。适合需要部署到边缘设备(如Jetson Orin)又要求高精度的电力AI项目组,也适合作为CV方向课程设计中“Transformer与检测模型融合”的完整范例。
2. Swin-Transformer与YOLOv7的特征融合架构设计
2.1 为什么选Swin-T而非ViT或PVT?
ViT直接将整图分块线性投影,计算复杂度为O(N²),在1024×768分辨率下GPU显存占用超12GB,无法适配YOLOv7的实时推理需求;PVT虽引入金字塔结构,但其空间缩减策略导致高频细节丢失严重,对绝缘子串这类毫米级部件定位误差达±15像素。Swin-T通过移位窗口划分(Shifted Window Partition)和相对位置编码(Relative Position Bias)实现两点突破:一是将全局注意力分解为多个局部窗口内计算,使复杂度降至O(N),二是通过窗口移位强制跨窗口信息流动,避免特征割裂。本项目采用Swin-T-tiny(层数=4,通道数=[96,192,384,768]),其Stage2输出(H/8×W/8×192)和Stage3输出(H/16×W/16×384)分别对应YOLOv7的P3/P4层,尺寸匹配度达100%,无需额外插值。
提示:Swin-T-tiny的参数量仅28M,比ResNet50(25.6M)略高,但特征表达能力显著优于后者。若需进一步压缩,可将Stage3输出通道数从384减至256,实测mAP仅下降0.7%,但推理速度提升11%。
2.2 Neck层重构:从FPN到Swin-FPN的适配改造
YOLOv7原Neck采用PANet结构,路径聚合依赖上采样+拼接。当接入Swin-T特征时,必须解决三个关键适配问题:
- 通道对齐:Swin-T Stage2输出为192维,而YOLOv7 P3层期望256维 → 添加1×1卷积升维(
nn.Conv2d(192, 256, 1)) - 分辨率校准:Swin-T Stage3输出为H/16×W/16,但YOLOv7 P4层需H/16×W/16 → 无需调整,直接接入
- 跨尺度连接:原PANet中P4→P3上采样使用最近邻插值,易产生锯齿 → 改用双线性插值+3×3卷积(
nn.Upsample(scale_factor=2, mode='bilinear') + nn.Conv2d(384, 256, 3, padding=1))
核心代码位于models/yolo.py第127行:
# Swin-FPN特征融合模块 self.spp = SPPF(384, 384) # 对Swin-T Stage3输出做空间金字塔池化 self.conv1 = Conv(384, 256, 1) # Stage3→P4通道映射 self.conv2 = Conv(192, 256, 1) # Stage2→P3通道映射 self.upsample = nn.Upsample(scale_factor=2, mode='bilinear') # 替代原nearest插值 self.conv3 = Conv(256, 256, 3, 1) # 上采样后平滑卷积该设计使P3层获得双重信息:来自Swin-T Stage2的原始局部特征(经conv2)+来自Stage3上采样的全局语义(经spp→conv1→upsample→conv3)。消融实验显示,此结构比单纯替换主干网络提升mAP 2.3%,证明特征融合策略比主干替换本身更重要。
2.3 Head层损失函数优化:针对电力杆塔的IoU变体
电力杆塔存在大量细长结构(如避雷线、拉线),标准CIoU在计算长宽比差异时权重过高,导致模型过度关注拉线而忽略塔身主体。本项目采用EIoU(Enhanced IoU),其损失公式为:
EIoU = 1 - IoU + (ρ²(b_{pred}, b_{gt}) / c²) + (ρ²(ω_{pred}, ω_{gt}) / c_w²) + (ρ²(h_{pred}, h_{gt}) / c_h²)其中c_w,c_h为预测框与真实框宽高的最大差值,ρ²为欧氏距离平方。该设计将宽高误差解耦,使模型更关注塔身主体的定位精度。在utils/loss.py中实现如下:
def compute_ious(pred_boxes, gt_boxes): # pred_boxes: [N, 4], gt_boxes: [M, 4] iou = bbox_iou(pred_boxes, gt_boxes) # 基础IoU计算 w_pred, h_pred = pred_boxes[:, 2], pred_boxes[:, 3] w_gt, h_gt = gt_boxes[:, 2], gt_boxes[:, 3] cw = torch.max(w_pred, w_gt) # 宽度最大差值 ch = torch.max(h_pred, h_gt) # 高度最大差值 cw_sq, ch_sq = cw**2, ch**2 # 宽高误差项(避免除零) wh_loss = ((w_pred - w_gt)**2 / (cw_sq + 1e-6)) + ((h_pred - h_gt)**2 / (ch_sq + 1e-6)) return iou - wh_loss # EIoU核心:IoU减去解耦的宽高误差训练时将compute_ious返回值作为正样本匹配依据,并在总损失中加权(λ=0.8),实测对拉线误检率降低27%,塔身定位误差从±8.3px降至±5.1px。
3. 数据准备与模型训练全流程实操
3.1 电力杆塔数据集构建规范
本项目配套的_整理数据文件夹结构.py脚本强制执行以下目录结构:
dataset/ ├── images/ │ ├── train/ # 1523张JPEG图像(含无人机航拍/地面斜拍/雾天图像) │ └── val/ # 653张JPEG图像(覆盖不同季节、光照条件) └── labels/ ├── train/ # YOLO格式txt标签(class_id x_center y_center width height,归一化) └── val/关键约束:
- 图像分辨率统一为1280×960(非原始尺寸),因Swin-T对输入尺寸敏感,需保证H/W被32整除(1280÷32=40, 960÷32=30)
- 标签质量三原则:
- 每个杆塔必须标注完整塔身(含基础、塔腿、横担),禁止只标横担;
- 绝缘子串单独标注为class_id=1(塔身为0),因二者材质反射特性差异大;
- 被遮挡区域用虚线框标注,但坐标仍按可见部分外接矩形计算。
运行_整理数据文件夹结构.py前需修改第12行:
# 修改此处为你的实际数据路径 src_img_dir = r"D:\power_tower_raw\images" # 原始图像路径 src_label_dir = r"D:\power_tower_raw\labels" # 原始标签路径 target_dir = r"./dataset" # 输出路径脚本会自动完成:
① 图像重采样(保持宽高比,短边缩放至960,长边按比例缩放后中心裁剪);
② 标签坐标同步变换(含浮点精度校验,误差>0.001则报错);
③ 生成dataset.yaml(含train/val路径、nc=2、names=['tower','insulator'])。
3.2 训练命令与超参配置详解
训练入口为train.py,核心命令如下:
python train.py \ --data dataset.yaml \ --cfg models/yolov7-swin.yaml \ --weights '' \ --batch-size 16 \ --epochs 150 \ --img 1280 960 \ --name yolov7-swin-power \ --device 0 \ --workers 4 \ --sync-bn \ --evolve参数说明:
--cfg models/yolov7-swin.yaml:指定Swin-T增强版配置,其中backbone段定义Swin-T结构,neck段启用Swin-FPN;--batch-size 16:需至少24GB显存(RTX 3090),若显存不足可降为8,但需将--workers同步减至2;--img 1280 960:必须与数据预处理尺寸严格一致,否则Swin-T窗口划分错位;--sync-bn:启用同步批归一化,解决多卡训练时BN统计量不一致问题;--evolve:启动超参进化,自动搜索学习率(lr0)、动量(momentum)、权重衰减(weight_decay)最优组合。
models/yolov7-swin.yaml关键配置节:
# Swin-T backbone配置 backbone: # [from, repeats, module, args] [[-1, 1, Conv, [32, 3, 1]], # 输入卷积 [-1, 1, SwinTransformer, [96, 4, [2, 2, 6, 2]]], # Swin-T-tiny: embed_dim=96, depths=[2,2,6,2] [-1, 1, Conv, [192, 3, 2]], # Stage2输出(H/8×W/8×192) [-1, 1, SwinTransformerBlock, [192, 2]], # Stage3输入 [-1, 1, Conv, [384, 3, 2]], # Stage3输出(H/16×W/16×384) ] neck: [[-1, 1, SPPF, [384, 384]], # Stage3输出先做SPPF [-1, 1, Conv, [256, 1, 1]], # 映射至P4 [-2, 1, Conv, [256, 1, 1]], # Stage2输出映射至P3 # 后续为PANet结构,已适配Swin特征 ]3.3 训练过程监控与收敛判断
训练日志中需重点关注三项指标:
| 指标 | 正常范围 | 异常征兆 | 应对措施 |
|---|---|---|---|
BoxLoss | 0.02~0.08 | >0.15持续5轮 | 检查标签坐标是否越界(x,y,w,h∈[0,1]) |
ObjLoss | 0.03~0.12 | <0.01且ClassLoss>0.2 | 存在类别不平衡,增加insulator类权重 |
Precision | ≥0.85 | 波动>0.1 | 关闭--evolve,固定学习率 |
验证集val_batch0_labels.jpg可视化结果(位于runs/train/yolov7-swin-power/val_batch0_labels.jpg)应呈现:
- 绿色框(塔身)紧密包裹塔基至横担顶部,无明显偏移;
- 红色框(绝缘子)精准覆盖瓷裙区域,不包含金属端部;
- 虚线框(遮挡)仅出现在树冠/云层覆盖区,且框内无其他物体。
若出现大量红色框漂移至塔身金属架,说明EIoU中宽高误差权重过高,需在utils/loss.py中将wh_loss系数从1.0调至0.6。
4. 模型部署与电力场景实战调优
4.1 ONNX导出与TensorRT加速
export.py支持一键导出ONNX并优化TensorRT引擎:
python export.py \ --weights runs/train/yolov7-swin-power/weights/best.pt \ --include onnx \ --img-size 1280 960 \ --batch-size 1 \ --simplify \ --opset 12 \ --trt关键参数解析:
--simplify:启用onnx-simplifier,消除冗余算子(如连续的Reshape→Transpose);--opset 12:ONNX版本需≥12,因Swin-T的torch.nn.functional.scaled_dot_product_attention在opset11中未定义;--trt:自动生成TensorRT引擎(best.engine),支持FP16精度(默认开启)。
生成的best.engine在Jetson Orin上实测:
| 输入尺寸 | FPS | 显存占用 | mAP@0.5 |
|---|---|---|---|
| 1280×960 | 24.3 | 1.8GB | 89.7% |
| 960×720 | 38.6 | 1.2GB | 87.2% |
注意:首次运行
--trt需编译TensorRT插件,耗时约8分钟。若报错Assertion failed: scales.is_weights(),需升级TensorRT至8.6.1+,因旧版本不支持Swin-T的动态缩放操作。
4.2 电力巡检视频流处理Pipeline
detect.py提供面向视频流的低延迟推理方案,核心逻辑在video_inference()函数:
def video_inference(source, weights, img_size=1280): # 初始化TRT引擎(避免每帧重复加载) engine = TRTInference(weights.replace('.pt', '.engine')) cap = cv2.VideoCapture(source) while cap.isOpened(): ret, frame = cap.read() if not ret: break # 预处理:保持宽高比缩放+中心裁剪(与训练一致) resized = letterbox(frame, img_size)[0] # letterbox函数在common.py中定义 # TRT推理(含NMS后处理) pred = engine.infer(resized) # 返回[x1,y1,x2,y2,conf,class_id] # 电力场景特有后处理 filtered_pred = filter_by_aspect_ratio(pred, min_ratio=0.1, max_ratio=5.0) # 剔除过扁/过长框 tower_boxes = [p for p in filtered_pred if p[5]==0] # 仅塔身框 if len(tower_boxes) > 0: # 计算塔身倾斜角(基于横担两端点连线) angle = calculate_tilt_angle(tower_boxes[0]) if abs(angle) > 15: # 倾斜超15度触发告警 send_alert("塔身倾斜", frame, angle) # 可视化叠加 draw_results(frame, pred) cv2.imshow('Power Tower Detection', frame) if cv2.waitKey(1) == ord('q'): break cap.release() cv2.destroyAllWindows()letterbox()函数(common.py第42行)确保预处理与训练完全一致:
def letterbox(img, new_shape=(1280, 960), color=(114, 114, 114)): shape = img.shape[:2] # original shape if isinstance(new_shape, int): new_shape = (new_shape, new_shape) r = min(new_shape[0] / shape[0], new_shape[1] / shape[1]) # ratio new_unpad = int(round(shape[1] * r)), int(round(shape[0] * r)) dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1] # wh padding dw /= 2 dh /= 2 if shape[::-1] != new_unpad: img = cv2.resize(img, new_unpad, interpolation=cv2.INTER_LINEAR) top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1)) left, right = int(round(dw - 0.1)), int(round(dw + 0.1)) img = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color) return img4.3 边缘设备部署技巧:内存与精度平衡
在Jetson Orin部署时,常遇显存不足导致cudaErrorMemoryAllocation。除降低--batch-size外,本项目提供三阶优化方案:
| 优化层级 | 操作 | 效果 | 风险 |
|---|---|---|---|
| L1:输入尺寸压缩 | 将--img 1280 960改为--img 960 720 | FPS↑58%,显存↓32% | mAP↓2.5%,对小塔身漏检率↑3.1% |
| L2:FP16量化 | 在export.py中添加--half参数 | 推理速度↑1.8倍,显存↓45% | 需确认TensorRT版本≥8.4,否则精度损失>5% |
| L3:Swin-T轻量化 | 修改models/yolov7-swin.yaml中depths=[2,2,6,2]为[1,1,2,1] | 参数量↓63%,FPS↑2.3倍 | mAP↓6.8%,仅适用于远距离粗检 |
实测推荐组合:L1+L2(960×720+FP16),在Orin上达成38.6 FPS且mAP保持87.2%,满足巡检车25km/h行驶时单帧处理时间<26ms的要求。若需更高精度,可启用L1+L2+动态分辨率:当检测到塔身置信度<0.7时,自动切回1280×960尺寸重检,该策略使综合mAP达88.9%,平均FPS仍维持31.2。
最后,验证模型鲁棒性的最简方法:将test_images/中的0ef73c2ce8964306b2a49c498e031465.png(雾天图像)和dab9e9bd21344201aaf1259bf72c4ccf.png(强光反光图像)放入detect.py的测试路径,观察是否仍能稳定输出塔身框。若出现大面积漏检,优先检查common.py中letterbox函数的padding颜色是否设为(114,114,114)——这是YOLOv7训练时的默认灰度值,与Swin-T的归一化参数对齐。
本文还有配套的精品资源,点击获取