简介:这份资源面向计算机视觉学习者与道路安全检测方向的开发者,提供一套基于YOLOv8实现路面坑洼检测的完整项目方案,涵盖从数据准备、模型训练到推理评估的全流程,适合具备一定Python与深度学习基础、希望上手实战目标检测的读者参考。压缩包共10个文件,约170.66MB,包含4个py脚本(训练、测试、验证与推理)、2个pt模型权重、1个依赖清单txt、1段mp4演示视频、1份md项目说明及1张png效果图,结构清晰便于按模块查阅。目前已有423人学习下载。项目说明中详细交代了数据集标注、训练参数设置与mAP等评估指标,配合训练好的权重可直接复现坑洼检测效果,演示视频直观呈现推理过程,读者能借此理解YOLOv8在真实道路场景中的落地思路,也可迁移至交通标志识别、路面破损评估等相近任务。
1. 路面坑洼检测为什么值得用 YOLOv8 重做一遍
市政巡检、园区道路养护、自动驾驶感知冗余,这几个场景里「路面坑洼检测」都是绕不开的刚需。传统做法靠人工巡查或者传统图像处理阈值分割,白天光照一变、阴影一压,误报率立刻飙升。这两年 YOLOv8 成了目标检测落地的主力军,原因很直接:anchor-free 头、C2f 结构、解耦检测头,加上 Ultralytics 那套训练推理一条龙的工程封装,让一个 Python 工程师从标注到出模型的时间压缩到几天。这个项目标题里的「python 源码 + 项目说明 + 模型」组合,本质就是一套可复现的坑洼检测落地包:数据集怎么标、YOLOv8 怎么训、模型怎么导出、推理怎么接业务。适合两类人——想拿它做课程设计或毕设的学生,以及要给巡检车、边缘盒子加检测能力的嵌入式/算法工程师。下面我按自己实际跑通的顺序,把选型理由、训练参数、踩过的坑和部署技巧讲清楚,你照着能复现,也能判断这套方案值不值得投入。
2. 从数据集到 YOLOv8 训练:坑洼检测的最小可跑通路径
2.1 为什么坑洼检测选 YOLOv8 而不是 Faster R-CNN 或分割模型
先讲选型,不然后面调参没有依据。坑洼检测的难点有三个:目标尺度差异大(细裂缝到半米大坑)、边缘模糊(坑洼和阴影、水渍、修补痕迹容易混)、实时性要求(巡检车视频流至少 15 FPS)。Faster R-CNN 精度够但两阶段推理慢,边缘设备上基本跑不动;语义分割(U-Net 那类)能出像素级轮廓,但标注成本高一个量级,而且业务上多数只需要「有没有坑、在哪、多大」的框。YOLOv8 的 anchor-free 设计对小目标和密集目标更友好,n/s/m 三个尺寸可以按算力选,导出 ONNX 或 TensorRT 后 RK3588、Jetson 这类板子都能吃。我一般会先跑 YOLOv8n 验证流程通不通,再换 YOLOv8s 或 m 提精度。这里有个反直觉的点:坑洼检测里模型大不一定好,因为坑洼纹理特征弱,大模型容易过拟合到背景纹理(比如沥青颗粒),小模型加好数据反而更稳。
2.2 数据集标注:labelme 转 YOLO 格式的脚本与四个边界坑
YOLOv8 训练要的是 YOLO 格式标签:每张图一个同名 txt,每行class_id cx cy w h,坐标全部归一化到 0~1。很多人手上是 labelme 标的 json,得转。下面这个脚本我用了很多次,处理了中文路径、空标注、坐标越界、图片尺寸不一致四个坑。
import json, os, glob from PIL import Image def labelme_to_yolo(json_dir, out_dir, class_map): os.makedirs(out_dir, exist_ok=True) for jf in glob.glob(os.path.join(json_dir, "*.json")): with open(jf, "r", encoding="utf-8") as f: data = json.load(f) # 坑1:图片尺寸以 json 里为准,别用 PIL 重新读,避免 EXIF 旋转导致错位 img_w = data["imageWidth"] img_h = data["imageHeight"] lines = [] for shape in data["shapes"]: label = shape["label"] if label not in class_map: # 坑2:未登记类别直接跳过,别硬塞 continue pts = shape["points"] xs = [p[0] for p in pts] ys = [p[1] for p in pts] # 坑3:坐标裁剪到图内,标注手抖画出界会训崩 x1, x2 = max(0, min(xs)), min(img_w, max(xs)) y1, y2 = max(0, min(ys)), min(img_h, max(ys)) if x2 - x1 < 2 or y2 - y1 < 2: # 坑4:过滤极小框 continue cx = (x1 + x2) / 2 / img_w cy = (y1 + y2) / 2 / img_h w = (x2 - x1) / img_w h = (y2 - y1) / img_h lines.append(f"{class_map[label]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}") if not lines: # 空标注图不生成 txt,避免训练报错 continue name = os.path.splitext(os.path.basename(jf))[0] with open(os.path.join(out_dir, name + ".txt"), "w") as f: f.write("\n".join(lines)) labelme_to_yolo("./labels_json", "./labels_yolo", {"pothole": 0})逻辑说明:class_map把中文或英文标签映射成从 0 开始的整数,YOLOv8 的data.yaml里names顺序必须和这里一致,否则类别全错。参数上cx cy w h保留 6 位小数足够,归一化后不要四舍五入到 2 位,小目标会丢精度。转换完务必抽查几张:用cv2把框画回原图看一眼,比任何校验脚本都直观。
2.3 data.yaml 与目录结构:训练前必须对齐的三件事
YOLOv8 对目录结构有约定,常见做法是:
dataset/ images/train/ images/val/ labels/train/ labels/val/data.yaml写:
path: /home/user/dataset train: images/train val: images/val nc: 1 names: ["pothole"]三件必须对齐的事:一是nc和names长度一致;二是 images 和 labels 的文件名(不含后缀)必须一一对应,缺一个 txt 训练时会被当负样本;三是path用绝对路径最稳,相对路径在不同工作目录下跑会找不到。我见过最常见的翻车就是 labels 目录里混进了classes.txt这种非标签文件,训练直接报解析错误。
2.4 训练命令与关键参数:从 YOLOv8n 起步的完整配置
环境上,Ubuntu 20.04 或 Windows 都行,CPU 版本也能跑通流程,只是慢。装依赖:
pip install ultralytics # 验证环境 yolo checks训练命令:
yolo detect train \ model=yolov8n.pt \ data=dataset/data.yaml \ epochs=150 \ imgsz=640 \ batch=16 \ lr0=0.01 \ patience=30 \ device=0 \ project=runs/pothole \ name=v8n_exp1参数说明:imgsz=640是精度和速度的平衡点,坑洼目标偏小可以试 800,但显存翻倍;batch=16在 8G 显存上跑 YOLOv8n 基本够,爆显存就降到 8;lr0=0.01是 Ultralytics 默认,小数据集(几百张)建议降到 0.005 防震荡;patience=30表示 30 轮没提升就早停,省时间。device=0指定第一块 GPU,CPU 训练去掉这个参数即可。训练完权重在runs/pothole/v8n_exp1/weights/best.pt。想看损失曲线,Ultralytics 会自动生成results.png,也可以自己用results.csv画,重点看train/box_loss和val/box_loss是否背离——背离就是过拟合,该加数据或加增强。
3. 推理、评估与导出:让模型真正跑在业务里
3.1 用 Python 调 best.pt 做单图与视频推理
训练完先别急着部署,用 Python 验证一遍推理链路:
from ultralytics import YOLO model = YOLO("runs/pothole/v8n_exp1/weights/best.pt") # 单图推理,conf 阈值按业务调,坑洼建议 0.35 起步 results = model.predict("test.jpg", conf=0.35, iou=0.5, imgsz=640) for r in results: for box in r.boxes: cls = int(box.cls) conf = float(box.conf) xyxy = box.xyxy.tolist()[0] print(f"类别{cls} 置信度{conf:.3f} 框{xyxy}") # 视频流推理,stream=True 省内存 for r in model.predict("road.mp4", stream=True, conf=0.35): r.save("out.mp4") # 或接自己的业务逻辑逻辑说明:conf是置信度阈值,坑洼检测宁可漏检也别误报太多,业务上 0.35~0.5 之间调;iou控制 NMS 合并,密集小坑可以调到 0.6 减少误合并。stream=True对长视频很关键,不加会把所有帧结果堆内存里。参数imgsz推理时要和训练一致,否则精度掉得莫名其妙。
3.2 评估指标怎么看:mAP50 高不代表能用
yolo detect val model=best.pt data=dataset/data.yaml会输出 mAP50、mAP50-95、precision、recall。血泪经验:mAP50 到 0.85 不代表业务可用,一定要看 recall。坑洼漏检的代价远大于误报,如果 recall 低于 0.7,优先加正样本、调低 conf、或者用copy_paste增强。另外看混淆矩阵(confusion_matrix.png),如果坑洼大量被分到背景,说明标注里负样本太多或目标太小。评估集一定要和训练集来源不同(不同路段、不同天气),否则指标虚高,上线就翻车。
3.3 导出 ONNX 与 RK3588 部署的注意点
边缘部署常见路线是导出 ONNX 再转 RKNN 或 TensorRT:
yolo export model=best.pt format=onnx opset=12 imgsz=640 simplify=Trueopset=12兼容性最好,simplify=True会做图优化。转到 RK3588 时注意:RKNN 对动态 shape 支持有限,导出时固定imgsz;量化用 INT8 需要准备校准集(从训练集抽 100~300 张),校准集分布要覆盖实际场景,否则量化后小目标精度断崖。GTX1660Ti 这类桌面卡跑 YOLOv8n 推理 640 大概几毫秒一帧,板端 NPU 上量级也够实时。低显存设备上跑训练,把batch降到 4、开amp=True混合精度,能省不少显存。
4. 坑洼检测落地避坑:五条踩出来的经验
4.1 现象:训练 loss 正常但验证 mAP 一直是 0
原因:data.yaml里names顺序和标注 class_id 对不上,或者 val 的 labels 路径写错导致全是负样本。解决:先跑yolo detect val看有没有预测框输出,再抽查 val 的一张图手动核对标签,路径用绝对路径重写一遍。
4.2 现象:模型把阴影、水渍全框成坑洼
原因:训练集里阴影样本被误标成正样本,或者负样本(无坑图)太少。解决:清洗标注,把阴影、修补痕迹单独作为困难负样本加入训练集(空 txt),比例控制在正样本的 20%~30%。
4.3 现象:小坑检测不到,大坑框不准
原因:imgsz=640下小目标下采样后只剩几个像素。解决:提高imgsz到 800 或 960,或开mosaic=1.0增强,也可以在数据里对小目标做复制粘贴增强。大坑框不准通常是标注框太松,重新标紧一点。
4.4 现象:训练到一半显存爆了
原因:batch太大或imgsz太高,也可能是 dataloader 的workers开太多。解决:batch减半,workers=4,开amp=True,还不行就换 YOLOv8n。
4.5 现象:导出 ONNX 后推理结果和 PyTorch 不一致
原因:预处理(归一化、letterbox)没对齐,或opset版本问题。解决:用 Ultralytics 自带的predict对比 ONNX Runtime 输出,确认输入是 0~1 归一化、RGB、letterbox 填充;opset换 11 或 12 试。
5. 把坑洼检测做成可迭代系统的三个进阶技巧
第一个技巧是主动学习闭环。巡检车每天产生大量新图,别全标,先用当前模型推理,把置信度在 0.3~0.6 之间的「模糊样本」挑出来人工复核,这批样本信息量最大,标 200 张的效果往往超过随机标 1000 张。我一般写个脚本按 conf 分桶,优先送中间桶去标注。
第二个技巧是滑动窗口 + 全图推理的取舍。高分辨率巡检图(4000×3000)直接缩到 640 会丢小坑,常见做法是切 640×640 的滑动窗口带重叠推理再合并,重叠率 0.2 左右。代价是推理次数翻几倍,板端要算好帧率预算。合并时用 NMS 或 WBF 去重,WBF 对重叠框融合更稳。
第三个技巧是版本化你的数据和模型。每次改标注、改增强都记一个版本号,模型权重、data.yaml、训练命令一起存档。我吃过亏:调了一版效果变好,回头想复现却找不到当时的数据集版本,只能重训。用 git-lfs 或简单的目录命名v1_20240101都行,关键是别偷懒。
验证方法上,除了 mAP,我习惯做一个「业务回归集」:固定 50 张覆盖晴天、雨天、夜间、阴影的图,每次出新模型都跑一遍,人工看漏检和误报,比指标更贴近真实。这套流程跑顺之后,换检测目标(裂缝、井盖缺失)基本只改数据和类别名,框架不用动。
我自己现在的习惯是:任何检测项目,先花半天把数据管道和评估集搭扎实,再动模型。模型是玄学,数据是科学。希望帮到你。
本文还有配套的精品资源,点击获取