简介这份资源面向计算机视觉与智能交通方向的学习者与研究者聚焦低分辨率或低质量行车记录仪图像下的坑洼检测难题。内容以一篇完整英文论文PDF呈现提出先用ESRGAN对低质图像做超分辨率增强再交由YOLOv7完成目标检测并与仅用YOLOv7的基线方案对比速度与精度涵盖CNN、迁移学习、多尺度预测等知识点适合具备一定深度学习基础、希望了解超分与检测联合方案的读者。资源包共1个文件为1个PDF文档整体约1.35MB轻量便于随时查阅。目前已有254人学习读者可从中获取完整的算法流程、实验设计与结果分析思路理解超分预处理如何提升小目标检测表现并借鉴其成本效益与鲁棒性评估方法为道路病害检测或类似低质图像识别任务提供可复用的方案参考。1. 低清行车记录仪也能跑坑洼检测YOLOv7 加 ESRGAN 到底值不值得上路上跑的车载摄像头十台有八台是 720P 甚至更低的模组白天勉强能看一到夜间或雨雪天画面糊得连车道线都费劲更别说分辨路面上一块巴掌大的坑洼。很多做道路巡检的团队第一反应是换硬件上 4K 工业相机结果预算一算直接劝退。这篇论文给的思路反着来不换相机先用 ESRGAN 把低分辨率帧超分到高分辨率再喂给 YOLOv7 做检测用软件补硬件的短板。作者在 Stellenbosch 大学公开的坑洼数据集上做了对照实验低清图像经 ESRGAN 放大后再检测mAP 和召回率都比直接检测低清图有明显提升速度虽然多了一步超分但整体仍在可接受范围。这套方案适合谁做车载 ADAS 预研、道路养护巡检、边缘盒子部署的从业者尤其是手里只有低成本摄像头、又不想推翻现有采集链路的团队。下面我把这份资源拆开从数据组织、ESRGAN 超分、YOLOv7 训练到部署踩坑一步步走一遍。2. 数据集与预处理1784 张图的目录结构和 11:3:1 划分2.1 数据集从哪来、长什么样论文用的数据集来自 OpenCV 官网免费下载原始出处是 Stellenbosch 大学电子系整理的坑洼图像集。整个包解压后是两个顶层文件夹images和labels各自下面再分Training、Testing、Validation三个子目录。images里放的是行车记录仪拍的路面图labels里放的是同名.txt文件每行格式是class_id x_center y_center width height坐标全部归一化到 0 到 1 之间这是 YOLO 系列的标准标注格式。图像总数 1784 张划分比例是 11:3:1——训练集 1265 张验证集 401 张测试集 118 张。原始图像尺寸不统一作者统一 resize 到 1100×800然后再降采样到 640×360 作为低清输入用来模拟低分辨率摄像头拍出来的画面。这里有个细节值得注意他们没有对 800p 的图做上采样原因是显存扛不住训练大网络时 batch size 会被压得很小收敛慢。这个取舍在实际项目里很常见后面避坑章节会展开。2.2 目录组织与 YOLO 格式转换拿到数据集后第一件事是把目录结构整理成 YOLOv7 能直接吃的格式。YOLOv7 官方仓库要求data目录下有一个.yaml文件描述路径和类别图像和标签按 split 分开放。常见做法是建一个pothole_dataset根目录结构如下pothole_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── pothole.yamlpothole.yaml内容# 坑洼检测数据集配置 train: ./pothole_dataset/images/train val: ./pothole_dataset/images/val test: ./pothole_dataset/images/test # 类别数坑洼只有一类 nc: 1 names: [pothole]如果原始标签是 VOC 的 XML 格式需要转成 YOLO 的 txt。转换脚本核心逻辑import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_path, img_w, img_h, out_path): tree ET.parse(xml_path) root tree.getroot() lines [] for obj in root.iter(object): cls_name obj.find(name).text # 只保留 pothole 类其余跳过 if cls_name ! pothole: continue bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 归一化中心点和宽高 x_c (xmin xmax) / 2.0 / img_w y_c (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f0 {x_c:.6f} {y_c:.6f} {w:.6f} {h:.6f}) with open(out_path, w) as f: f.write(\n.join(lines))这段脚本的关键参数是img_w和img_h必须和实际图像尺寸一致否则归一化坐标会错位。转换完建议随机抽 20 张用cv2.rectangle画框验证一遍肉眼确认框的位置对得上再开始训练。我一般会写一个visualize.py把标签画回图上存到debug/目录翻车过几次之后这个习惯就固定下来了。2.3 低清模拟与数据增强论文的核心变量是图像分辨率所以预处理阶段要显式构造两组数据一组是 640×360 的低清图一组是 1100×800 的高清图。低清图直接 resize 即可高清图作为 baseline 对照。数据增强方面YOLOv7 自带 mosaic、mixup、随机缩放但坑洼检测有个特殊性——坑洼是贴地目标垂直翻转会产生不真实的场景建议在hyp.scratch.p5.yaml里把flipud设为 0.0fliplr保持 0.5。另外 HSV 增强里的hsv_v可以适当调高到 0.5模拟不同光照下的路面反光这对夜间和阴天场景的泛化有帮助。3. ESRGAN 超分模块RRDB 块与相对判别器怎么落地3.1 为什么选 ESRGAN 而不是双三次插值双三次插值是最省事的放大方案OpenCV 一行cv2.resize就完事但它本质是像素值加权平均放大后边缘发虚、纹理丢失坑洼的边界会糊成一团YOLOv7 的卷积核很难从中提取到有效梯度。ESRGAN 走的是生成对抗网络路线生成器负责重建高频细节判别器负责判断图像是真实高清还是生成出来的两者对抗训练最终生成器能输出纹理更锐利、边缘更清晰的结果。ESRGAN 相比前代 SRGAN 有两处关键改动。第一去掉了所有 Batch Normalization 层换成 Residual-in-Residual Dense BlockRRDB。BN 层在超分任务里会引入伪影去掉之后训练更稳定细节保留更好。RRDB 把多级残差和密集连接揉在一个块里梯度流动更顺畅。第二判别器从标准 GAN 换成 Relativistic GAN判别器不再判断“这张图是真的还是假的”而是判断“这张图比另一张图更真实吗”这个相对判断让生成器能学到更细的纹理差异。3.2 超分推理脚本与参数实际用的时候不需要从头训练 ESRGAN直接拿官方在 DIV2K 等数据集上预训练的权重做推理即可。常见做法是用Real-ESRGAN仓库的inference_realesrgan.py或者自己写一个轻量推理脚本import torch import cv2 import numpy as np from basicsr.archs.rrdbnet_arch import RRDBNet from realesrgan import RealESRGANer # 初始化 RRDB 网络num_block23 是 ESRGAN 标准配置 model RRDBNet(num_in_ch3, num_out_ch3, num_feat64, num_block23, num_grow_ch32, scale4) # 加载预训练权重scale4 表示放大 4 倍 upsampler RealESRGANer( scale4, model_pathweights/RealESRGAN_x4plus.pth, modelmodel, tile400, # 分块大小显存不够就调小 tile_pad10, # 块间重叠像素防止拼接缝 pre_pad0, halfTrue # 半精度推理省显存 ) img cv2.imread(low_res_frame.jpg, cv2.IMREAD_COLOR) # 执行超分返回 BGR 图像 output, _ upsampler.enhance(img, outscale4) cv2.imwrite(high_res_frame.jpg, output)参数说明scale4是放大倍数如果只需要 2 倍可以改成 2但权重文件要对应tile400控制分块推理的块大小显存 8G 以下建议设 200 到 300否则容易 OOMhalfTrue开启 FP16速度能快 30% 左右但部分老卡不支持报错就关掉。推理完的图像尺寸是原来的 4 倍640×360 进去2560×1440 出来再 resize 到 YOLOv7 的输入尺寸 640×640 做检测。3.3 超分质量对检测的影响论文里的对照实验设计得很清楚同一批低清图一组直接送 YOLOv7另一组先过 ESRGAN 再送 YOLOv7比较 mAP0.5 和召回率。结论是超分后的检测指标明显优于直接检测低清图接近高清图 baseline 的水平。但这里有个容易被忽略的点——ESRGAN 是通用超分模型训练数据以自然场景为主对路面纹理的针对性不强。如果项目允许用坑洼数据集微调 ESRGAN 的生成器或者至少用路面图像做一次 domain adaptation效果会更好。我一般会先跑通用权重看 baseline如果 mAP 提升不到 3 个点再考虑微调。4. YOLOv7 训练与调参三个版本怎么选、超参怎么改4.1 YOLOv7、YOLOv7x、YOLOv7-tiny 的选型依据论文用了三个 YOLOv7 变体做对比参数差异直接决定部署场景模型卷积层数参数量适用场景YOLOv77536.9M边缘云协同精度优先YOLOv7x10571.3M服务器端追求最高精度YOLOv7-tiny246.2M边缘设备本地推理速度优先选型逻辑很直白如果跑在 Jetson Nano 或树莓派这类边缘盒子上YOLOv7-tiny 是唯一现实的选择6.2M 参数、24 层卷积推理延迟能压到几十毫秒如果跑在带 GPU 的工控机或边缘服务器上YOLOv7 标准版是甜点区精度和速度平衡得最好YOLOv7x 适合离线批量处理比如巡检车回传数据后统一分析不要求实时。我一般会先用 tiny 版跑通全流程确认数据管道没问题再换标准版调精度。4.2 训练命令与关键超参YOLOv7 官方仓库的训练入口是train.py一条典型命令python train.py \ --weights yolov7.pt \ # 预训练权重COCO 上训过的 --cfg cfg/training/yolov7.yaml \ --data pothole_dataset/pothole.yaml \ --hyp data/hyp.scratch.p5.yaml \ --epochs 300 \ --batch-size 16 \ --img-size 640 640 \ --device 0 \ --workers 8 \ --name pothole_yolov7参数逐个说--weights指定预训练权重YOLOv7 在 COCO 上训过迁移到坑洼检测收敛快很多--batch-size受显存限制8G 显存跑 640 尺寸大概能到 16不够就降到 8 并开--accumulate梯度累积--img-size设 640×640和超分后的 resize 目标一致--hyp是超参文件坑洼检测建议把lr0从 0.01 降到 0.005因为数据集只有一千多张学习率太大会震荡。训练过程中重点盯三个指标box_loss、obj_loss、mAP0.5。box_loss下降但mAP不涨通常是过拟合早停或加数据增强obj_loss震荡厉害检查标签里有没有空文件或坐标越界。我习惯每 50 个 epoch 存一次权重方便回滚到最佳 checkpoint。4.3 评估指标与 IoU 阈值论文用的评估指标是 mAP、precision、recall、F1外加 IoU 和混淆矩阵。IoU 的计算是预测框和真实框的交集面积除以并集面积阈值一般设 0.5即 IoU 大于 0.5 才算检测正确。坑洼检测有个特殊情况——坑洼边界本身模糊标注时不同人画的框可能差十几个像素所以 IoU 阈值可以适当放宽到 0.45否则 mAP 会被标注噪声拉低。验证集评估命令python test.py \ --weights runs/train/pothole_yolov7/weights/best.pt \ --data pothole_dataset/pothole.yaml \ --img-size 640 \ --conf-thres 0.25 \ --iou-thres 0.45 \ --task val--conf-thres是置信度阈值低于这个值的检测框直接丢弃0.25 是常用起点误检多就调高漏检多就调低--iou-thres是 NMS 的 IoU 阈值控制重叠框的合并力度。5. 避坑与排查显存、标签、超分伪影的五个血泪教训5.1 显存 OOM现象是训练启动就崩原因是 800p 图像加默认 batch现象训练脚本刚跑几秒就报CUDA out of memorynvidia-smi 显示显存占满。原因论文里提到他们放弃对 800p 图像上采样就是因为显存瓶颈。YOLOv7 在 640 尺寸下 batch16 大概吃 6 到 8G 显存如果输入尺寸设成 1100×800显存需求翻倍不止。解决把--img-size降到 640--batch-size降到 8 或 4同时开--accumulate 2做梯度累积等效 batch 不变但显存峰值降下来。另外 ESRGAN 推理时tile参数也要调小400 在 8G 卡上可能不够降到 200。5.2 标签坐标越界现象是训练 loss 变 NaN原因是归一化算错现象训练几个 epoch 后 loss 突然变成 NaN或者 mAP 一直是 0。原因标签 txt 里的坐标超出 0 到 1 范围常见于 VOC 转 YOLO 时图像尺寸填错或者标注时框画到了图像外面。解决写一个校验脚本遍历所有标签文件检查每行后四个数是否在 [0,1] 区间超出就打印文件名和行号。我一般会在数据加载前强制跑一遍校验不过这一步就等着训练中途崩吧。5.3 ESRGAN 伪影现象是超分后出现网格状纹理原因是 tile 拼接缝现象超分后的图像放大看有规则的网格纹路或者边缘出现不自然的锐化。原因tile分块推理时块与块之间的拼接没有足够重叠tile_pad设太小。解决把tile_pad从默认 10 调到 20 或 32让相邻块有更多重叠像素拼接时做羽化过渡。如果伪影还在关掉halfTrue用 FP32 推理半精度有时会引入数值误差。5.4 类别不平衡现象是漏检多、recall 低原因是负样本太多现象precision 还行但 recall 很低很多坑洼没检出来。原因行车记录仪画面里坑洼只占很小一块背景负样本远多于正样本模型倾向于预测背景。解决在hyp文件里调高obj_loss的权重或者用 focal loss 替代 BCE。另一个办法是过采样含坑洼的帧把训练集里正样本比例提上去。我一般会先统计每张图的坑洼数量如果平均不到 1 个就考虑过采样。5.5 超分与检测的尺寸不匹配现象是检测框偏移原因是 resize 比例不一致现象超分后检测框的位置整体偏移或框变大变小。原因ESRGAN 输出尺寸是输入的 4 倍比如 640×360 变 2560×1440然后 resize 到 640×640 时宽高比变了图像被拉伸框坐标跟着变形。解决resize 时保持宽高比用 letterbox 填充灰边YOLOv7 的datasets.py里自带 letterbox 函数确保推理时的预处理和训练时一致。这个坑很隐蔽因为框看起来“差不多对”但 IoU 就是上不去。6. 进阶技巧用 PNW 视频做跨域验证与 TensorRT 加速论文里除了 Stellenbosch 数据集还用了 PNW 数据集做对比测试。PNW 是一段 YouTube 上的高速公路行车视频拍摄于冬季路面有雪融和雨水侵蚀造成的坑洼车速 45 到 90 km/h帧尺寸 1280×720。这个数据集的价值在于跨域验证——Stellenbosch 是静态图像PNW 是视频流能检验模型在真实连续帧上的稳定性。我一般会把 PNW 视频抽帧成 1fps 的图片序列跑一遍推理统计连续帧之间的检测一致性。如果相邻帧的框跳变厉害说明模型对运动模糊和光照变化不够鲁棒需要补这类数据做微调。部署阶段如果目标是边缘设备TensorRT 加速是绕不开的。YOLOv7 官方仓库有export.py支持导出 ONNX再用trtexec转 TensorRT engine# 导出 ONNX python export.py --weights best.pt --grid --end2end --simplify \ --topk-all 100 --iou-thres 0.45 --conf-thres 0.25 --img-size 640 640 # ONNX 转 TensorRTFP16 精度 trtexec --onnxbest.onnx --saveEnginebest.engine \ --fp16 --workspace4096 --minShapesimages:1x3x640x640 \ --optShapesimages:1x3x640x640 --maxShapesimages:1x3x640x640--fp16开启半精度速度能提升 1.5 到 2 倍--workspace是显存工作空间4096MB 够用--minShapes到--maxShapes定义动态 batch如果只跑单帧推理三个都设 1x3x640x640 即可。ESRGAN 部分也可以转 TensorRT但 RRDB 结构里有密集连接导出时容易遇到不支持的算子建议先用 ONNX Runtime 跑确认精度无损再转 TRT。还有一个容易被忽视的技巧ESRGAN 和 YOLOv7 可以流水线并行。超分和检测是串行的但视频流里帧与帧独立可以用两个线程一个线程做超分一个线程做检测中间用队列缓冲。这样整体吞吐能提升接近一倍代价是延迟增加一帧。对于巡检场景延迟不敏感吞吐更重要这个优化很划算。从那以后我每次做低清图像检测项目都强制先跑一遍“低清直检 vs 超分后检测”的对照实验用数据决定要不要上超分模块而不是凭感觉堆模型。希望帮到你。本文还有配套的精品资源点击获取