YOLOv8路面坑洼检测实战:从训练到推理的完整项目解析
简介这份资源面向计算机视觉学习者与道路安全检测方向的开发者提供一套基于YOLOv8实现路面坑洼识别的完整Python项目可用于课程设计、毕业设计或算法复现练习。压缩包共10个文件约170.66MB包含4个py脚本训练、测试、验证与推理、2个pt权重文件、1个mp4检测演示视频、1个png效果图以及requirements.txt依赖清单和README.md项目说明覆盖从数据准备、模型训练到推理评估的完整流程。项目说明中涉及数据标注、特征提取、非极大值抑制与mAP评估等关键环节权重文件可直接加载用于坑洼检测演示视频便于直观核对检测效果。目前已有423人学习下载适合希望快速上手YOLOv8目标检测实战、理解道路病害识别思路的读者参考借鉴。1. 路面坑洼检测为什么值得单独拆一个 YOLOv8 项目市政巡检、自动驾驶感知、道路养护这几类场景里坑洼检测一直是个高频刚需。传统做法靠人工巡检或者简单的阈值分割遇到光照变化、阴影、水渍就翻车。这个项目用 YOLOv8 做路面坑洼检测把检测、训练、推理、评估整条链路都打包好了拿到手就能跑通。压缩包里包含train.py、predict.py、val.py、test.py四个核心脚本一份best.pt训练好的权重还有requirements.txt和README.md。适合想快速验证 YOLOv8 在自定义数据集上落地效果的人也适合拿它当模板改造成其他缺陷检测任务。下面按「资源是什么 → 怎么用 → 坑在哪」的顺序拆开讲。2. 拆包看结构YOLOv8 坑洼检测项目的文件分工与依赖2.1 压缩包里每个文件到底干什么拿到压缩包先别急着跑花两分钟把文件清单过一遍后面排错能省一半时间。这个项目的文件结构不算复杂但每个文件都有明确职责搞混了容易在路径上栽跟头。文件/目录作用是否必须train.py训练入口读取数据集配置并启动 YOLOv8 训练训练时必需predict.py推理脚本加载权重对单张图或视频做检测推理时必需val.py验证脚本在验证集上算 mAP、precision、recall评估时必需test.py测试脚本通常用于跑单张图看效果可选best.pt训练好的权重文件直接可用于推理推理时必需requirements.txtPython 依赖清单必需README.md项目说明含数据集格式和命令示例建议先读tested.mp4测试视频用来验证推理效果可选Pothole Detection using python and yolov8.png效果展示图可选best.pt是这个项目最值钱的部分。它是在坑洼数据集上训练收敛后的权重直接拿来做推理就能出结果。但要注意这个权重只对「坑洼」这一类目标有效换成裂缝、车辙就得重新训练。train.py和predict.py是两条独立链路训练和推理互不依赖但推理依赖训练产出的权重。2.2 环境依赖与版本对齐requirements.txt里通常列的是ultralytics、opencv-python、torch、torchvision、numpy、Pillow这几个。YOLOv8 的官方实现封装在ultralytics包里版本差异会直接影响 API 调用方式。常见做法是锁定ultralytics8.0.x这个区间太新的版本可能改了默认参数名。# 创建虚拟环境避免污染全局 Python python -m venv pothole_env source pothole_env/bin/activate # Windows 用 pothole_env\Scripts\activate # 安装依赖建议先装 torch 再装 ultralytics pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu pip install ultralytics opencv-python numpy Pillow上面这段命令里--index-url指定了 CPU 版本的 torch 源如果你有 NVIDIA 显卡并且装了 CUDA把cpu换成对应的cu118或cu121即可。ultralytics会自动拉取匹配的依赖但 torch 建议手动先装避免版本冲突。装完之后用python -c import ultralytics; print(ultralytics.__version__)确认一下版本号记下来后面出问题好对照。提示如果你在 Ubuntu 20.04 上搭环境系统自带的 Python 版本可能是 3.8而ultralytics较新版本要求 3.9。先python --version看一眼不够就装个 3.10 的 conda 环境别硬扛。3. 训练自己的坑洼数据集标注格式、参数配置与启动命令3.1 数据集目录结构与 YOLO 标注格式YOLOv8 对数据集目录有固定要求不是随便扔一堆图片就行。标准结构长这样dataset/ ├── images/ │ ├── train/ │ │ ├── 001.jpg │ │ └── ... │ └── val/ │ ├── 101.jpg │ └── ... ├── labels/ │ ├── train/ │ │ ├── 001.txt │ │ └── ... │ └── val/ │ ├── 101.txt │ └── ... └── data.yaml图片和标签文件名必须一一对应001.jpg对应001.txt。标签文件里每行是一个目标格式为class_id x_center y_center width height全部归一化到 0~1 之间。坑洼检测通常只有一类所以class_id恒为 0。data.yaml是数据集配置文件内容如下path: ./dataset train: images/train val: images/val nc: 1 names: [pothole]nc是类别数坑洼检测就是 1。names是类别名列表顺序要和标注时的class_id对应。如果你用 Labelme 标注它默认输出 JSON 格式需要转成 YOLO 的 txt 格式。常见做法是写个转换脚本把 JSON 里的多边形或矩形框转成归一化坐标。import json import os from PIL import Image def labelme_to_yolo(json_path, output_dir): with open(json_path, r, encodingutf-8) as f: data json.load(f) img_w data[imageWidth] img_h data[imageHeight] lines [] for shape in data[shapes]: if shape[label] ! pothole: continue points shape[points] xs [p[0] for p in points] ys [p[1] for p in points] x_center (min(xs) max(xs)) / 2 / img_w y_center (min(ys) max(ys)) / 2 / img_h width (max(xs) - min(xs)) / img_w height (max(ys) - min(ys)) / img_h lines.append(f0 {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) base os.path.splitext(os.path.basename(json_path))[0] with open(os.path.join(output_dir, base .txt), w) as f: f.write(\n.join(lines))这段脚本读取 Labelme 的 JSON提取pothole类别的边界框转成归一化坐标写入 txt。x_center和y_center是框中心点坐标除以图像宽高width和height是框的宽高除以图像宽高。转换完记得抽查几个 txt确认数值都在 0~1 之间否则训练时 loss 会直接炸掉。3.2 train.py 的关键参数怎么设train.py的核心是调用ultralytics的YOLO类。典型写法from ultralytics import YOLO model YOLO(yolov8n.pt) # 从预训练权重开始 model.train( datadata.yaml, epochs100, imgsz640, batch16, lr00.01, patience20, device0, projectruns/train, namepothole_v8n )yolov8n.pt是 nano 版本的预训练权重参数量最小适合快速验证。如果显存够可以换成yolov8s.pt或yolov8m.pt精度会高一些但速度慢。epochs100是训练轮数坑洼数据集一般 50~100 轮就能收敛。imgsz640是输入分辨率路面图像如果坑洼目标很小可以提到 1280但显存占用会翻倍。batch16根据显存调8G 显存跑yolov8n加 640 分辨率16 基本能稳住。patience20是早停耐心值20 轮验证集指标不涨就停省时间。device0指定第一块 GPUCPU 训练就写devicecpu。训练启动后runs/train/pothole_v8n/目录下会生成weights/、results.csv、confusion_matrix.png等文件。weights/best.pt是验证集上表现最好的权重last.pt是最后一轮的。优先用best.pt做推理。3.3 训练过程监控与损失曲线训练时终端会实时打印每轮的 box_loss、cls_loss、dfl_loss 和 mAP。box_loss 是边界框回归损失cls_loss 是分类损失dfl_loss 是分布焦点损失。正常情况下三个 loss 都应该是下降趋势如果某个 loss 震荡或者反弹大概率是学习率太大或者标注有问题。results.csv里记录了每轮的详细指标可以用 pandas 画曲线import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/train/pothole_v8n/results.csv) df.columns df.columns.str.strip() plt.plot(df[epoch], df[train/box_loss], labelbox_loss) plt.plot(df[epoch], df[train/cls_loss], labelcls_loss) plt.plot(df[epoch], df[metrics/mAP50(B)], labelmAP50) plt.legend() plt.savefig(training_curve.png)这段代码把训练损失和 mAP 画在一张图上方便判断是否过拟合。如果 mAP50 在 80 轮之后还在涨说明可以再加轮数如果 train loss 降但 val loss 涨就是过拟合了得加数据增强或者减模型复杂度。4. 推理与验证predict.py 和 val.py 的实操细节4.1 predict.py 跑单张图和视频推理脚本的核心就几行from ultralytics import YOLO model YOLO(best.pt) results model.predict( sourcetest_image.jpg, conf0.25, iou0.45, saveTrue, projectruns/detect, namepothole_result )conf0.25是置信度阈值低于这个值的检测框会被过滤掉。坑洼检测建议从 0.25 起步漏检多就降到 0.15误检多就提到 0.4。iou0.45是非极大值抑制的 IoU 阈值控制重叠框的合并程度。saveTrue会把带框的结果图存到runs/detect/pothole_result/下。如果输入是视频source换成视频路径即可YOLOv8 会自动逐帧处理并输出新视频。推理速度方面yolov8n在 GTX 1660 Ti 上跑 640 分辨率单帧大概 10~15msCPU 上大概 80~120ms。如果要做实时检测建议用 GPU或者把imgsz降到 416。4.2 val.py 算 mAP 和混淆矩阵验证脚本用来量化模型在验证集上的表现from ultralytics import YOLO model YOLO(best.pt) metrics model.val( datadata.yaml, imgsz640, batch16, conf0.001, iou0.6, projectruns/val, namepothole_eval ) print(metrics.box.map) # mAP50-95 print(metrics.box.map50) # mAP50 print(metrics.box.map75) # mAP75conf0.001在验证时设得很低是为了让所有预测框都参与 mAP 计算避免漏掉低置信度的正样本。iou0.6是评估时的 IoU 阈值比推理时的 0.45 高因为评估要更严格。跑完之后runs/val/pothole_eval/下会生成confusion_matrix.png和PR_curve.png。混淆矩阵能看出漏检和误检的比例PR 曲线能看出不同置信度下的 precision 和 recall 权衡。注意验证集和训练集必须来自不同场景。如果训练集全是晴天柏油路验证集全是雨天水泥路mAP 会低得让你怀疑人生。这不是模型不行是数据分布不匹配。5. 避坑与排查坑洼检测项目里最容易翻车的五个点5.1 训练 loss 不降反升现象启动训练后 box_loss 从 2.0 涨到 5.0 以上mAP 一直是 0。原因通常是标注格式错了比如坐标没归一化、class_id 写成了 1、或者 txt 里多了空行。解决随便抽一个 txt用cat看一眼确认每行五个数值第一个是 0后四个在 0~1 之间。再检查data.yaml里的nc和names是否和标注一致。5.2 推理时提示找不到 best.pt现象predict.py报FileNotFoundError: best.pt。原因一般是工作目录不对脚本里写的是相对路径但你在别的目录下执行。解决要么cd到项目根目录再跑要么把best.pt的路径改成绝对路径。另外确认best.pt确实在压缩包里有些打包工具会漏掉大文件。5.3 显存不够导致训练中断现象训练到一半报CUDA out of memory。原因是batch或imgsz设大了。解决先把batch减半比如从 16 降到 8还不够就把imgsz从 640 降到 416。如果用的是yolov8m换成yolov8n也能省不少显存。实在不行就上 CPU 训练慢但不会崩。5.4 检测框重叠严重现象同一个坑洼被画了好几个框。原因是iou阈值设太高非极大值抑制没把重叠框压掉。解决把推理时的iou从 0.45 降到 0.3让 NMS 更激进地合并重叠框。但别降太低否则相邻的两个坑洼会被合并成一个。5.5 视频推理结果没有声音现象用predict.py跑tested.mp4输出的视频画面正常但没声音。原因是 YOLOv8 的saveTrue只保存视频帧不保留音频轨道。解决这是预期行为不是 bug。如果需要带声音的输出用 ffmpeg 把原始音频合回去ffmpeg -i original.mp4 -i output.mp4 -c copy -map 0:a -map 1:v final.mp4。6. 从能跑到好用坑洼检测的进阶调优与验证习惯项目跑通之后真正决定检测效果的是数据质量和后处理策略。我一般会做三件事来验证模型是否靠谱。第一拿一批训练集里没出现过的场景图做盲测比如夜间、积水、阴影路面看漏检率。第二把conf从 0.1 到 0.5 每隔 0.05 跑一遍验证集画 precision-recall 曲线找 F1 最高的那个阈值。第三用val.py输出的混淆矩阵反推标注质量如果背景被大量误检为坑洼说明负样本不够得补一些正常路面的图进去。import numpy as np from ultralytics import YOLO model YOLO(best.pt) best_f1 0 best_conf 0.25 for conf in np.arange(0.1, 0.55, 0.05): metrics model.val(datadata.yaml, conffloat(conf), iou0.6, verboseFalse) p metrics.box.mp r metrics.box.mr f1 2 * p * r / (p r 1e-6) if f1 best_f1: best_f1 f1 best_conf conf print(f最佳置信度阈值: {best_conf:.2f}, F1: {best_f1:.4f})这段脚本遍历置信度阈值找 F1 最高的点。metrics.box.mp是平均 precisionmetrics.box.mr是平均 recall。跑完之后把best_conf写回predict.py推理效果会明显好于默认的 0.25。还有一个容易被忽略的点输入分辨率。路面坑洼在图像里往往只占几十个像素640 分辨率下特征很弱。如果显存允许训练和推理都提到 1280mAP 通常能涨 3~5 个点。但推理速度会降到原来的四分之一左右得根据实际场景权衡。从那以后我每次拿到一个新的检测项目都强制先跑一遍val.py看混淆矩阵再决定要不要调阈值。这个习惯帮我省了很多「看起来能跑但实际不能用」的返工。希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联
返回资讯列表 →