
简介基于Python和YOLOv8的基建裂缝目标检测系统面向毕业设计、课程设计及项目开发场景适合计算机视觉或土木工程方向的学生、研究者与开发者。系统覆盖从数据准备、模型训练、验证评估到结果展示的完整流程可有效解决基建裂缝检测任务中的数据集处理、模型构建与精度调优等需求源码结构清晰便于直接运行和二次开发。压缩包内含850个文件以jpg图像、txt与xml标注、pt模型权重、py源码、yaml配置为主整体约666MB其中图像与标注用于训练与验证pt为预训练或训练好的权重文件yaml和py分别对应模型配置与核心代码另有文档与结果图表辅助理解。已有206人学习下载适合作为课题研究的基线系统。项目附带详细开发文档、标注数据集、训练曲线与检测效果展示源码经过严格测试可放心使用在此基础上可进一步改进模型结构、优化检测精度或集成到实际工程监测系统中。1. 基建裂缝检测为什么要用 YOLOv8从巡检痛点说到这套源码的定位桥墩、隧道衬砌、路面这些基建结构件的裂缝检测过去主要靠人拿着记录本去现场目测效率低不说同一个裂缝不同人拍出来的判定结果能差出好几个等级。把目标检测模型搬进来之后现场拍一张图模型直接标出裂缝位置和置信度这已经是很多检测单位的标准流程。这套基于 python yolov8 开发的基建裂缝目标检测系统交付的不只是能跑的源码还有配套的开发文档、数据集和结果展示定位很明确给毕业设计、课程设计和项目开发做地基。它的核心价值在于把「数据标注 → 模型训练 → 推理部署」这条链路完整走通你拿到手不需要从零调通环境而是可以直接基于这套源码做二次延伸。往下我会按拿到源码后的实际操作顺序把运行链路、训练参数、标注转换和最常见的坑逐个拆开讲。2. 先读懂这套源码的运行链路目录结构、缓存文件与三个推理入口2.1 目录里那几个文件到底是谁train2017.cache、labels.cache 与 results.csv 的角色拿到压缩包解压后第一眼看到的文件里train2017.cache、labels.cache、results.csv 这几个容易被当成无用文件其实它们才是理解这套训练流程的关键。train2017.cache 和 labels.cache 是 YOLOv8 在第一次加载数据集时自动生成的序列化缓存里面存的是每张图片的路径、尺寸、标签统计信息和标注框的类别分布。它的作用是避免每次启动训练都重新扫描一遍几千张图片的磁盘目录属于典型的空间换时间做法。results.csv 则是训练过程中的指标流水账每一行对应一个 epoch记录 train/box_loss、val/box_loss、precision、recall、mAP50、mAP50-95 这些数值。你后来想画损失曲线、判断模型是否过拟合全靠这个文件不需要自己另外记录。我一般拿到项目的第一件事就是先看 results.csv 的行数如果行数太少说明训练提前中断过后面加载 best.pt 时心里要有个底。ls -la # 输出里会看到 train2017.cache、labels.cache、results.csv、003.jpg 等文件这段命令的作用是确认目录结构cache 文件的后缀和命名会随数据集名变化比如数据集叫 train2017就生成 train2017.cache叫 labels 就生成 labels.cache。如果你用一份新数据集首次训练时 YOLOv8 会在数据加载阶段重新生成对应 cache 文件旧 cache 可以手动删掉不影响训练结果反而能避免缓存与图片不一致导致的报错。003.jpg、002.jpg、004.jpg 以及 1703396895116.jpg 这几个是推理测试图前三张是相机拍的现场图最后一张明显是手机时间戳命名的照片用来验证模型在实拍场景下的泛化表现这也是项目结果展示环节的输入素材。2.2 三个代码入口detect 推理、train 训练、val 验证分别怎么启动这套项目的代码组织方式遵循 ultralytics 的标准约定核心入口是三个推理、训练、验证。推理入口负责加载训练好的权重文件对图片做预测训练入口负责在自有数据集上重新训练验证入口负责在验证集上计算 mAP 等指标。你不需要把每个 py 文件都读一遍先把主入口跑通再按需深入。运行推理是最快的验证方式直接指定权重和图片路径输出结果会保存到 runs/detect/ 目录下默认文件名带 predict 后缀。yolo detect predict modelbest.pt source003.jpg conf0.25 saveTrue这里 model 参数指定权重文件best.pt 是训练过程中验证集上表现最好的权重source 指定输入图片conf 是置信度阈值0.25 意味着模型只有判定概率超过 25% 才画框基建裂缝属于低对比度目标我一般会把 conf 压到 0.15 到 0.2 之间避免漏检细裂缝saveTrue 表示把画了框的结果图存盘。运行训练则要指定数据配置文件data.yaml 里声明了训练集、验证集路径和类别名model 参数决定用哪个网络结构作为起点常见的有 yolov8n.pt、yolov8s.pt裂缝检测场景数据量不大时用 n 或 s 足够。yolo train datadata.yaml modelyolov8s.pt epochs100 imgsz640 batch16最后是验证跑完训练后用它确认最终指标输出内容包括 precision、recall、mAP50 和 mAP50-95其中 mAP50-95 对裂缝这种细长目标更有参考价值因为它考察的是不同 IoU 阈值下的平均表现。验证结果会写进 runs/detect/val 目录同时生成混淆矩阵图能直观看到哪些类别之间容易相互误判。3. 把环境搭到能复现Python 虚拟环境、ultralytics 安装与 CPU 兜底方案3.1 环境配置顺序先锁 PyTorch 再装 ultralytics 而不是反着来不少人在环境配置上翻车多半是装 ultralytics 时顺手装了个默认版 PyTorch结果和显卡驱动不匹配训练时速度慢到像死机。这套项目用的是 YOLOv8底层依赖 PyTorch顺序必须是先确定 PyTorch 版本再装 ultralytics。如果你的机器没有 NVIDIA 显卡或者驱动版本太老直接用 CPU 版本也能跑训练时间会拉长到三五倍但推理和验证是完全没问题的特别是在毕业设计演示场景下CPU 跑推理速度其实可以接受。conda create -n crack python3.10 -y conda activate crack pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu pip install ultralytics第一行创建 Python 3.10 的虚拟环境避免和系统其他 Python 环境互相污染第二行激活环境第三行安装 CPU 版 PyTorch这里指定了 CPU 的 index-url如果你有 CUDA 显卡这个地址要换成对应的 cu118 或 cu121具体看驱动支持的 CUDA 版本第四行安装 ultralytics 库它会自动把 numpy、opencv-python、matplotlib 等依赖拉齐。装完之后建议先验证两件事torch 能不能正常加载以及 CUDA 是否被识别。python -c import torch; print(torch.__version__); print(torch.cuda.is_available())这段命令打印 PyTorch 版本和 CUDA 可用状态。输出 torch.cuda.is_available() 为 False 时别急着怀疑代码先确认装的是不是 CPU 版。我在 CPU 机器上跑这套项目时训练 100 个 epoch 大概需要比 GPU 多六到八倍的时间如果你的时间预算紧可以把 imgsz 从 640 降到 512epochs 减到 50指标不会差太多但时间能省下一大半。3.2 首次推理复现结果用自己的图片验证权重是否正常工作环境装好后不要直接上训练先用项目自带的测试图片跑一次推理确认权重、配置文件、代码三者的匹配关系是正常的。这一步相当于给整条链路做了个冒烟测试能过滤掉 80% 的环境问题。yolo predict modelbest.pt source1703396895116.jpg conf0.2跑完后终端会输出检测到的目标数量、每类目标的置信度、推理耗时同时在 runs/detect/predict 目录下生成标注后的图片。打开这张图重点看三点裂缝框是否紧贴裂缝边缘是否出现同一道裂缝被拆成多个框的情况以及背景里的水渍、结构缝有没有被误检。如果结果图表现正常说明环境和权重都健康可以进入数据准备阶段了。这里有个容易被忽略的细节推理时的 conf 和训练时的 conf 含义一样但推理端的 conf 还可以配合 iou 参数使用。YOLOv8 的默认 NMS IoU 阈值是 0.7如果你发现同一道裂缝上叠加了多个框把 iou 提高到 0.8 或者 0.85框的数量会明显收敛。yolo predict modelbest.pt source003.jpg conf0.2 iou0.8设置 iou 为 0.8 表示两个框的重叠度超过 80% 时才合并这个数值越高保留的框越多越适合裂缝这种细长目标因为裂缝框长宽比很大正常的 NMS 容易把相邻框误当成重复框删掉。4. 用自己的数据重新训练标注转换脚本、data.yaml 配置与参数调整逻辑4.1 把 labelme 标注转成 YOLO 格式一个可直接复制的转换脚本如果你要用自己的裂缝图片训练第一步不是直接打开 train.py而是把标注数据转成 YOLO 要求的 txt 格式。YOLOv8 的标签格式是每行一个目标类别ID 归一化中心点x 归一化中心点y 归一化宽度 归一化高度。而 labelme 保存的是 JSON里面记录的是多边形的顶点坐标不转换模型根本读不了。这套项目用 labelme 做标注是常见做法转换脚本我直接给可用的版本。import json import os from glob import glob def labelme_to_yolo(json_path, out_dir, class_map): with open(json_path, r, encodingutf-8) as f: data json.load(f) name os.path.splitext(os.path.basename(json_path))[0] img_w data[imageWidth] img_h data[imageHeight] out_path os.path.join(out_dir, name .txt) with open(out_path, w, encodingutf-8) as out: for shape in data[shapes]: label shape[label] if label not in class_map: continue cls_id class_map[label] pts shape[points] xs [p[0] for p in pts] ys [p[1] for p in pts] x_min, x_max min(xs), max(xs) y_min, y_max min(ys), max(ys) cx (x_min x_max) / 2.0 / img_w cy (y_min y_max) / 2.0 / img_h w (x_max - x_min) / img_w h (y_max - y_min) / img_h cx max(0, min(1.0, cx)) cy max(0, min(1.0, cy)) w max(0, min(1.0, w)) h max(0, min(1.0, h)) out.write(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}\n) if __name__ __main__: class_map {crack: 0} os.makedirs(labels/train, exist_okTrue) os.makedirs(labels/val, exist_okTrue) for json_path in glob(labelme_jsons/train/*.json): labelme_to_yolo(json_path, labels/train, class_map) for json_path in glob(labelme_jsons/val/*.json): labelme_to_yolo(json_path, labels/val, class_map)这段脚本的核心逻辑是把多边形标注替换成边界框取出所有标注点的 X 和 Y 坐标分别求最小值和最大值就得到了外接矩形中心点坐标用矩形中心除以图片宽高做归一化宽度和高度同样做归一化。归一化后的值都必须落在 0 到 1 之间脚本里最后四行做了钳制防止标注点正好在图片边缘导致坐标超过 1。class_map 这个字典是你自己的类别映射现在只有 crack 一类如果数据里还有剥落、露筋就往后追加编号 1、2。脚本里 labels/train 和 labels/val 目录已经自动创建你需要提前把 labelme 导出的 JSON 文件按训练集和验证集分好分别放进 labelme_jsons/train 和 labelme_jsons/val。4.2 data.yaml 与训练参数为什么裂缝检测推荐 imgsz1024 而不是 640转换完成后需要在项目里建一个 data.yaml告诉 YOLOv8 数据在哪里、有几类、类名是什么。path: ./ train: images/train val: images/val nc: 1 names: 0: crackpath 是相对于当前工作目录的根路径train 和 val 指向图片目录注意 YOLOv8 会自己解析图片目录对应的标签目录默认把 images 替换成 labels。如果你把标签放在 labels/train图片放在 images/train这个配置就能直接工作。nc 是类别数names 是对应的类别名顺序必须和转换脚本里的 class_map 一致否则模型学到的类别和实际标注对不上训练出来 mAP 是 0 都不知道怎么回事。训练参数这块裂缝目标有个和普通目标检测不太一样的点裂缝又细又长在 640x640 的输入尺寸下一道 2 像素宽的裂缝下采样到 80x80 的特征层上可能连 1 个像素都占不满特征直接消失。所以训练时把 imgsz 提到 1024 是值得的代价是显存占用变大如果你显存只有 6G 就老老实实用 640多利用 mosaic 增强让模型见到更多裁剪细节。yolo train datadata.yaml modelyolov8s.pt epochs100 imgsz1024 batch8 lr00.01 patience30 ampTrue对照参数表来看每个值的作用。参数推荐值说明epochs100训练轮数裂缝数据量小于 2000 张时 100 轮足够收敛imgsz1024输入尺寸裂缝细长目标建议 1024显存小就 640batch8每批图片数显存不足时优先减小这个值而不是 imgszlr00.01初始学习率数据量小时可以降到 0.005 避免震荡patience30验证损失连续 30 轮不下降就早停防止浪费时间ampTrue混合精度训练显存占用减少约 30%默认开启训练过程中终端会每轮打印一次损失和 mAP 指标同时项目目录下会生成 runs/detect/train 系列文件夹里面存着 weights 权重、results.csv 和训练过程的可视化图片。训练结束后用 2.2 节的推理命令加载 runs/detect/train/weights/best.pt 对测试图片做验证确认效果再考虑部署。5. 训练与部署避坑指南缓存文件、细长目标与显存问题的排查经验5.1 训练中断后报错找不到数据先删 cache 文件再重跑现象训练跑到第 40 个 epoch 时断电重新启动训练命令后YOLOv8 直接报错提示 Dataset not found 或者数据集路径相关错误但肉眼检查 images 目录图片明明都在。原因第一次加载数据集时生成的 train2017.cache 记录了图片路径、尺寸和标签信息断电时这个缓存文件只写入了一半或者图片目录在断点之后被改动过缓存与实际文件对不上YOLOv8 读缓存失败后就误判数据集不存在。解决直接删除数据集目录下的所有 cache 文件。find . -name *.cache -type f -delete删除后重新启动训练YOLOv8 会重新扫描图片并生成新缓存一般两到三分钟就重建完。从那以后我每次训练前都会确认数据集没有新增或删减图片只要动过数据就先把 cache 删掉省得训练到一半爆出诡异报错。5.2 训练正常但 mAP 始终为 0检查标注坐标是否越界、类别编号是否对齐现象训练日志里 loss 正常下降验证集的 precision 和 recall 也都在变但 mAP50 一直是 0或者某一类永远没有预测框。原因最常见的是两个一是转换标注时归一化坐标没有钳制到 0 到 1导致模型收到的 ground truth 框有一部分在图片外二是 data.yaml 里的 names 顺序和 labelme 转换脚本里的 class_map 不一致比如转换脚本里 crack 是 0data.yaml 里却写成了 1模型学到的标签和真实框对不上。解决先用脚本检查所有 txt 标签文件确认里面没有大于 1.0 的坐标值。import glob for txt in glob.glob(labels/**/*.txt, recursiveTrue): with open(txt) as f: for line in f: parts line.strip().split() nums list(map(float, parts[1:])) if any(n 1.0 or n 0.0 for n in nums): print(f坐标越界: {txt} - {line.strip()})这段脚本遍历所有标签文件打印出坐标越界的行。出现越界说明转换脚本有问题回 4.1 节把钳制逻辑加上。没有越界但 mAP 还是 0就去检查 data.yaml 的 names 是否和标注一致必要时打印一条标注的原始内容和转换结果对比。5.3 细长裂缝被拆成多个框或者漏检imgsz 太低和 conf 阈值太高现象推理结果显示一道完整的裂缝被模型切成了三段中间有明显断档或者很细的裂缝直接没检测出来。原因裂缝是典型的细长目标imgsz 设为 640 时下采样后裂缝中部可能只有 1 到 2 个像素响应特征图上的信息不足以让模型召回完整裂缝另外 conf 阈值设得太高比如默认 0.25细裂缝的特征置信度本来就不高容易被阈值过滤掉。解决训练时把 imgsz 提到 1024推理时把 conf 降到 0.15 到 0.2 之间。如果拆框情况还严重可以在后处理里对同一类别的框做纵向合并。import cv2 import numpy as np results model.predict(source, conf0.15) boxes results[0].boxes.xyxy.cpu().numpy() # 合并纵向重叠且横向距离小于阈值的两个框这个片段展示了后续处理的方向把模型输出的一组框拿出来按两个框的纵向重叠度和横向中心距判断是否属于同一道裂缝满足条件就取并集合并。具体阈值要现场调试但思路是面对细长目标时不要完全信任 NMS 的输出。5.4 Python 环境检测到 CUDA 但训练速度极慢检查是否装成 CPU 版 PyTorch现象torch.cuda.is_available() 输出 True但训练时 GPU 利用率只有 5% 到 10%速度甚至比同事的 CPU 机器还慢。原因ultralytics 安装时通过 pip 自动装了默认的 PyTorch 版本这个版本可能与你机器的 CPU 指令集或显卡驱动不匹配导致实际回退到 CPU 计算而不报错。解决确认 PyTorch 版本与 CUDA 版本匹配。nvidia-smi python -c import torch; print(torch.__version__)第一行查看驱动支持的 CUDA 版本第二行看 PyTorch 版本号。如果 torch 版本是 cpu卸载重装对应 cuda 版本。5.5 训练时显存溢出直接崩溃batch、imgsz、amp 三者怎么取舍现象训练启动后几秒钟内报 CUDA out of memory进程直接被杀掉。原因batch 和 imgsz 的乘积超过了显存容量。解决优先把 batch 减半比如从 16 减到 8显存占用立竿见影还不够就保持 imgsz1024 不动把 amp 开启混合精度能让显存占用再降两成最后一步才是降 imgsz因为对裂缝场景来说 imgsz 对效果影响比 batch 更敏感。显存 6G 以下的机器建议直接 imgsz640、batch4、ampTrue先把流程跑通再考虑效果。6. 从 results.csv 画损失曲线到 ONNX 导出两个能直接用的进阶技巧训练完后不要只看终端里最后一行指标把 results.csv 拿出来画成曲线能看出模型在哪个 epoch 开始过拟合也能判断是否还有继续训练的价值。这个 csv 每行是一个 epoch列名包含 train/box_loss、val/box_loss、metrics/mAP50-95 等用 pandas 读进来直接画。import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/detect/train/results.csv) df.columns df.columns.str.strip() plt.figure(figsize(12, 4)) plt.subplot(1, 2, 1) plt.plot(df[epoch], df[train/box_loss], labeltrain box_loss) plt.plot(df[epoch], df[val/box_loss], labelval box_loss) plt.xlabel(epoch) plt.ylabel(box_loss) plt.legend() plt.subplot(1, 2, 2) plt.plot(df[epoch], df[metrics/mAP50-95(B)], labelmAP50-95) plt.xlabel(epoch) plt.ylabel(mAP50-95) plt.legend() plt.tight_layout() plt.savefig(train_curve.png, dpi200)这段代码第一行读 csv第二行去掉列名里的空格这是很多版本 ultralytics 输出文件的小坑列名首字符可能带空格导致 KeyError。画完图后如果 val box_loss 在训练后段持续上升而 mAP50-95 不再增长说明模型过拟合这时需要回头增加数据增强或者提前停止。反过来说如果 val box_loss 还在下降但已经跑完 100 轮可以加载 best.pt 接着训练 50 轮。另一个实用技巧是导出 ONNX把 pytorch 模型转成端侧可用的格式方便后续接入 C 或者手机端推理。YOLOv8 用一条命令完成转换。yolo export modelbest.pt formatonnx imgsz640导出成功后当前目录会多出一个 best.onnx。注意导出时的 imgsz 必须和训练时的 imgsz 一致否则模型输入尺寸不匹配推理时要么报错要么精度骤降。用 ONNX Runtime 跑推理时输出格式是 [1, 84, 8400] 的三维数组84 的前四项是边界框坐标后面 80 项是类别概率需要自己做 NMS这一步和 PyTorch 端的行为有差异转换后先用 ONNX Runtime 跑一遍同一张测试图对比两边的检测框是否一致。那次我拿新导出的 ONNX 直接部署漏检了一堆裂缝排查半天发现是输出解析时把坐标系的中心点格式当成了角点格式从那以后我每次导出完都强制走一遍「同图对比 → 解析校验 → 再上线」的流程这个习惯帮我省下不少返工时间。这套项目从源码、开发文档到数据集和结果展示都是齐的按第 3 章的步骤把环境搭起来就能复现整个训练链路希望帮到你。本文还有配套的精品资源点击获取