简介面向地质勘探与计算机视觉交叉领域这份PDF系统讲解YOLOv11在岩石裂隙检测与三维地质建模中的联合优化方案。文档共23页结构完整内容从地质勘探面临的挑战切入逐步展开YOLO系列算法发展历程与YOLOv11网络结构、训练及检测流程并重点阐述数据采集与预处理、裂隙信息融合、系统架构设计等关键环节还配有系统实现与代码示例、实验结果对比和多个应用场景案例适合正在研究目标检测落地地质场景的工程师与相关专业学生参考。资源为单个PDF文件体积仅1.83MB支持目录章节跳转与大纲定位阅读体验完整涵盖引言、岩石裂隙检测与三维地质建模概述、YOLOv11原理剖析、联合优化方案设计、系统实现与代码示例、实验结果与分析、应用场景与案例、总结与展望等模块。目前已有85人学习使用既可快速理解YOLOv11地质应用的整体框架也能为模型优化、三维建模融合与工程落地提供方法借鉴。1. 为什么地质勘探团队开始用 YOLOv11 做岩石裂隙检测一个裂隙密集的关键边坡人工编录可能一周才能完成换成 YOLOv11 目标检测后半天出初稿——但这份初稿能不能被三维地质建模直接使用取决于你如何处理坐标、置信度和缺失裂缝。地质勘探里的岩石裂隙检测本质是在“石头纹理”这种高噪声环境里找细长小目标通用目标检测模型很容易翻车。这篇笔记讲我摸索过的完整链路用 YOLOv11 训练裂隙检测模型、把检测结果转成地质坐标、再用地质统计方法生成三维裂隙密度场并让它反过来指导模型迭代。适合工程地质、矿产勘探、岩土监测方向的人也适合刚接触目标检测但想快速跑通闭环的初学者——别怕后面每一步都给命令。2. 用 YOLOv11 做岩石裂隙检测网络结构、数据标注和最小训练闭环裂隙检测的第一道坎不是模型而是“裂隙到底是什么”。它不像行人、车辆那样有清晰的轮廓而是细长的线性弱纹理可能只有几个像素宽。很多团队直接套用 YOLOv5 默认配置结果损失函数看着还行可视化后裂隙全被漏掉。所以我先把目标特点讲清楚再给标注转换脚本和最小训练命令。2.1 裂隙检测为什么挑 YOLOv11小目标优化与网络结构的关系YOLOv11 在 ultralytics 生态里是可安装、可训练、可导出的一套完整工具链也是当前做视觉检测时最快出结果的选项。它的 backbone 用了更轻量的跨阶段结构并在高层特征里引入了注意力机制整体对多尺度特征的保留比 YOLOv8 更强。裂隙检测最怕的是“细线在深采样层里被磨没了”YOLOv11 的 neck 部分做了更密集的自上而下融合让浅层位置信息和高层语义信息能同时出现在输出特征图上这对小目标优化非常关键。我选择 YOLOv11 不是因为它的公开精度分数比谁高一个点而是因为它把权重文件下载、网络结构配置、训练自己的模型都收敛成了几条命令地质团队不需要养一个算法工程师也能跑通。裂隙检测的应用场景往往是野外高分辨率正射影像或岩芯扫描图图像尺寸动辄 6000×4000目标宽度占全图不到 1%所以“小目标优化”不是一个可选项而是必选项。YOLOv11 输入分辨率可以拉到 1280 甚至 1536加上注意力机制比老模型在背景纹理干扰下更稳。另外要明确一个边界YOLOv11 是框检测不是线检测。它能告诉你“这里有一组裂隙”但不能直接输出裂隙中心线和长度。所以后面的三维建模需要把框转成几何参数这一步我会在第 4 章展开。先确认你能稳定检测再谈三维。2.2 标注裂隙格式转换脚本从标注软件到你自己的模型常见做法是用 labelImg 或 X-AnyLabeling 这类工具导出 VOC 格式 XML 或 YOLO 格式 txt。但很多测绘和地质人员习惯用 ArcGIS、QGIS 里画矢量线导出的是 Shapefile 或 GeoJSON。做目标检测前需要把这些统一转成 YOLO 训练的 txt 格式。裂隙标注的细分规则要和业务对齐。我一般约定两种类别fracture表示明显张开的裂隙带crack_zone表示破碎带或隐裂隙密集区。不要在一个框里塞入一条几十米的完整裂隙建议按图像分辨率和业务需求切成多段每段长度控制在几百像素以内。这样模型学的是“局部裂隙特征”而不是“一整条线”。下面这段脚本把 VOC 格式 XML 转成 YOLO 训练 txt核心是把绝对像素坐标归一化为 01 的相对坐标。YOLO 每行格式类别索引、中心点 x、中心点 y、框宽、框高。import xml.etree.ElementTree as ET from pathlib import Path def convert_voc_to_yolo(xml_path: Path, out_dir: Path, class_map: dict): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_map: continue box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) x_center (xmin xmax) / 2.0 / img_w y_center (ymin ymax) / 2.0 / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h lines.append(f{class_map[name]} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) out_path out_dir / (xml_path.stem .txt) out_path.write_text(\n.join(lines), encodingutf-8) # 用法示例 class_map {fracture: 0, crack_zone: 1} convert_voc_to_yolo(Path(a.xml), Path(labels), class_map)这段脚本只处理水平框。如果裂隙方向集中在某个倾角可以后续改用 OBB 旋转框但坐标转换脚本要变成四点坐标。第一版不建议上 OBB因为标注成本高且后续三维建模时仍然要转回中心点和方向角。2.3 从环境配置到训练自己的模型最小命令与权重文件说明环境配置是纯小白最容易卡住的地方实际上只需要三行命令就能建好环境。这里用 conda 建独立环境避免把系统 Python 搞乱。conda create -n geo_yolo python3.10 -y conda activate geo_yolo pip install ultralytics安装完成后先确认yolo命令可用。权重文件不需要手动去翻 GitHubYOLOv11 的yolo11n.pt等预训练权重会在第一次运行时自动下载。接下来准备数据配置文件指向你的训练、验证数据和类别名YAML 内容大致如下。path: ./fracture_data train: images/train val: images/val names: 0: fracture 1: crack_zone然后启动训练命令。这是最小可训练闭环yolo detect train datarock_fracture.yaml modelyolo11n.pt \ epochs150 imgsz1280 batch4 device0这条命令里modelyolo11n.pt是网络结构加预训练权重yolo11n是轻量档显存不够时可以选它。imgsz1280是这次训练最关键的参数因为裂隙是细长目标640 输入下很多小裂隙直接被压缩成 1 个像素模型根本学不到。batch4在 8G 显存下比较稳如果翻车就降到 2后面再讲梯度累积的思路。epochs150对中等规模数据集足够但更重要的指标是看runs/detect/train/weights/best.pt的验证集 mAP。3. YOLOv11 训练调参与推理结果保存小目标优化与坐标提取训练结束时你以为完事了其实三维建模的工程问题才刚开始。模型权重只是给了你一张图里“哪里像裂隙”地质建模需要的是“这个裂隙在哪、多长、什么走向、置信度有多高”。所以这一章先讲调参再讲推理结果怎么保存成结构化文件最后讲小目标优化路线。3.1 三个必调参数imgsz、mosaic、学习率以及显存翻车时的处理训练参数里我优先推荐这张表按地质图像体量直接参考参数推荐值说明imgsz1280小于等于 960 会让细裂隙特征丢失batch48G 显存稳妥值16G 可试 8mosaic0.5关闭或降低避免裂隙被拼接边界切断lr00.005野外数据集噪声大默认 0.01 容易震荡close_mosaic10最后 10 轮关闭 mosaic让模型适应真实分布ampTrue混合精度训练稳定省显存命令对应写成这样会更好我建议最后 10 轮关闭 mosaicyolo detect train datarock_fracture.yaml modelyolo11n.pt \ epochs150 imgsz1280 batch4 device0 \ mosaic0.5 close_mosaic10 lr00.005 ampTrue如果你显存不够不要只压缩一个参数。常见做法是batch2 imgsz960 ampTrue再配合切图训练。把大图切成 640×640 的 patch 再喂给模型也能训练但 patch 之间会丢失上下文。切图训练的核心是不要切出“没有裂隙”的空白块占太多比例不然模型会学到“检测地面”。我的经验是先用整体图训练一个粗糙模型再用切图推理做密集检测这样比一开始就切图训练省时。3.2 推理与保存把 YOLOv11 预测结果保存成 txt/json喂给建模程序推理阶段最关心的是结果保存格式。YOLOv11 预测后保存有多种方式我建议同时开启save_txt和save_json前者方便快速看后者方便后续脚本读取。命令如下。yolo detect predict modelruns/detect/train/weights/best.pt \ sourcefield_images save_txtTrue save_confTrue \ save_jsonTrue imgsz1280 conf0.25 iou0.5注意几个坑conf0.25不要把置信度阈值设太高野外裂隙的纹理对比度低很多有效目标置信度只有 0.20.4设成 0.5 会把中长裂隙漏掉。iou0.5是 NMS 的并交比阈值裂隙框大多是细长框邻框重叠模式很复杂0.5 比较稳。save_txtTrue生成的文件中每行是类别 中心x 中心y 宽 高 置信度这些坐标是归一化到图片尺寸的。三维建模应用时要把归一化坐标乘回原始图像宽高再用相机标定参数转换到地质坐标。3.3 小目标优化路线切图推理、提高分辨率、不要迷信公开权重小目标优化是热词但实际操作就三条路提高输入分辨率、切图推理、后处理合并。野外正射影像很大直接全图推理经常会漏掉宽度只有两三个像素的裂隙。切图推理是最有效的工程手段把大图切成多个 patch每个 patch 独立检测再映射回原图。from ultralytics import YOLO import numpy as np model YOLO(best.pt) img np.array(Image.open(big_slope.jpg)) # 大图 patch_size, overlap 640, 64 step patch_size - overlap boxes [] for y in range(0, img.shape[0], step): for x in range(0, img.shape[1], step): patch img[y:y patch_size, x:x patch_size] result model.predict(patch, imgszpatch_size, conf0.25, verboseFalse) for det in result[0].boxes: cx, cy, w, h, conf, cls det.data[0].tolist() # 坐标映射回原图 box [x cx - w / 2, y cy - h / 2, x cx w / 2, y cy h / 2, conf] boxes.append(box)这段代码的核心是两个参数patch_size640要和训练输入尺寸接近太大上下文好但显存压力大太小会让裂隙特征在 patch 里占比不稳定overlap64用来避免裂隙正好卡在 patch 边界。切图后经常出现同一条裂隙被相邻 patch 重复检测后处理阶段要用 NMS 合并。我一般把重合度大于 0.3 的框按置信度加权合并否则后续密度统计会翻倍。4. 从裂隙检测到三维地质建模坐标变换、裂隙密度场和联合优化流程模型输出的框只是像素坐标系里的矩形三维地质建模需要真实坐标和几何参数。这一章是把“图像检测”和“三维地质建模”连接起来的关键也是标题里“联合优化方案”的核心。每一步都直接影响地质体体积估算、渗透率模拟和边坡稳定性分析的结果。4.1 坐标配准像素到地质坐标的最简做法如果只是一张野外露头照片最常见做法是用 4 个以上控制点求单应矩阵。控制点可以用 RTK 或全站仪测出坐标然后在图像上精确点选。我用cv2.findHomography求变换矩阵再用矩阵把像素中心点投影到地质平面上。注意野外照片要先做镜头畸变校正否则框的中心点偏差会随距离放大。import cv2 import numpy as np # 图像像素坐标每个元素是 (px, py) src np.array([[x1, y1], [x2, y2], [x3, y3], [x4, y4]], dtypenp.float32) # 对应地质坐标每个元素是 (east, north) dst np.array([[e1, n1], [e2, n2], [e3, n3], [e4, n4]], dtypenp.float32) H, _ cv2.findHomography(src, dst, methodcv2.RANSAC) def pixel_to_geo(px, py): p np.array([px, py, 1.0]) g H p return g[0] / g[2], g[1] / g[2]RANSAC 能剔除部分选点误差但如果控制点少于 4 个会失败所以我习惯在勘测图里布 6 个以上控制点多出来的点用于交叉验证。对无人机正射影像如果已经做过正射校正H 会接近仿射变换且不需要考虑镜头畸变对近景广角照片先做相机标定和畸变校正再做投影。这里最常翻车的点是把未校正的广角图像直接假设为平面导致三维密度场出现“幽灵断层”。4.2 检测结果转三维裂隙参数中心点、迹长、方位角与裂隙密度有了坐标变换函数我可以把 YOLOv11 的推理 JSON 转成点云和裂隙属性。常见做法是取每个框的中心点作为裂隙采样点用框的长宽和对角线近似迹长。这个近似对大型张开裂隙够用对小裂纹会有偏差但胜在稳定可复现。import json import numpy as np with open(runs/detect/predict/predictions.json, encodingutf-8) as f: preds json.load(f) points [] for pred in preds: img_w pred[image][width] img_h pred[image][height] for det in pred[predictions]: x1, y1, x2, y2 det[box][x1], det[box][y1], det[box][x2], det[box][y2] geo_x, geo_y pixel_to_geo((x1 x2) / 2, (y1 y2) / 2) length_px np.hypot(x2 - x1, y2 - y1) length_m length_px * scale_meter_per_pixel # 从已知标尺换算 angle np.degrees(np.arctan2(y2 - y1, x2 - x1)) % 180 points.append({ x: geo_x, y: geo_y, confidence: det[confidence], length_m: length_m, angle_deg: angle })这段代码把每个检测框变成一个带置信度的空间点。这里有一个从血泪里总结出来的细节裂隙的走向角不能用简单atan2(y2-y1, x2-x1)直接得出结论因为框的宽边不一定对应裂隙长轴。要先判断长轴是水平还是垂直方向再取对应方向向量。上面代码给了近似但正式项目我会再加一步把同一裂隙的碎片用 DBSCAN 聚类按角度一致性合并再重新拟合中心线。否则一条 5 米裂隙被识别成 10 段密度统计会严重偏高。4.3 联合优化方案把检测置信度变成地质统计权重让插值更可信三维地质建模中裂隙密度场通常用克里金插值或离散裂缝网络模拟。联合优化的含义是检测结果和三维模型不是单向流动而是迭代反馈。第一版模型会漏掉低对比度裂隙密度场在局部区域会呈现凹陷这时候用三维模型模拟这些区域的裂隙网络再渲染成图像回填到训练集重新训练检测模型。在插值环节我用检测置信度作为“观测值而不是把每个框都当作确定性记录。置信度低的地方插值权重应该降低。使用 gstools 或 PyKrige 做克里金插值时可以在协方差模型中引入块金效应来表示观测噪声。下面是简化的流程from gstools import Gaussian, Krige coords np.array([[p[x], p[y]] for p in points]) values np.array([p[confidence] for p in points]) # 0~1 model Gaussian(dim2, var0.5, len_scale15.0) krige Krige(model, coords[:, 0], coords[:, 1], values, driftlinear) grid_x np.linspace(xmin, xmax, 100) grid_y np.linspace(ymin, ymax, 100) field, variance krige.structured((grid_x, grid_y))这里的var0.5是裂隙发育强度对置信度方差的估计len_scale15.0是地质统计学的变程代表裂隙空间相关性衰减到零的距离。这两个参数需要根据现场露头规模和人工编录做校验不能拍脑袋。联合优化闭环中我会比较插值后的裂隙密度分布和实测钻孔 RQD 值如果偏差大就回头调整检测阈值、切图参数和克里金模型。这套流程在项目结束时能给出一个“可信区间”而不是单纯一张热力图。5. YOLOv11 岩石裂隙检测的四大翻车现场避坑与排查清单裂隙检测和三维建模这条链路里训练代码本身不容易出错真正让人加班的是环境和数据问题。我按亲身踩过的坑整理成清单每条都给出现象、原因和解决路径。5.1 训练期翻车显存不足与低召回并存现象一训练到一半退出提示CUDA out of memory把 batch 从 4 改到 2 还是不行。最后发现是imgsz1280在单卡 8G 显存下本身就紧张加上 mosaic 会让计算临时峰值更高。原因imgsz、batch、mosaic三个因素是显存峰值叠加导致的不是单一参数问题。地质图像普遍分辨率高imgsz1280虽然有效但对显存不友好。解决我把ampTrue打开batch2imgsz960并关闭前 20 轮 mosaic。如果还不行就用切图训练把训练图像切成 640 patch。这个方案在小裂隙召回率和显存占用之间找到了平衡点比硬调batch1更合理。现象二训练 loss 在下降验证集 mAP 卡在 0.2 以下可视化输出显示裂隙全部漏检只框出破碎带。原因裂隙是细长小目标默认 anchor 尺寸和训练增强会把它缩没。mosaic1.0时四条裂隙图拼在一起每一条被缩到极小模型学不到有效特征。解决训练时降低mosaic0.5并设置close_mosaic10让模型最后适应单图真实分辨率。如果数据集里长框占比高可以考虑把输入分辨率提升到 1536但显存不允许时优先切图推理。5.2 部署与建模期翻车域迁移、重复检测与坐标误差现象三模型在 A 矿山测试效果很好换到 B 矿山后 mAP 直接掉一半漏检大量暗色裂隙。原因这是典型的域迁移问题。不同地区岩石颜色、光照、表面风化程度差异大YOLOv11 学习到的还是训练集的颜色和纹理组合而不是“裂隙”的抽象几何特征。解决我一般分两步。第一步在训练时加入随机颜色扰动、灰度化和随机擦除模拟不同岩石表面。第二步从 B 矿山取 5080 张代表性图像快速标注用当前权重继续训练 30 轮微调比重新训练更有效。大量真实项目的模型都是靠“现场数据微调”保持分数的不要指望一个公开权重在所有岩性上通吃。现象四同一裂隙在切图推理后形成 4 段重复框统计密度时裂隙条数翻倍三维建模出现局部高密度团块。原因切图推理的overlap相邻区域会重复检测同一目标后处理 NMS 阈值设置太高没有合并线性重复框。解决后处理采用两个步骤第一步是普通 NMS把重叠度大于 0.5 的框去掉第二步是相隔一定距离但方向一致的框按长度连续性合并用 DBSCAN 按角度和中心点距离聚类。三维建模时我只用合并后的线段不用原始框。现象五三维密度场在局部区域出现明显的断层态检查 Kriging 插值没问题但对照现场发现那个区域根本没那么多裂隙。原因坐标变换矩阵出错了或者检测框的像素坐标没有统一到同一坐标系。最常见的是把归一化坐标直接当成像素坐标用漏乘了原始图像宽高或者挑选控制点时选错了一个角点单应矩阵局部扭曲。解决每次推理保存后先做一个自检把 10 个检测框的中心点用pixel_to_geo变换后画回无人机正射图看是否与原始裂隙位置对应。对控制点做 RANSAC 残差检查残差超过 2 个像素的点要剔除。地质建模对厘米级偏差不敏感但米级偏差会让整个密度场失真。6. 让联合优化真正闭环合成数据回填与置信度验证的进阶玩法走到这一步你已经有了一个能用的检测模型、一个能插值的密度场。传统流程到这里就结束了但“联合优化”的价值在于让两边互相修正。我常用的进阶做法是用三维裂隙网络模型生成合成图像模拟不同岩性和光照条件下的裂隙表现经渲染后加入训练集。这种做法能明显提升模型对新矿山的泛化能力前提是合成数据里要保留真实的比例、宽度和形态不能只画几条白线。验证方法上我习惯用 TTA测试时增强给每个检测框一个稳定性度量例如对同一张图做水平翻转和尺度变化如果三次检测都命中说明该裂隙是稳定的地质特征而不是光照伪影。把稳定度乘到置信度上再作为克里金插值的观测值会比只依赖原始置信度更可信。还可以用留一法每次抽出一个区域的实测裂隙密度与模型生成的密度场对比计算相对误差误差控制在 15% 以内我才认为这个联合优化方案合格。我以前总迷信高 mAP后来在一个边坡项目里翻车模型在测试集上 mAP 0.78但三维渗流模拟结果和实测钻孔数据差了几十倍因为漏掉的裂隙刚好是地下水通道。从那以后我改成了“先跑通最小闭环再优化网络”的习惯——先让检测到建模的链路能输出一个合理的密度场再回头调模型参数。这个顺序看起来慢实际是省时间因为很多后处理合并、坐标转换问题会提前暴露。希望帮到你。本文还有配套的精品资源点击获取