简介:基于YOLO11的边坡护坡山坡滑坡检测系统,配套PyQt5图形界面,面向计算机视觉、人工智能等专业的学生、教师及工程技术人员,可用于毕业设计、课程设计或实际边坡安全监测演示。系统针对山区公路、水利工程等场景,对“滑坡”单类别进行高准确率检测,内置标注好的6600余张图片数据集,并提供训练好的模型、评估指标曲线及安装使用教程,下载后即可运行。压缩包内共2000个文件,主要包括Python源码、PyQt5界面文件、yaml模型配置、xml文件以及大量txt格式的标注数据,资源整体约929MB。目前已有682人学习使用,内容经过完整测试验证,结构清晰,适合新手从数据准备到模型部署完整走通流程,也便于在此基础上二次开发,拓展其他地质灾害检测功能。
1. 基于YOLO11深度学习的边坡护坡山坡滑坡检测系统:它解决什么、适合谁
在工地边坡巡检、地质灾害预警、无人机巡查这几类场景里,我见过太多项目最后不是死在算法上,而是死在“模型训完不知道怎么给人用”上。基于YOLO11深度学习的边坡护坡山坡滑坡检测系统(带GUI界面)就是把这条链路完整打包的工程资源:Python 源码负责推理,PyQt5 负责交互界面,6600 多张标注好的图像作为训练底子,再配上训练好的权重、评估指标曲线和安装教程。对研究生来说,它是能直接出结果再做改进的毕业设计骨架;对算法工程师来说,它省掉了写前端交互的工作量;对做监测系统集成的朋友,它是能快速改成 Web API 或者接进软硬件联调的原型。这篇文章会把数据组织、训练逻辑、GUI 启动和常见翻车点逐一拆开讲。
2. 从数据到GUI的完整链路:YOLO11选型理由与6600张数据集的训练逻辑
目标检测项目能不能落地,通常不是看网络结构有多新,而是看数据、训练配置和推理闭环是否对齐。一个带 GUI 的滑坡检测系统,本质上就是三件事:模型能识别出画面里的滑坡体或护坡异常区域,GUI 能把识别结果显示出来,数据能支撑这两个环节反复调优。下面从选型、数据集、评估三个角度拆。
2.1 为什么选YOLO11而不是YOLOv8:检测性能和部署成本的双重考量
YOLO11 是 Ultralytics 生态里目前较新的目标检测基线。相比 YOLOv8,它在主干和检测头部分做了结构调整,推理速度更快,模型体积也更紧凑。滑坡检测这类场景有个特点:很多目标是远景中的山体局部、边坡开裂区域或者落石堆,目标尺寸偏小,且背景和地物纹理非常接近。传统视觉方法在这种环境下几乎必翻车,因为颜色特征、边缘特征会被植被和岩壁干扰。而 YOLO11 的解耦检测头能把“目标在哪”和“目标是什么”分开优化,对遮挡和尺度变化更友好。
从工程角度说,选 YOLO11 的另一个理由是 Ultralytics 的 Python 接口足够统一。同一个 YOLO 类既能训练、验证,也能直接推理视频流和图片集,对写 GUI 程序非常省事。整个循环里,GUI 只需要拿到检测框坐标、类别索引和置信度,再画到 QLabel 或 QGraphicsView 上,不需要关心底层的卷积计算。模型文件可以单独存放,换模型权重不需要改界面代码。
需要留意的是,YOLO11 的模型大小从 n、s、m、l 到 x 逐级增加。带 GUI 的本机如果只用 CPU 推理,我一般建议先用 YOLO11n 或 YOLO11s 验证流程,再考虑是否换更大的权重。数据量 6600 多张对一个单类别或两三类的项目来说是够用的,但分布是否均衡还是要看标注统计,不能只看总量。
2.2 数据集划分与标注格式检查:train/val/test与YOLO txt的关系
拿到资源后,第一步不是急着跑训练,而是打开数据集目录看结构。YOLO 系列的标注文件是一一对应的 txt 文件,每行格式是“类别索引 中心x 中心y 宽度 高度”,坐标全部归一化到 0-1 之间。图像放在 images 目录下,标签放在 labels 目录下,训练集、验证集、测试集分别管理。
常见的数据集组织方式如下,实际路径以资源包目录为准:
bash dataset/ ├── train/ │ ├── images/ │ ├── labels/ ├── val/ │ ├── images/ │ ├── labels/ ├── test/ │ ├── images/ │ ├── labels/ └── data.yaml
data.yaml 是训练和推理的关键配置,决定类别数、类别名和路径。我拿典型场景举例,里面通常会出现滑坡体、护坡区域这类目标,对应的 YAML 配置大概长这样:
yaml path: ./dataset train: train/images val: val/images test: test/images
names: 0: landslide 1: slope_protection 2: rockfall
这里有几个容易踩的坑。第一,names 的顺序必须和训练时完全一致,否则加载新权重后框和标签对不上。第二,txt 标注里的类别索引从 0 开始,如果原始标注是在 Labelme 里画的 JSON,转成 YOLO 格式时必须检查转换脚本有没有把类别映射错位。第三,检查一下 labels 目录里是否有和 images 目录同名的文件,漏标、空标注文件都会直接影响训练结果。
我一般会在跑训练前先用脚本扫一遍标注分布,确认没有大面积空标注或者类别严重失衡。可以用下面的脚本快速统计:
python import os from collections import Counter
def inspect_labels(label_dir): total_boxes = 0 class_counter = Counter() empty_files = 0 file_count = 0
for name in os.listdir(label_dir): if not name.endswith('.txt'): continue path = os.path.join(label_dir, name) with open(path, 'r', encoding='utf-8') as f: lines = [line.split() for line in f.read().strip().splitlines()] file_count += 1 total_boxes += len(lines) if len(lines) == 0: empty_files += 1 for line in lines: if len(line) > 0: class_counter[int(line[0])] += 1 avg = total_boxes / max(1, file_count) print(f'标注文件数: {file_count}') print(f'空标注文件数: {empty_files}') print(f'平均每张图目标数: {avg:.2f}') print(f'类别分布: {dict(class_counter)}')inspect_labels('dataset/train/labels')
脚本逻辑很简单:遍历标签目录下所有 txt,统计文件数量、空文件和类别索引分布。如果某个类别的目标数特别少,训练时就要考虑复制粘贴增强或加权重。这个统计脚本本身也是检查“标注好的数据集”是否干净的最笨但最有效的方法。
2.3 评估指标怎么读:precision、recall、mAP50和曲线文件
资源里附带训练好的模型和评估指标曲线,常见文件是 results.png、confusion_matrix.png、val_batch0_pred.jpg 这些。很多人只看 loss 曲线,这是常见误区。对滑坡检测这种实际工程场景,真正要优先看的是精确率和召回率。
精确率代表模型标出的框里有多少是正确的;召回率代表所有真正的滑坡区域里模型找出了多少。在边坡监测场景中,漏报比误报更危险,所以阈值设置通常要适当牺牲精确率来换召回率。mAP50 指的是 IOU 阈值为 0.5 时的平均精度,mAP50-95 则是在 0.5 到 0.95 范围内综合评估。资源里的指标曲线,我建议重点看 P/R 曲线和 F1-Confidence 曲线,前者能看出置信度怎么设最合理,后者能直接指导 GUI 里的阈值滑块默认值。
下面用表格把几个关键指标和适用场景说明一下:
| 指标 | 关注点 | 滑坡检测场景下的建议 |
|---|---|---|
| Precision | 框出的目标有多少是对的 | 阈值设高时数值好看,但可能漏检 |
| Recall | 真实目标有多少被找出来 | 滑坡监测应保证较高的召回率 |
| mAP50 | 综合性能的简单参考 | 0.85 以上属于可部署水平 |
| mAP50-95 | 对边框精度的严格考核 | 边框不稳的小目标会比较吃亏 |
| F1-Confidence | 不同阈值下的综合得分 | 用来确定默认置信度最直接 |
如果发现 mAP 高但实际 GUI 里漏检多,十有八九是预测时的 conf 设得比训练验证高,后面第四章会详细说参数调整。
3. 本地环境配置与Windows安装:把Python源码和PyQt5界面跑起来
这类带 GUI 的检测系统,最容易卡住用的不是模型本身,而是环境。YOLO11 需要 PyTorch,PyQt5 需要 Qt 运行库,两者一旦版本冲突就会出现各种玄学报错。为了不把系统 Python 搞乱,一律先建虚拟环境。
3.1 环境隔离与依赖安装:Python版本和PyQt5的坑
Windows 下用 Conda 建环境是最稳妥的方式。Python 版本选 3.10 或 3.9 都可以,pyqt 和 ultralytics 的兼容性都还不错。不建议一上来就装最新 Python 3.13,很多编译好的轮子还没跟上,容易翻车。
bash conda create -n yolo11 python=3.10 -y conda activate yolo11 pip install -U pip pip install PyQt5==5.15.10 pip install ultralytics
这里把 PyQt5 锁到 5.15.10 是我反复试过的版本,5.15 系列在 Win10、Win11 下表现比较稳定。如果直接 pip install PyQt5 装到最新版,有时会出现 QWidget 显示异常或 Qt 平台插件报错。Ultralytics 库本身会主动带上 torch 和 opencv-python 依赖,不需要单独装,但国内网络环境下建议把 PyTorch 的安装源切到国内镜像,否则下载速度会让人怀疑人生。
注意,如果你电脑上已经有 Nvidia 驱动,想要 GPU 加速,可以加装对应 CUDA 版本的 PyTorch。如果只是先把 GUI 跑通,用 CPU 版本也完全足够,YOLO11n 在 CPU 上单张图片推理大概几百毫秒,不影响功能验证。
提示:不要图省事直接 conda install pyqt5 装到 base 环境。后续一旦跑其他深度学习项目,pyqt 的 Qt 版本和 opencv 依赖会互相打架,到时候删除都删不干净。
3.2 模型权重与数据集YAML的组织方式
环境装好后,打开资源包先确认几个关键文件是不是都在:GUI 主程序(通常是 main.py)、权重目录(weights/best.pt)、数据集配置(data.yaml)和 demo 图片或视频。我拿标准化推理流程演示,先加载权重并打印模型的类别映射:
python from ultralytics import YOLO
model = YOLO('weights/best.pt') model.info()
print('模型类别:', model.names)
这段代码做了两件事。第一,model.info() 会打印模型的参数量、层数和输入尺寸,通过它可以确认权重文件是否真的被正确解析,避免加载到损坏文件。第二,model.names 是一个字典,比如 {0: 'landslide', 1: 'slope_protection'},这一步能直接看出训练时用的类别顺序。如果这里打印的类别和 GUI 界面里显示的类别文案对不上,那说明权重和界面设置的类别映射有偏差,得检查代码里的类名列表。
通常这个项目的 GUI 会从 data.yaml 读取 names,也可能会在 GUI 代码里硬编码一份。最稳的做法是让推理模块统一从 model.names 拿标签,而不是自己写死,这样以后换数据集训练时界面自动适配。
3.3 启动GUI和第一次推理:从main.py到检测结果
确认文件齐全后,在虚拟环境里切换到资源包根目录,执行启动命令:
bash python main.py
正常情况下会弹出 PyQt5 窗口,窗口上有一个图像显示区域、一个“选择图片”按钮、一个“开始检测”按钮,以及置信度阈值调节滑块。先选一张 demo 图片,点击检测,如果模型正常工作,图像上会出现带类别的矩形框,旁边是对应置信度。
第一次跑通时如果窗口弹出但点按钮没反应,最常见的原因是模型推理过程没有放进子线程,导致界面在等待推理结果时卡死。后续版本通常在代码里用 QThread 处理,但如果拿到的是精简版源码,就得自己包一层。这个问题在第五章会专门讲。另一个容易忽略的事是第一次推理会自动下载一些配置文件或模型文件,如果网络受限,建议先手动确认 weights 路径下的 best.pt 存在且大小合理,再重新运行。
提示:如果点击检测直接报“No module named torch”或“CUDA unavailable”,说明虚拟环境里 torch 没装好。不要急着卸载重来,先执行 python -c "import torch; print(torch.version)" 看看能不能正常导入,再决定下一步。
4. 用GUI和脚本做推理:置信度、NMS与批量检测参数
跑通 GUI 只是第一步,真正要能应对实际使用,必须理解置信度和 NMS 这两个参数。很多用户拿到手后觉得“模型检测不准”,其实是 GUI 里的阈值和场景不匹配。
4.1 PyQt5界面操作流程:加载图片、调节阈值、看结果
典型 GUI 的操作顺序是:点击“选择图片”按钮,通过 QFileDialog 选定一张 jpg 或 png;图像显示到界面中央;拖动置信度滑块调整阈值;点击“开始检测”;结果显示在原图上,并在状态栏打印检测数量。
滑块值的范围通常会设成 0.05 到 0.95,步长 0.05。推荐把默认值放在 0.25 到 0.35 之间。边坡和滑坡这类目标不像人脸那样特征集中,在无人机视角下有时目标很小,若默认置信度 0.5,会漏掉大量边缘和远景目标。之前帮一个做尾矿库监测的朋友调系统,他把置信度从 0.5 降到 0.3,漏报少了将近一半,虽然误报框也多了,但宁可多看几个框再人工筛,也不能让危险区域被吞掉。
PyQt5 界面里的“保存结果”按钮通常是把带检测框的图像写回磁盘。如果想自己实现,核心逻辑就是拿推理结果在 cv2 图像上画框,然后 cv2.imwrite。画面上的框颜色建议对误报更显眼的暖色系,比如滑坡目标用红色,护坡区域用黄色,方便巡检员第一眼看到高危部位。
4.2 推理脚本参数说明:conf、iou、imgsz、device
抛开 GUI,直接调 Ultralytics 接口可以更精确地观察参数作用。下面这段代码把单张图片推理的完整过程写出来了:
python from ultralytics import YOLO import cv2
model = YOLO('weights/best.pt') image = cv2.imread('demo/slope_01.jpg')
results = model.predict( source=image, conf=0.30, iou=0.50, imgsz=640, classes=[0, 1], verbose=False )[0]
for box in results.boxes: x1, y1, x2, y2 = map(int, box.xyxy[0]) cls = int(box.cls[0]) score = float(box.conf[0]) label = f'{model.names[cls]} {score:.2f}'
cv2.rectangle(image, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.putText(image, label, (x1, y1 - 8), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)cv2.imwrite('output/slope_01_result.jpg', image) print('检测到目标个数:', len(results.boxes))
代码逻辑分三段。第一段是模型加载,第二段是 predict 推理,第三段是结果绘制和保存。参数里 conf=0.30 代表只保留置信度不低于 0.30 的框;iou=0.50 代表当两个框的交并比超过 0.5 时合并成一个;imgsz=640 是把输入图像缩放到 640x640 再推理,这个值直接影响小目标检测效果。classes=[0, 1] 用来过滤类别,只检测滑坡体和护坡区域,落石类别如果不想看可以直接排除掉。
关于 imgsz,这里有讲究。如果原图是 4000x3000 的无人机航拍图,直接缩到 640 会把细微裂缝和边坡局部完全抹平,导致漏检。我一般优先用 1024 或 1280 推理大图,再把检测框坐标按比例映射回原图坐标。代码里的 box.xyxy 是归一化前的像素坐标,只要 predict 的 source 是原始图,返回的 xyxy 就是原图坐标,可以直接画框。
4.3 视频与批量图片检测:线程和显存处理
如果是批量图片或视频文件,不能一次性把所有帧都送进模型,否则显存和内存都会爆掉。推荐用 stream=True 模式逐帧处理:
python from ultralytics import YOLO
model = YOLO('weights/best.pt')
for idx, result in enumerate( model.predict( source='demo/slope_video.mp4', stream=True, conf=0.30, iou=0.50, imgsz=640, device='0' ) ): if result.boxes is not None: result.save(f'output/frame_{idx:04d}.jpg')
这里把 device='0' 表示使用第一张显卡,如果只有 CPU 就改成 device='cpu'。stream=True 的作用是把推理变成生成器,每处理完一帧才拿下一帧,不会一次性把整个视频读进内存。对于 GUI 应用,视频流场景还应该把模型实例放在主线程外面,只在后台线程里调用 model.predict,界面线程负责刷新 QImage,否则视频画面会掉帧严重,甚至出现窗口未响应。
5. YOLO11+PyQt5踩坑排查:从安装报错到检测结果全为0
带 GUI 的深度学习项目,报错类型百分之六十在环境,百分之四十在数据或推理逻辑。我把实际遇到的高频问题按阶段整理成清单,每一条都按“现象、原因、解决”说明。
5.1 安装和启动阶段:Pip冲突、ImportError、Qt平台插件丢失
现象一:pip install PyQt5 时自动卸载了其他包,或者提示“ERROR: pip’s dependency resolver does not currently take into account all the packages”。原因:当前环境中已存在其他版本 Qt 或 opencv 依赖,pip 解析时发生冲突。解决:不要硬扛,新建 conda 虚拟环境,只安装 PyQt5 和 ultralytics,确保系统里没有混装的 pyqt4、pyqt5、pyqt6。装完执行 pip list 检查有没有多余的 Qt 包,有冲突就统一卸载后重新装。
现象二:运行 main.py 时提示“ImportError: cannot import name ‘QtWidgets’ from ‘PyQt5’”。原因:当前 Python 的 PyQt5 安装不完整,或者当前目录下存在一个叫做 PyQt5.py 的文件,导致 Python 把本地文件当成模块导入。解决:先确认当前目录没有命名冲突文件;然后在虚拟环境执行 pip install --upgrade --force-reinstall PyQt5。如果还不行,直接从基础环境用 importlib 检查安装路径。
现象三:启动窗口时弹窗提示“could not load the Qt platform plugin windows”或“qt.qpa.plugin could not be found”。原因:PyQt5 自带的 Qt 平台插件目录被清理,或者系统 PATH 里存在多个 Qt 运行时。解决:检查虚拟环境下的 site-packages/PyQt5/Qt/plugins/platforms 是否存在 qwindows.dll。若缺失,重装 PyQt5。若存在,把 plugins 目录加到环境变量,或者删除系统里其他 Qt 的 PATH 项。
现象四:Win 下双击运行脚本没有反应,但命令行启动能正常打开。原因:GUI 程序没有保留命令行窗口,报错直接闪退。解决:以后统一用命令行启动,python main.py 才能看到报错。如果是打包 exe 的需求,得在入口处 catch 异常并写入日志文件。
5.2 推理结果阶段:全0、漏检多、画面卡顿的排查顺序
现象五:图片能加载,但检测框一个都没有,日志显示 0 objects detected。原因:常见于权重文件没有加载成功,或 predict 时的 conf 阈值过高,也可能模型类别和输入图像完全不匹配。解决:先打印 model.names 看类别是否正确;再打印 model.ckpt 路径确认权重;最后把 conf 调到 0.1 看一下是否出现低置信度框。如果调低后大量出框,说明之前阈值设太高;如果依旧全 0,那就是模型和数据不匹配。
现象六:检测框大量存在,但全部标错类别,比如把排水沟当落石。原因:classes 顺序映射错位。训练时类别顺序是 landslide、slope_protection,但 GUI 推理代码里 hardcode 的 names 列表写成了 rockfall、slope_protection,索引一差就全错。解决:修改 GUI 里的 names 列表,使其与训练 data.yaml 完全一致。
现象七:视频检测时播放很流畅,但每隔几秒卡一下,CPU 占用率忽高忽低。原因:推理线程和界面刷新线程抢占 GIL,或者模型在每一帧都重新加载。解决:把模型实例化放在子线程构造里,只初始化一次;界面刷新用定时器从队列里取最新帧,而不是每帧都同步。若用 GPU,注意检查显存是否打满,打满后推理帧率会突然掉到接近 0。
现象八:同一张图片反复推理,输出框的位置在抖动。原因:输入图像尺寸不固定,模型内部做 padding 后映射坐标有误差,或推理时启用了测试时增强。解决:推理时固定 imgsz,不要对图像做自动缩放;如果还要高精度,就别用 letterbox 的默认行为,手动先 resize 到统一尺寸再推理。
6. 进阶:更换数据集重训YOLO11并把新模型接回GUI
如果内置的 6600 多张数据满足不了你的场景,比如要识别特定矿区的渣土边坡,或者要增加“防护网破损”类别,那必须用自己的数据重训。资源里带的训练好的模型只是一个起点,最终还是要落回自有数据上。
6.1 数据准备与训练命令
新数据准备不复杂,按 YOLO 格式组织即可。图像放到 images 下,标注 txt 放到 labels 下,改 data.yaml:
yaml path: ./my_data train: images/train val: images/val
names: 0: landslide 1: slope 2: net_damage
然后从 YOLO11n 预训练权重开始微调,不建议从头随机初始化训练。训练脚本如下:
python from ultralytics import YOLO
model = YOLO('yolo11n.pt') model.train( data='my_data.yaml', epochs=100, imgsz=640, batch=8, device='0', patience=15, )
epochs 设到 100 是常见默认值,但 patience=15 会控制在验证集指标连续 15 轮不提升时提前停止,省时间。batch=8 对 8G 显存的显卡比较安全,显存小就降到 4。训练完成后 best.pt 在 runs/detect/train/weights 下。
6.2 模型替换与阈值调整
把训练好的 best.pt 复制到资源包 weights 目录,替换旧文件,再重新运行 GUI。因为 GUI 推理模块通常只调用 model.names,只要训练时的 names 和 GUI 代码一致,界面就能直接显示新类别。如果没有自动适配,就把 names 列表改成新的四类名称。
从那以后,我每次拿到这种带 GUI 的检测项目,都会强制走一遍流程:先建干净虚拟环境,再用 CPU 跑通 demo,最后改置信度和类别映射表,确认这三样东西没问题才上 GPU 或部署。很多人翻车都是跳过前两步直接拿自己的手机照片测试,结果权重、阈值、坐标映射混在一起报错,搞不清楚到底是哪一环的问题。希望这组踩坑笔记能帮你在拿到这套资源时少走一段弯路。
本文还有配套的精品资源,点击获取