简介基于YOLO11深度学习的道路裂缝检测系统配备PyQt5图形界面是面向计算机视觉相关专业学生、研究人员及工程开发者的完整实践项目。系统聚焦道路裂缝单类别检测依托训练好的权重模型实现高准确率识别可直接对图片或视频进行推理适用于道路病害巡检、毕业设计、课程设计及日常实战练习界面交互直观能清晰展示裂缝位置与置信度结果。压缩包内含825个文件、整体约386.87MB其中402张jpg图像与379个txt标注文件构成配套数据集5个py文件为训练与推理源码5个pt文件为模型权重另有yaml配置、ui/qrc界面文件以及csv评估指标记录目录结构划分清晰可快速定位代码、数据与模型。资源还附带安装使用教程、评估指标曲线和演示图片视频从数据准备、模型训练、效果评估到GUI封装形成完整闭环基本实现开箱即用遇到问题可联系作者获得技术支持。当前已有186人学习/浏览适合希望系统掌握YOLO11检测项目全流程的学习者参考借鉴。1. 一套带GUI的YOLO11道路裂缝检测系统能做什么别抱什么幻想别人交付一套 YOLO11 深度学习道路裂缝检测系统本质上是把三样东西打包交到你手上370 多张标注图片、一份训练好的权重、一个 PyQt5 写的检测界面。对正在做毕业设计、或者想快速验证深度学习能不能自动筛路面病害的工程师来说它的价值是省掉从零搭环境、标注数据、调模型的过程。但它不是装上就能适配所有路面的工业级产品——裂缝是典型的细长小目标换一条新路、换一种光照、换一台相机检测结果就可能明显波动。这篇笔记按“先搞懂 YOLO11 改了什么、再把它跑通、最后把坑填掉”的顺序把原理、落地步骤和踩坑细节一次讲透。适合正在入坑 CV 缺陷检测的学生以及刚接触深度学习落地的一线工程师。2. YOLO11为什么适合做道路裂缝检测网络结构和选型逻辑2.1 YOLO11和YOLOv8差在哪先看懂这代模型改了什么要说清 YOLO11绕不开它和 YOLOv8 的关系。YOLO11 是 Ultralytics 在 2024 年 9 月推出的版本官方命名不带 v所以叫 YOLO11 而不是 YOLOv11。它延续了 v8 的 anchor-free 解耦检测头最核心的结构改动是把 backbone 里的 C2f 模块换成了 C3k2。C3k2 里的 k 是一个控制卷积配置的参数结构上属于 CSP 瓶颈输入经过两个分支一个分支走若干 Bottleneck另一个分支走恒等映射最后 concat 到一起。相比 C2fC3k2 在浅层用的 Bottleneck 更少FLOPs 更低深层保留 Bottleneck 保证特征表达能力。对裂缝检测来说这个改动带来的直接影响是在同样参数预算下YOLO11 能把更多计算量留给高层特征。裂缝宽度经常只有两三个像素经过 8 倍下采样后对应几个像素点经过 32 倍下采样后几乎消失所以浅层特征P3 层的保真度决定了小裂缝的召回上限。C3k2 减少了浅层的冗余计算这对长条形小目标是有利的。另一个容易被忽略的点是YOLO11 的 API 和 YOLOv8 完全一致。训练、验证、导出 ONNX、加载权重命令几乎不用改。这也意味着 v8 时代积累的教程、踩坑文档和第三方增强代码大部分能直接迁移到 YOLO11 上。对从业者来说模型生态的稳定性往往比单个模型涨零点几个点 mAP 更重要这是选 YOLO11 而不是某个冷门检测器的最现实理由。如果你打开它的模型配置文件还会发现这一代同时支持检测、分割、姿态估计和旋转框。这条多任务支持对裂缝检测系统有意义后续如果要升级成“裂缝分割 裂缝分类”不用换框架加一个输出头即可数据集也能在现有框标注基础上补画 mask不用推倒重来。2.2 裂缝检测难在哪三个视觉层面的真实原因裂缝检测不是普通的目标检测。大多数检测任务里的目标比如行人、车辆、瓶子在画面上是一个紧凑的块有相对稳定的宽高比。裂缝不同它是细长的、断裂的、走向任意的曲线。它的困难可以从三个层面理解。第一尺寸层面。一条两毫米宽的裂缝在 1080P 画面里可能只有两三个像素宽、几百像素长。常规下采样 32 倍后它的宽度特征被压缩到几乎不可见这就是为什么很多裂缝检测系统要把输入分辨率提到 1280 甚至更高。但分辨率提上去之后显存占用和推理延迟同步上升系统就陷入了“小目标需要大图大图拖慢速度”的两难。第二背景层面。不是所有深色长条都是裂缝。沥青路面的颗粒纹理、雨后水渍、树影、新旧路面接缝、车道线磨损在灰度特征上跟裂缝高度相似。传统 CV 里的 Canny 边缘检测或阈值分割在这种背景下会产生大量假阳性而且参数换一个场景就要重调。深度学习模型能学到的恰恰是纹理上下文——比如裂缝通常沿受力方向延伸、出现在车辆碾压带上这些隐含上下文是人工设定规则很难穷尽的。第三标注层面。裂缝的标签质量直接影响训练效果。一个长方形的目标检测框要框住一条弯曲的裂缝只能拆段。标注员习惯不同会把一条裂缝拆成三个长框也可能拆成二十个碎框。碎框导致的后果是大量框的面积比过小很难匹配到合适的 anchor 和正样本模型学到的是“裂缝碎片”而不是“裂缝”。370 多张图的数据量本身就不大标注质量对最终模型的影响占比非常高。理解了这三点就能解释为什么这套系统选择框检测而不是语义分割。分割的标注成本高一个量级模型训练也更重而路面养护场景需要的是快速定位病害位置、按里程桩号上报检测框已经能满足业务流程。这也是工程上最常见的务实做法。2.3 YOLO11、YOLOv8、RT-DETR怎么选一张对比表和三点建议经常有人拿这三个模型来问选哪个。严格说 YOLOv8 和 YOLO11 是同一生态的前后两代RT-DETR 是实时 Transformer 检测器结构差异比前两者大得多。我把它们的差异压缩成一张表。模型对裂缝任务适配数据需求量上手与部署适合场景YOLO11小模型下采样适中P3 层对小目标友好中API 与 v8 一致文档全从零起步的新项目YOLOv8与 YOLO11 接近生态成熟中教程最多第三方代码多已有 v8 权重或代码积累RT-DETR需大数据量拟合注意力370 张图易欠拟合高导出部署相对繁琐数据多、追求高精度的后台服务实际选择看三点。一是你手头有没有现成权重或标注脚本有就顺着走二是部署端是不是有 GPU如果没有YOLO11 导出 ONNX 后的 CPU 推理方案最成熟三是团队后续是否打算加裂缝分类、裂缝分割如果想在统一框架里多任务演进YOLO11 明显比 RT-DETR 省事。从这三点看这套系统选 YOLO11 作为基座是合理的而且预训练权重 yolo11n.pt、yolo11s.pt 可以直接在自家数据上做迁移学习不需要从零训练。3. 让YOLO11裂缝检测系统真正跑起来数据、训练、GUI全流程拆解3.1 数据先检查目录结构、标签格式和三个划分红线拿到项目包第一件事不是跑训练而是把数据集翻一遍。一个标准的 YOLO 数据集目录长这样datasets/road_crack/ ├── data.yaml ├── images/ │ ├── train/ # 约 300 张 │ ├── val/ # 约 50 张 │ └── test/ # 约 30 张可选 └── labels/ ├── train/ ├── val/ └── test/每个 jpg 对应一个同名 txttxt 的每一行是一个目标框格式是 class x_center y_center width height四个坐标都相对于图片宽高归一化到 0 到 1。这套系统只有裂缝一个类别class0。随便打开一个 txt内容大致是0 0.485214 0.552374 0.083412 0.014287 0 0.112834 0.734491 0.095302 0.011892 0 0.724581 0.310436 0.610756 0.012491先看宽高比上面几行宽度在 0.08 到 0.61 之间高度在 0.01 左右说明标注的是横向延伸的长条裂缝正常。如果看到大量 width 和 height 都小于 0.01 的框说明这张图的标签被切成了碎块这种标签会让训练很难收敛建议处理后再用。数据划分比想象中更容易出问题。370 多张图按 8:1:1 分 train/val/test 只是最基础的做法更重要的红线是来自同一路段、同一批次、同一光照条件下的照片不能同时出现在 train 和 val 里。否则 val 指标漂亮一到现场就翻车。正确做法是按拍摄批次或路段号分组划分保证 val 图片所属的场景 train 里完全没有并固定随机种子让划分可复现。提示训练前先用脚本扫一遍标签坐标出现负值或大于 1 的数值说明标注或转换脚本有问题这类脏标签会让 loss 在训练初期就起飞。3.2 环境配置Python、PyQt5、ultralytics和GPU的一次性体检YOLO11 环境配置是网上提问最多的环节其实核心就是三条Python 版本、PyTorch 版本、PyQt5 版本。Python 建议 3.9 或 3.10ultralytics 在 3.11 以上偶尔出现依赖编译问题没必要冒险。PyTorch 安装强烈建议去 pytorch 官网选对应 CUDA 版本用官网给出的命令安装不要直接 pip install torch。默认 PyPI 源在部分环境下会装 CPU 版 torch表面装成功实际训练时完全用不上 GPU。装完做一个体检python -c import torch; print(torch.__version__, torch.cuda.is_available()) python -c from ultralytics import YOLO; print(ultralytics ok) python -c from PyQt5.QtWidgets import QApplication; print(pyqt5 ok)第一行输出最后必须是 True才说明 CUDA 可用。第二行验证 YOLO 框架导入正常第三行验证 GUI 依赖正常。这三条命令一次跑完环境问题基本都能暴露出来。PyQt5 我一般固定装在 5.15.x太新的 6.x 在部分老代码里不兼容5.15 在 Windows 上最稳。权重文件在项目里一般叫 best.pt。直接跑 GUI 时加载它就行如果打算重新训练启动训练命令时模型参数写 yolo11s.pt 或 yolo11n.pt程序会先下载预训练权重再用你的数据做迁移学习。370 多张图的规模从头训练大概率过拟合迁移学习是最合理的路径。3.3 训练命令和参数一条命令跑通重点看这几个数值训练不用写复杂脚本ultralytics 的 CLI 足够。Windows 下建议一行写完避免换行符问题yolo detect train datadatasets/road_crack/data.yaml modelyolo11s.pt epochs100 imgsz640 batch16 device0 patience20 projectruns/train逐一说明参数。data 指向数据集的 yaml 文件里面描述类别数和类别名model 是预训练权重yolo11s 是 small 版速度和精度均衡比 n 版准确、比 m 版省显存imgsz640 是输入尺寸裂缝这种小目标如果显存允许可以提到 1280但推理耗时也会涨batch16 在 8G 显存上跑 s 模型基本没问题显存不足就降到 8device0 指定第一块 GPU机器没 GPU 时改成 devicecpu 但要有耐心patience20 表示 20 个 epoch 没有改善就早停防止小数据量下把训练时间浪费在后期的过拟合阶段。训练过程中输出目录 runs/train/exp 下会自然生成一系列评估指标曲线包括损失曲线、P-R 曲线、mAP50 和 mAP50-95 的曲线通常集中在一个 results.png 和混淆矩阵图里。这也是项目标题里“评估指标曲线”的由来不需要另外写评估脚本。对裂缝检测我的建议是重点看 mAP50 而不是 mAP50-95。因为裂缝框的标注本身就带主观性不同标注员拆框方式不同用 0.5 的 IoU 阈值能反映“框大概位置找没找对”0.95 的严格 IoU 更多在衡量标注一致性数值偏低不代表模型不好。训练结束后weights/best.pt 和 weights/last.pt 都会保留best 按 val 指标挑选是默认要用的那份。要提醒的是370 张图训练 100 轮很快瓶颈不在训练时间而在数据量。epochs 从 100 加到 300 不会带来质变真正有效的是数据增强和独立测试集验证这部分放到第 4 章展开。3.4 PyQt5界面从选择图片到显示结果的最小可运行逻辑GUI 部分的核心逻辑比想象中简单界面提供一个按钮选择文件、一个 QLabel 显示结果后端加载模型做推理。给它一个最小可运行骨架import sys import cv2 from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QFileDialog, QVBoxLayout, QWidget from PyQt5.QtGui import QImage, QPixmap from ultralytics import YOLO model YOLO(weights/best.pt) class CrackWindow(QMainWindow): def __init__(self): super().__init__() self.label QLabel(选择图片开始检测) self.btn QPushButton(打开图片) self.btn.clicked.connect(self.open_file) layout QVBoxLayout() layout.addWidget(self.label) layout.addWidget(self.btn) container QWidget() container.setLayout(layout) self.setCentralWidget(container) def open_file(self): path, _ QFileDialog.getOpenFileName(self, 选择图片, , Images (*.jpg *.png *.bmp)) if not path: return results model.predict(sourcepath, conf0.25, verboseFalse) plotted results[0].plot() # BGR rgb cv2.cvtColor(plotted, cv2.COLOR_BGR2RGB) h, w, ch rgb.shape qimg QImage(rgb.data, w, h, ch * w, QImage.Format_RGB888) self.label.setPixmap(QPixmap.fromImage(qimg).scaled(self.label.width(), self.label.height()))代码逻辑很直接model.predict 接受图片路径或 numpy 数组results[0] 是第一张图的推理结果plot() 方法会直接绘制出带框和置信度的图像省去手工 cv2.rectangle。返回的 plotted 是 BGR 顺序的 numpy 数组直接塞给 QImage 会出现颜色偏蓝偏绿的问题必须先转成 RGB。QImage 构造时的步长参数 ch*w 必须和图像通道数一致否则大图会出现斜切条纹。setPixmap 前调用 scaled 做等比缩放避免大图把界面撑爆。这里有一个很多教程没说透的坑QImage 构造时不复制图像数据而是持有原 numpy 数组的指针。open_file 函数返回后局部变量 rgb 被释放QLabel 里出现过一次能显示、之后花屏或随机条纹的情况多半就是这个原因。稳妥做法是在绘制前对数据做一次拷贝或把 rgb 保存为 self 成员变量。对视频流检测还要把推理从主线程挪到 QThread用信号把结果传回界面刷新直接在主线程里推理画面一动就卡成 PPT这个坑第 4 章单独说。4. 踩坑与排查五个让YOLO11裂缝检测系统直接翻车的细节4.1 训练时检测不到GPU日志里出现Using device CPU现象训练命令跑起来日志第一行显示 Using device CPU一个 epoch 要跑几十分钟loss 下降慢得离谱。原因最常见的两种情况。一是 pip 直接装的 torch 是 CPU 版本torch.cuda.is_available() 返回 False二是 CUDA 驱动版本太旧和 PyTorch 要求的 CUDA 运行时版本不匹配。解决到 pytorch 官网用对应环境生成安装命令选 CUDA 11.8 或 12.1 版本重新安装 torch。装完再跑一遍 3.2 里那三行体检命令确认输出 True 再开始训练。如果是老显卡用 nvidia-smi 查看驱动支持的 CUDA 版本号只要不低于 PyTorch 要求的版本就行。注意 conda 默认源在某些镜像环境下也会解析到 CPU 版 torch检查安装包名里有没有 cpu 后缀。4.2 val指标漂亮真实路面一测就翻车过拟合和数据划分问题现象训练结束 mAP50 达到 0.85 以上loss 曲线也正常把项目外自己拍的路面照片丢进去裂缝漏检一大半或者把车道线磨损误检成裂缝。原因本质是验证集和训练集分布太接近。370 多张图如果来自同一条路、同一个相机角度、差不多的光照模型只需要记住这条路面的纹理就能拿到很高的 val 指标换一条路纹理和光照变化后特征分布整体偏移模型立刻失效。这也是深度学习小数据落地的头号翻车现场。解决从数据划分上做文章。把 train 和 val 按拍摄批次或路段分组保证 val 里出现的场景训练时完全没见过再打开数据增强把 HSV 色彩扰动、随机翻转、Mosaic 都加上扩大训练分布。最后单独留出 10 到 20 张完全独立的“验收图”这些图不参与训练也不参与 val只在项目交付前做最终测试。我的做法是训练前先把验收图封装在一个单独的 test_images 目录里和 data.yaml 分开管理防止训练脚本不小心把它卷进去。4.3 裂缝被检测成一堆碎片标签碎框问题现象检测结果里一条完整的纵向裂缝被画成了十几个小框框与框之间有断档看起来像虚线而不是一条缝统计结果里裂缝数量虚高。原因训练标签里长裂缝被切成了太多小框。YOLO 按框的面积比分配正样本过小的框在特征图上只覆盖一两个点正样本数量严重不足模型学到的是碎片特征同时后处理 NMS 在小框密集区域会只保留置信度最高的那一小段造成整条裂缝被切碎。解决标注阶段控制粒度。对直线裂缝每段框的长度建议不小于整条裂缝长度的四分之一弯曲裂缝按弯曲趋势分段尽量让框的长边方向贴近裂缝走向。如果项目已经训练完且标签不好改可以在后处理里加合并逻辑对同一方向、同一水平带上的检测框做基于距离的二次聚类合并。这个方法不能完全替代重新标注但能缓解碎框问题。自查方式也很简单写脚本统计所有标签框的面积占比如果大量框的 w*h 小于 0.0005这批标签基本就是碎框重灾区。4.4 装了labelme后PyQt5界面启动失败Qt插件加载崩溃现象GUI 程序双击后无反应或直接报错 could not find or load the Qt platform plugin windows而之前明明能正常打开。原因这是非常典型的依赖冲突。labelme 为了适配自身功能安装时会配套装特定版本的 PyQt5如果之前项目的 PyQt5 是 5.15labelme 把它升级或降级后Qt 插件路径和库版本对不上整个 GUI 就打不开了。解决最干净的做法是给 labelme 单独创建虚拟环境比如 conda create -n labelme python3.9然后只在那个环境里装 labelme主项目环境保持原来的 PyQt5 不动。如果已经混装坏了把当前环境的 PyQt5 卸载后重新按项目要求的版本装一遍即可。这个问题的根本教训是所有带 GUI 依赖的标注工具不要和项目环境混装虚拟环境是唯一后悔药。4.5 GUI一卡一卡推理阻塞了Qt事件循环现象点击打开图片后界面先白一会儿才出结果视频检测时画面严重掉帧拖动窗口也一顿一顿。原因推理函数在主线程里同步执行。YOLO11 在 GPU 上单帧推理虽然只要几十毫秒但图像解码、NMS、绘制叠加图这几步加起来可能到两三百毫秒主线程被这些计算占住后Qt 的界面刷新事件和用户交互事件全部排队表现就是卡顿和无响应。解决把推理挪进 QThread 子线程父线程只负责创建任务和接收信号。具体做法是定义一个 Worker 类在子线程里读取视频帧或图片列表把推理结果通过 pyqtSignal 发回主线程主线程的槽函数里只做 setPixmap。对视频还可以把检测频率降为每 3 帧检测一次中间帧直接用上一帧结果或做跳帧显示体验会平滑很多。这一步是 GUI 从“能跑”到“能用”的分水岭。5. 部署前的最后一步最优置信度阈值和CPU加速推理模型训练完只是第一步真正部署时还有两件事值得做把置信度阈值从“拍脑袋的 0.25”变成“测出来的最优值”以及在没有 NVIDIA 显卡的机器上把推理速度提上来。阈值对裂缝检测的影响比一般任务更大。裂缝误检的代价是人工复核成本漏检的代价是病害漏报两者都受置信度这一根滑杆控制。与其凭感觉定 0.25不如在独立验收图上做一个从 0.1 到 0.5 的遍历看不同阈值下的检测数量变化和 F1 曲线峰值from ultralytics import YOLO model YOLO(weights/best.pt) test_dir datasets/road_crack/test_images for conf in [0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5]: total 0 results model.predict(sourcetest_dir, confconf, verboseFalse) for r in results: total len(r.boxes) # 正式评估时应结合GT计算TP/FP/FN print(fconf{conf:.2f}, detections{total})如果验收图上 0.3 的 F1 明显高于 0.25就把 GUI 里的置信度滑块默认值改成 0.3。这个遍历每次推理都很快370 张图规模下几分钟出结果属于投入产出比最高的一次调参。数据增强和 P2 小目标头这些结构上的改进在数据量不足时收益有限先把阈值调对反而最实在。CPU 部署是另一个常见需求。很多路面巡检现场只有普通工控机没有独立显卡。ultralytics 支持直接把模型导出成 ONNX 或 OpenVINO 格式推理代码一行不用改yolo export modelweights/best.pt formatonnx imgsz640 yolo export modelweights/best.pt formatopenvino imgsz640导出后把代码里的 YOLO(weights/best.pt) 换成 YOLO(weights/best_openvino_model)OpenVINO 格式在 Intel CPU 上能比纯 PyTorch 快一倍以上而且部署机器不需要安装 CUDA整个环境体积小了很多。对 PyQt5 程序打包来说这是个非常实用的降本方式。我做一个项目收尾的习惯是不看跑分先拿一张没在数据里出现过的现场照片丢给系统跑一遍再问自己如果这条路是阴天、逆光、路面全是水渍它还能不能用。这套 YOLO11 道路裂缝检测系统的价值在于把数据、权重和界面一次给齐让“搭平台”不再是门槛它能走多远取决于数据划分、阈值验收这两件小事有没有做扎实。希望帮到你。本文还有配套的精品资源点击获取