ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于YOLO11的滑坡检测系统实战:从模型训练到PyQt5界面部署

基于YOLO11的滑坡检测系统实战:从模型训练到PyQt5界面部署 简介这套基于YOLO11深度学习的边坡护坡山坡滑坡检测系统面向计算机相关专业学生、老师及企业开发者专注于高准确率的滑坡单类别识别内置Pyqt5图形界面操控直观可直接用于毕业设计、课程设计或实战项目演示也适合深度学习入门者学习进阶。资源包共2000个文件含1992个txt标注文件、6个xml、1个yaml配置及1个py主程序压缩包约929.18MBtxt与xml对应6600多张标注数据集yaml定义模型参数与滑坡类别py提供核心推断逻辑配套安装教程与训练好的模型可快速复现检测效果文件目录结构清晰便于按模块检索。当前已有682人学习下载资源另附评估指标曲线和演示图片视频便于直观理解模型性能项目代码经作者运行验证支持在此基础上略作修改以适配其他检测场景整体属于开箱即用的完整解决方案。1. 暴雨天的人工巡查困局这套 YOLO11 滑坡检测系统解决什么问题每年汛期公路边坡巡查员都要在雨后沿着盘山路用肉眼观察坡面有没有裂缝、鼓包和落石。一个人一天要看几十公里车停在路边拿望远镜瞄很多早期滑坡征兆根本看不出来。这套基于 YOLO11 的边坡护坡滑坡检测系统就是把这件危险又枯燥的事交给深度学习模型用 6600 多张已标注的滑坡图像训练检测模型再包一层 PyQt5 桌面界面导入图片或连接摄像头模型自动框出滑坡体位置并给出置信度整个过程开箱即用。适合做公路养护信息化、地灾监测预警的工程团队也适合拿它当参考项目快速入门 YOLO11 叠加 GUI 开发的在校学生。2. 为什么用 YOLO11 做滑坡检测网络改动、小目标能力与选型边界2.1 YOLO11 的网络结构变化C3k2、SPPF 和效率账YOLO11 是 ultralytics 在 YOLOv8 基础上改出来的目标检测模型核心变化在 backbone把 v8 的 C2f 换成了 C3k2内部用两个 C3k 瓶颈块串联通道数配比重新调整过。只看结构图容易懵C3k2 的设计意图是在尽量不增加参数量的前提下扩大感受野让特征提取更高效。SPPF 层被保留下来继续用不同尺度的池化核做多尺度特征聚合。对滑坡检测来说backbone 的任务是把坡面纹理异常、颜色突变、几何变形这些低层特征逐层抽象成可能是滑坡体的高层语义。C3k2 在保持特征图尺度不变的同时减少了分支合并开销所以 yolo11n 的参数量被压到 2.6M 左右在 CPU 上都能接近实时跑。如果部署机器只有一张 GTX 1060 这种老卡yolo11s 或 yolo11m 是更稳妥的档位后面训练参数部分再细化怎么选。2.2 小目标增强滑坡体小到只有 30 个像素怎么办滑坡检测和行人检测最大的区别是目标尺度极其分散近处坡面的滑坡体可能占半张图远处山体上的滑坡在 640x640 输入下只有二三十个像素。YOLO11 原生 P3 检测层对这种小目标很吃力所以做这套系统时经常要给它开小灶。常见的做法有两种一是在模型 yaml 里增加 P2 检测层把 stride 从 8 降到 4让 backbone 浅层的 160x160 特征图参与检测代价是显存和推理耗时上升二是推理时做滑窗切块把原图切成 640 的块分别检测再合并。前者要改模型结构重新训练后者纯推理侧改动不动模型权重。对 6600 多张的数据量来说建议先不改结构把 imgsz 从 640 提到 896配合数据增强里的 mosaic先把漏检压下去结构改进放到模型迭代第二轮再做。2.3 YOLO11 和 SAM3 的边界什么时候不该换分割大模型经常有人问 YOLO11 和 SAM3 怎么选。SAM3 是分割大模型能给出像素级掩码理论上对滑坡边界的勾勒比检测框精细得多但它的使用前提是给提示词要么点一下要么框一下不是丢一张图就全自动巡检的东西。而且 SAM3 的模型体积和推理耗时摆在那里跑在工控机上的实时监测场景基本扛不住。滑坡检测系统要的是从一张巡检图里自动找出哪几处可疑、坐标在哪、置信度多高YOLO11 的边界框输出正好对接后续业务系统派单复核、标记台账、按框裁剪存档都是一条链路。如果最终目的是估算滑坡土方量那要走另一条路线常见做法是 YOLO11 先检测再接一个分割头做精细勾画而不是直接拿 SAM 当主力。选型核心就一句话要自动定位、要快、要轻选 YOLO11要人工交互式精细勾画才考虑分割大模型。3. 把 6600 多张滑坡标注数据变成可训练集目录组织、格式校验与增强策略3.1 从标注文件到 ultralytics 格式VOC 转 YOLO 的转换脚本这套方案里的 6600 多张标注图大部分是边坡、护坡、山体滑坡的现场照片标注类别一般就一类滑坡体复杂一点会分成滑坡、落石、裂缝多类。ultralytics 框架期望的数据目录长这样dataset/ images/ train/ val/ labels/ train/ val/每张图对应一个同名 txt内容是class cx cy w h四个坐标都归一化到 0~1 的浮点数。常见做法是把 Labelme 的 json 或 VOC 的 xml 转成这种格式。转换脚本核心逻辑不复杂难点在于边界情况处理。先看 VOC 转 YOLO 的最小实现import xml.etree.ElementTree as ET from pathlib import Path def voc2yolo(xml_path, out_dir, class_map): root ET.parse(xml_path).getroot() size root.find(size) w_img int(size.find(width).text) h_img int(size.find(height).text) lines [] for obj in root.iter(object): name obj.find(name).text bbox obj.find(bndbox) x1 int(bbox.find(xmin).text) y1 int(bbox.find(ymin).text) x2 int(bbox.find(xmax).text) y2 int(bbox.find(ymax).text) cx (x1 x2) / 2 / w_img cy (y1 y2) / 2 / h_img w (x2 - x1) / w_img h (y2 - y1) / h_img lines.append(f{class_map[name]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) out Path(out_dir) / (Path(xml_path).stem .txt) out.write_text(\n.join(lines))这段代码只做坐标转换不做合法性校验。class_map 是类别名到数字的映射比如{landslide: 0, rockfall: 1}。转换完必须再跑一遍校验因为 VOC 标注里经常出现 x2 小于 x1、坐标超出图片边界这类问题转换脚本会把脏数据原样变成 txt。3.2 数据集质量校验揪出空标签、越界框和类别错标6600 多张图人工标注总会有疏漏。每次拿到数据集的第一件事不是直接训练而是跑校验脚本检查三类脏数据一是 labels 里有 txt 但 images 里没对应图二是标注框越界归一化后的 cx、cy、w、h 超出 [0,1]三是类别编号超过类别总数说明转换时 class_map 没对上。给一个可复用的扫描脚本from pathlib import Path def scan_labels(img_dir, lbl_dir, num_classes1): lbl_files list(Path(lbl_dir).glob(*.txt)) issues {empty: 0, out_of_range: 0, mismatch: 0, class_oob: 0} for lbl in lbl_files: img Path(img_dir) / (lbl.stem .jpg) if not img.exists(): issues[mismatch] 1 continue lines [l for l in lbl.read_text().strip().splitlines() if l.strip()] if not lines: issues[empty] 1 continue for line in lines: parts line.split() cls int(parts[0]) vals list(map(float, parts[1:])) if cls num_classes: issues[class_oob] 1 if any(v 0 or v 1 for v in vals): issues[out_of_range] 1 return issues跑完看统计空标签多的数据集要回炉补标越界框多的要回去修 VOC 转换脚本而不是手工改 txt。6600 张图手工改不现实从源头脚本修才是治本。mismatch 数量高通常是图片格式不统一有的图是 .jpg 有的 .png脚本里只查 .jpg 会误报改成先读 labels 文件名再去 images 目录里找同名后缀匹配。3.3 数据增强策略滑坡场景不是无脑堆 Mosaicultralytics 的数据增强通过 data yaml 里的全局参数控制。滑坡场景的特殊性在于训练图大多来自晴天、白天、清晰视角但实际部署会遇到阴天、雨雾、逆光和远距离小目标。增强策略要往模拟恶劣条件走增强 HSV 的饱和度随机性让土壤和植被颜色偏移调低亮度模拟阴天加轻微高斯模糊模拟雨雾。Mosaic 和 MixUp 建议开但注意滑坡体的形状是块状的、边界不规则MixUp 混太狠容易让模型学成贴图感类别特征会糊掉。还要注意翻转方向不要无脑开上下翻转。山体照片里天空和地面的语义位置是固定的上下翻转会让模型学到错误的先验比如把天空误判成坡面背景。常见的做法是只开左右翻转。如果后面要做位移趋势分析坡向在物理上是有意义的翻转后的样本要单独验证过再决定是否保留。4. 从零跑通 YOLO11 滑坡检测训练环境配置、超参数与评估指标4.1 Windows 下安装 YOLO11 环境顺序比命令重要这套方案在 Windows 上跑需要装的东西就三样Python、PyTorch、ultralytics外加 PyQt5 给 GUI 用。建议用 conda 建独立环境避免把系统 Python 搞乱。安装顺序是固定的conda create -n yolo11 python3.10 -y conda activate yolo11 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics pip install pyqt5PyTorch 一定要先于 ultralytics 装因为 ultralytics 装完会校验 torch 是否可用。装完跑一句python -c import torch; print(torch.cuda.is_available())输出 False 多半是 CUDA 版 PyTorch 没装上或者显卡驱动太老。没有 NVIDIA 显卡的机器用 CPU 版也能跑推理检测一张 640 的图大概两三秒做演示够用做实时监测得换机器。conda 环境有个经典坑同时装了 qt 和 pyqt5 两套库会导致 Qt 平台插件冲突后面避坑章节详细讲。4.2 训练命令与超参数这些参数直接决定漏检率数据准备好后训练就是一行命令。假设数据 yaml 叫 slope.yaml内容如下path: D:/slope_dataset train: images/train val: images/val names: 0: landslide类别少、目标单一names 就一行。有落石、裂缝就继续往上加注意类别编号必须从 0 开始连续。然后执行训练yolo detect train \ dataslope.yaml \ modelyolo11s.pt \ epochs200 \ imgsz896 \ batch16 \ patience30 \ ampTrue \ project./runs参数逐个说。modelyolo11s.pt 表示从预训练权重继续训练滑坡特征虽然和 ImageNet 差得远但底层纹理和边缘特征迁移是有效的从零训练反而容易欠拟合。显存小于 6G 就换 yolo11n.pt12G 显存可以试 yolo11m.pt。imgsz896 是为了小目标代价是训练时间涨约一倍如果 640 下漏检不严重先用 640但推理时的 imgsz 必须和训练一致否则模型要重新适应尺度。patience30 的意思是 30 个 epoch 验证集指标没提升就早停实际很少真跑满 200 轮大多 60~80 轮收敛。ampTrue 开混合精度显存直接省一半老卡上尤其重要。显存不够且不想降 batch 时常见做法是 batch 减半同时加长训练轮数。cosine 学习率衰减在 ultralytics 里默认开着不要关滑坡这种类别不平衡的数据集靠它稳定收敛。训练日志里重点看 val 损失是否持续下降如果 val 损失在第 40 轮开始反弹而 train 损失还在降就是过拟合信号这时候加数据增强或者提前早停。4.3 评估指标别只盯着 mAP先看 PR 曲线训练结束后 runs/detect/train 目录下会生成 best.pt、last.pt、results.csv、PR_curve.png、F1_curve.png、confusion_matrix.png。看指标的顺序应该是先看 PR 曲线再看 F1 曲线最后才看 mAP 数值。PR 曲线越靠近右上角越好如果曲线在 recall 高段急剧掉下去说明模型为了精度牺牲了大量滑坡召回这在巡检场景是致命的漏一个滑坡体是要出事的。这时候调的不是阈值而是回训练端降低置信度默认阈值、加小目标增强、补数据。results.csv 里每行是一次 epoch 的汇总用 pandas 读出来画 loss 曲线能直观判断过拟合。best.pt 是验证集指标最好的权重GUI 里加载的就是这个文件last.pt 是最后一轮权重泛化通常不如 best一般不用。混淆矩阵看的是类别间的误检对单类滑坡检测来说重点关注滑坡被漏检进了背景类还是被误检成了落石。5. 滑坡检测系统避坑排查PyQt5 闪退、中文路径与显存不足的 4 个真问题5.1 PyQt5 安装后闪退labelme 也起不来现象pip 装完 pyqt5 后运行任何 Qt 程序直接闪退用 labelme 标注工具也打不开GUI 界面还没弹出来就没了。原因PyQt5 5.15.x 在 Windows 上经常缺平台插件 qwindows.dll或者 OpenGL 动态库版本冲突。conda 环境里如果同时存在 qt 和 pyqt5 两套库平台插件路径会被搞乱。解决先conda list看是否有 qt 和 pyqt5 混装有就全卸掉用 pip 重装指定版本。pip install pyqt55.15.2是稳定性较好的组合。重装后还在闪退在代码里强制指定平台插件os.environ[QT_QPA_PLATFORM] windows放在 import PyQt5 之前执行。5.2 训练正常但 GUI 推理时图片全是黑框现象训练阶段一切正常loss 在降验证集指标也不错。把 best.pt 加载进 GUI 后选择图片推理画面显示黑框或者检测框画在空白画布上。原因OpenCV 的 imread 对中文路径支持很差。Windows 下项目路径或图片路径里带滑坡边坡这种中文目录时imread 静默返回 None界面拿到的是空图像但检测逻辑照常跑完于是框画在了空画布上。解决整个项目的图片路径、模型路径、导出路径全部用英文目录。中文只在 UI 显示层用类别映射表{0: 滑坡体}只用于表格显示不参与文件读写。如果业务上绕不开中文路径用下面这段代码替代 imreadimport cv2 import numpy as np def imread_unicode(path): data np.fromfile(path, dtypenp.uint8) return cv2.imdecode(data, cv2.IMREAD_COLOR)np.fromfile 按字节读文件imdecode 解码成图像绕开了 OpenCV 内部对路径的编码假设。这个函数在 Windows 中文环境下是必备工具。5.3 训练到一半报 CUDA out of memory现象imgsz 从 640 提到 896 后训练刚开始几个 epoch 就报RuntimeError: CUDA out of memorybatch 调小后仍然报错。原因imgsz896 时特征图显存占用约是 640 的两倍batch16 在 6G 显存上直接爆掉。这是提升分辨率换小目标召回率的直接代价。解决先看nvidia-smi确认显存总量。6G 卡 imgsz896 时 batch 压到 4开启 ampworkers 降到 2。还想保住 batch 的话用 640 训练 80 轮跑出基础权重再用 896 接着训练 30 轮做尺度微调这是显存紧张的性价比最高方案。这个血泪经验适用范围很广任何检测项目从 640 升级到更大分辨率都先按显存减半的预期去规划 batch。5.4 远距离小滑坡漏检但训练集里同类目标是能检出的现象GUI 推理时近处坡面的滑坡都能正常框出但远处山体上只有几十个像素的滑坡却全部漏掉训练集里的小目标样本明明能检测出来。原因训练时的 imgsz 和推理时不一致或者 Mosaic 增强虽然开了但缺乏针对性尺度增强。模型在 640 分辨率下对极小目标的特征已经严重下采样P3 层感受野覆盖不住。解决训练和推理 imgsz 统一到 896。还漏就做切块推理把原图按 2x2 切成四块每块放大两倍进模型检测完合并坐标回原图坐标系重叠区域的重复框用 NMS 过滤。ultralytics 的模型对象自带 nms 方法可以直接调。切块推理的代价是耗时翻倍但对静态图像巡检场景完全可接受实时视频才需要考虑专用小目标模型。6. 用 PyQt5 把 YOLO11 封装成桌面检测工具线程、参数与批量导出6.1 GUI 布局图像预览、参数面板和结果表格PyQt5 界面按左图右表的经典结构做左侧放 QLabel 显示检测结果图缩放交互用 QGraphicsView 承载右侧放参数面板置信度 QSlider、IoU 滑条、模型下拉框 QComboBox底部 QTableWidget 显示检测结果列依次是序号、类别名、置信度、左上角坐标、右下角坐标。滑条一拉动画面上的框和表格实时刷新注意这里是重新画框而不是重新推理推理结果缓存下来只重绘 overlay。检测摘要可以用 QTextBrowser 输出 HTML 格式表格和图共存于一个滚动视图里方便做巡检报告。6.2 用 QThread 跑推理界面卡死的根源与解法YOLO11 推理虽然快但在 GUI 主线程里同步跑图片加载和模型推理期间整个窗口会假死。常见做法是点击检测按钮后主线程把图片路径发给工作线程工作线程跑 model.predict完成后发信号回主线程更新界面。核心代码from PyQt5.QtCore import QThread, pyqtSignal class DetectThread(QThread): result_ready pyqtSignal(object, object) def __init__(self, model, img_path, conf, iou): super().__init__() self.model model self.img_path img_path self.conf conf self.iou iou def run(self): results self.model.predict( sourceself.img_path, confself.conf, iouself.iou, imgsz896, verboseFalse, ) boxes results[0].boxes self.result_ready.emit(self.img_path, boxes)conf 和 iou 从滑条读取imgsz 保持和训练一致。verboseFalse 关掉控制台刷屏不然每张图都会打印一堆日志。result_ready 信号连接主线程的槽函数槽里解析 boxes.xyxy、boxes.conf、boxes.cls再画框和填表格。模型加载放界面init里做一次绝对不要在每次检测时重复加载否则每次都要等两三秒权重文件解析这是新手最容易忽略的性能瓶颈。6.3 从能跑到能用批量导入、结果导出与模型迭代闭环单张检测跑通后再往下做就是批量。QFileDialog.getExistingDirectory 选文件夹遍历所有 jpg/png逐个丢给 DetectThread结果汇总进 QTableWidget最后用 csv 模块导出。导出的 CSV 除了类别和置信度一定带上原图文件名和框坐标这样后期核对漏检时能按文件名直接回找原图。检测完可以把每个框裁剪出来存到一个 evidence 文件夹做人工复核台账时非常有用。现在的习惯是任何模型交付前都会拿一套模型没见过的现场照片跑一遍批量检测把漏检的图单独拉出来看是小目标、遮挡还是背景复杂再回头补训练数据。这套做法帮助避免过很多次训练指标好看、现场一测露馅的翻车。希望帮到你。本文还有配套的精品资源点击获取
返回列表