免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

岩石矿物YOLO数据集详解与训练避坑指南

岩石矿物YOLO数据集详解与训练避坑指南 简介面向地质学与矿业智能识别场景这份“岩石表面矿物质检测数据集”提供超过1000张高分辨率岩石图片及对应标注覆盖石英、斑铜矿、黄铁矿等8类矿物适合使用YOLO系列目标检测算法开展训练与验证的算法工程师、地质科研人员及入门学习者。数据已转换为YOLO格式并完成数据增广可省去格式转换与预处理环节配套训练集、验证集划分、class类别文件和show脚本便于直接训练、快速可视化检测边界框。整个压缩包共2000个文件以1138个txt标签文件、861张jpg图片及1个py可视化脚本为主资源包大小59.08MB结构紧凑实用。已有454人浏览学习。借助该数据集用户可以快速搭建岩石矿物自动检测流程减少数据清洗和标注成本同时通过展示脚本直观评估模型在岩石表面目标识别上的表现为进一步优化检测精度提供了完整基础。1. 岩石表面矿物质检测数据集超过1000张图YOLO格式直接开训做目标检测项目最烦的不是调参是找数据。尤其是地质、矿业这种垂直场景公开数据集少得可怜能直接喂给YOLO的更是稀缺。这套岩石表面矿物质检测数据集超过1000张带标签的高分辨率图片已经转成YOLO格式训练集、验证集划分好还带了class文件和可视化脚本下载下来就能开训。对正在做地质勘探自动化、矿物识别、岩矿鉴定相关项目的工程师和研究生来说省掉的不是一两天是整个数据准备阶段。8个矿物类别覆盖石英、斑铜矿、黄铁矿这些常见矿物量不大但做迁移学习、效果验证、算法对比完全够用。接下来直接拆目录结构、标签格式、训练细节和踩坑点。2. 数据集结构与YOLO格式先搞清文件组织再动手2.1 目录结构images、labels、data.yaml 一套齐活拿到数据集第一步不是急着训练是先看目录结构搞清楚每个文件是干什么的。这套数据集是标准的YOLO组织方式下载解压后大概是这样的rock_mineral_dataset/ ├── train/ │ ├── images/ # 训练集图片 │ │ ├── 0011_jpg.rf.7a7655516b6ade13a199ad135383cba7.jpg │ │ └── ... │ └── labels/ # 训练集标签 │ ├── 0011_jpg.rf.7a7655516b6ade13a199ad135383cba7.txt │ └── ... ├── valid/ │ ├── images/ # 验证集图片 │ └── labels/ # 验证集标签 ├── test/ # 有的数据集有有的没有 ├── data.yaml # 类别配置和路径配置 └── classes.txt # 类别清单train和valid下的images、labels一一对应文件名完全相同只是扩展名不同。jpg对应txt这个对应关系是YOLO系列训练的前提。图片和标签文件名里的.rf.字段说明这份数据经过 Roboflow 平台导出这直接决定了标签格式和data.yaml的写法后面细说。提示拿到数据集后第一步先数一下train和valid里图片数量和标签数量是否一致。不一致的话训练过程会报「Cant find label」的错或者静默跳过某些图片导致实际训练样本比预期少。2.2 标签内容解读归一化坐标和类别ID打开任意一个txt标签文件你会发现每行5个数字对应一个目标框。格式是class_id x_center y_center width height具体数值示例0 0.4512 0.5633 0.1234 0.0891 2 0.7890 0.2341 0.0567 0.0678这些坐标全是归一化的范围在0到1之间是相对于图片宽高的比例。比如x_center0.4512表示目标框中心点在图片从左往右45.12%的位置。类别ID从0开始计数对应classes.txt里的行顺序。classes.txt内容类似quartz bornite pyrite ...这个文件决定了模型输出的类别索引和实际矿物名称的映射关系训练前必须确认data.yaml里的类别列表和classes.txt完全一致。2.3 data.yaml的坑路径写绝对还是写相对data.yaml是所有YOLO训练入口的配置文件里面定义了train路径、val路径和类别名。这套数据集的data.yaml大致长这样train: ../train/images val: ../valid/images nc: 8 names: [quartz, bornite, pyrite, ...]这里最容易翻车的点在于路径。Roboflow导出时的默认路径可能是绝对路径比如C:/Users/xxx/rock_mineral_dataset/train/images换了一台机器根本找不到。我拿到任何数据集的第一件事就是把data.yaml里的路径改成相对路径然后整个数据集文件夹放到项目目录下这样换机器不会出问题。另外要注意nc参数必须和names列表长度一致。有个偷懒校验方法是数一下names里的引号数量8个类别就是8个名字nc写成8不一致的话YOLO训练直接报错连模型都不会加载。3. 数据增广与训练集划分泛化能力从哪里来3.1 已有的增广做了什么这套数据集做了数据增强常见做法是旋转、翻转、缩放、亮度调整的组合。增广的意义不是制造更多图片而是模拟不同光照条件、拍摄角度下的岩石表面状态。野外采集的岩石照片光照强弱差异极大同一块石英逆光和侧光下视觉特征完全不同。如果训练集里全是同一光照条件下的图片模型会把光照当成矿物特征的一部分换一批图片效果立刻崩掉。但增广也是有代价的。过度的几何变换会让矿物纹理失真尤其是黄铁矿这种靠晶面反光特征识别的矿物旋转90度加上亮度抖动可能让标注框里的目标看起来不像黄铁矿。所以增广比例需要克制一般控制在原图数量的1.5到3倍比较合适。3.2 划分比例问题验证集够不够用数据集已经做了train/valid划分默认比例一般是80/20或70/30。这里有一个常被忽略的问题如果原始图片只有1000多张验证集可能只有200多张每个类别分下来可能只有20到30个目标框。对于8个类别的检测任务这个验证集规模评估出来的mAP波动会比较大。我习惯在训练前自己重新划分一次或者至少检查一下现有划分是否均匀。划分脚本如下import os import random import shutil # 统计每个类别在train和valid里的目标框数量 def count_labels(labels_dir, nc8): counts [0] * nc for f in os.listdir(labels_dir): if not f.endswith(.txt): continue with open(os.path.join(labels_dir, f), r) as fh: for line in fh: cls_id int(line.strip().split()[0]) counts[cls_id] 1 return counts train_counts count_labels(rock_mineral_dataset/train/labels) valid_counts count_labels(rock_mineral_dataset/valid/labels) for i in range(8): print(fclass {i}: train{train_counts[i]}, valid{valid_counts[i]})这个脚本的作用是把每个类别在训练集和验证集中的目标框数量分别统计出来。如果发现某个类别在valid里只有个位数目标框说明这个类别的验证结果不具备统计意义。这个时候需要手动从训练集挪一些样本到验证集或者采用k-fold交叉验证的方式训练。注意重新划分数据集时图片和对应txt标签文件必须一起移动只挪图片不挪标签或者反过来训练时就会出现图上没框、框没图配的情况。血的教训。3.3 数据集量级与迁移学习策略1000多张图、8个类别这个数据量从头训练YOLO是铁定过拟合的。常规做法是加载COCO预训练权重冻结前若干层只训练检测头。具体做法在YOLOv5里是python train.py --data rock_mineral_dataset/data.yaml --weights yolov5s.pt --freeze 10 --epochs 100 --batch 16--freeze 10的意义是冻结前10层这些层学到的是通用视觉特征边缘、纹理、颜色对域不敏感直接复用后面层微调去学矿物特有的判别特征。这个策略在这个数据量级下基本是最优解。4. show脚本可视化训练前必须做的检查4.1 可视化脚本的价值数据质量是整个训练流程里最关键也最容易出问题的环节。标签坐标写错、类别标错、图片旋转没同步标签这些问题靠肉眼审阅txt文件很难发现但一可视化就全暴露了。这套数据集自带的show脚本就是干这个的。如果没有脚本我一般自己写一个import cv2 import os import numpy as np def show_bbox(img_path, label_path, class_names, save_pathNone): img cv2.imread(img_path) h, w img.shape[:2] with open(label_path, r) as f: lines f.readlines() for line in lines: cls_id, x_c, y_c, bw, bh map(float, line.strip().split()) # 反归一化把0-1的坐标换算回像素坐标 x1 int((x_c - bw / 2) * w) y1 int((y_c - bh / 2) * h) x2 int((x_c bw / 2) * w) y2 int((y_c bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, class_names[int(cls_id)], (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) if save_path: cv2.imwrite(save_path, img) else: cv2.imshow(check, img) cv2.waitKey(0) cv2.destroyAllWindows() # 遍历验证集前50张 labels_dir rock_mineral_dataset/valid/labels images_dir rock_mineral_dataset/valid/images for i, fname in enumerate(os.listdir(labels_dir)): if i 50: break if not fname.endswith(.txt): continue img_name fname.replace(.txt, .jpg) img_path os.path.join(images_dir, img_name) label_path os.path.join(labels_dir, fname) show_bbox(img_path, label_path, class_names, save_pathfvis_{i}.jpg)这段代码的逻辑是从标签文件读取每一行把归一化坐标乘以图片宽高还原成像素坐标画框和类别名。核心参数是反归一化的换算过程写错的话画出来的框就会偏移到搞笑的位置。可视化结果存成图片方便批量检查不必一张一张弹窗查看。4.2 可视化检查的三个重点抽检时重点关注三类问题。第一类是框的大小是否合理。如果很多框占图片面积的80%以上可能是标注粒度太粗把整个岩石表面框进去而不是框单个矿物颗粒反过来如果框都特别小可能是忘了标注一些小目标。第二类是框和矿物纹理是否对齐。人工标注难免有偏移轻微的没问题但如果偏移超过10%的面积模型训练时就会学到错误的位置信息。第三类是类别是否肉眼可辨。如果石英和黄铁矿标注相互混用说明标注人员的标准不统一这种情况必须回头修正标签不能指望模型自己学会区分错误标注。4.3 文件夹级批量检查单张可视化效率太低更实用的是批量生成缩略图拼版检查。用上面的脚本把所有验证集图片都输出到vis_output文件夹然后用图像拼接工具把几十张小图拼成一张大图肉眼扫一遍就能发现问题。这一步花费的时间不超过30分钟但能避免训练了十几个小时后才发现标签错位的惨剧。5. 训练避坑八类标签里的常见问题与排查5.1 现象训练loss正常下降但mAP一直在0.3左右上不去原因最常见的是类别不平衡问题。岩石表面矿物分布天然不均匀石英可能占了50%以上的标注框而斑铜矿可能只有几十个框。模型把绝大多数精力用来学石英的特征其他类别几乎没学到。验证集上石英的AP可能到0.8但少数类别的AP只有0.1左右整体mAP就被拉下来了。解决先跑一下2.2节那个统计脚本确认每个类别的目标框数量。差距超过一个数量级的用类别权重或者在损失函数里调整每个类别的惩罚系数。YOLOv5里用--cls 0.8提高分类损失的权重配合数据增广补充少数类样本。5.2 现象训练loss为nan或者验证集loss出现剧烈震荡原因先检查学习率默认学习率在1000张图这样的数据集上通常偏高到后半程容易出现震荡。再检查标签文件里有没有异常的bbox坐标比如x_center大于1或者width为负数。这种脏数据在训练时会让loss变成nan然后整个训练过程就废了。解决批量检查标签文件过滤掉坐标不在0到1范围内的行。如果是Roboflow导出的数据理论上不应该有问题但经过手动修改或者二次处理时很容易引入脏数据。写一个清洗脚本把所有标签读一遍过滤异常行再写回def clean_labels(label_path): valid_lines [] with open(label_path, r) as f: for line in f: parts line.strip().split() if len(parts) ! 5: continue cls_id, x_c, y_c, bw, bh map(float, parts) if 0 x_c 1 and 0 y_c 1 and bw 0 and bh 0: valid_lines.append(line) with open(label_path, w) as f: f.writelines(valid_lines)5.3 现象训练集loss很低验证集loss不断上升原因典型的过拟合。数据集只有1000多张图模型容量大容易把训练集样本的特征背下来。尤其岩石表面纹理细节丰富背景复杂模型很容易学到「记住这张图的纹理分布」而不是「学会识别石英的通用特征」。解决除了加载预训练权重外增加数据增强的强度开启mosaic增强把多张图拼接起来训练。同时early stopping的patience设置得小一点比如YOLOv5里--patience 20验证集loss连续20轮不降就停避免浪费时间。另外一个有效手段是把输入分辨率调低到416让模型被迫关注整体结构而不是细节纹理图像分辨率和模型复杂度的匹配直接影响泛化性能。5.4 现象预测时大量误报把背景纹理识别成矿物原因训练时背景和矿物的区分度不够。岩石表面本身就是高纹理表面有的矿物和背景的灰度值接近模型学到的可能不是「矿物的形状、颜色特征」而是「某个纹理区域大概率有矿物」。这个问题在野外光线不均匀的照片上尤其突出。解决如果数据集的增广里没有包含随机擦除Random Erase可以在训练时开启。这个策略随机遮挡图片的一部分迫使模型学习目标的整体特征而不是局部纹理。YOLOv5的--augment参数可以开启更激进的增广组合包括随机擦除、色调抖动、饱和度抖动。刚开始训练看到loss波动大是正常的增广越激进收敛越慢但最终的鲁棒性会好很多。5.5 现象valid和train的mAP差距不大但实际部署时效果很差原因数据划分太随机train和valid里的图片可能来自同一个拍摄现场背景纹理高度相似相当于变相的数据泄露。模型在验证集上看起来不错一旦部署到新的采集环境就露馅了。这个问题在小的私有数据集上非常普遍。解决按采集场景分组划分数据同一个拍摄场景的图片要么全在训练集要么全在验证集。如果数据集没有提供分组信息就按照文件名的前缀去分。这属于经验判断没见到具体文件结构不好说但值得花时间做。6. 进阶小目标矿物的专项调优与验证方法这套数据集的检测目标是岩石表面的矿物和COCO数据集里的常规目标相比最大的问题是目标尺度差异大。有的矿物颗粒有拳头大在图片里占据几百个像素有的矿物颗粒只有指甲盖大小可能就十几个像素。YOLO的默认锚框是基于COCO数据集统计出来的直接用在岩石矿物上小目标检出率会明显偏低。我现在拿到新数据集后的固定套路是先用默认锚框跑一轮baseline记录每类矿物的AP。然后跑YOLO自带的锚框自适应脚本基于训练集的目标框尺寸重新聚类python train.py --data rock_mineral_dataset/data.yaml --weights yolov5s.pt --epochs 50 --batch 16 --noautoanchor第一次自动锚框计算会在启动时打印新的锚框值对比一下和默认锚框的差距。如果新的锚框尺寸整体偏小说明数据集里小目标占比远高于COCO这时候可以开启--noautoanchor关闭自动计算改为手动调整。再训练时关注小目标的mAP看看是否有改善。输入分辨率也是一个关键参数。YOLOv5默认是640×640但岩石矿物的纹理细节对小目标识别影响很大提升到960甚至1280小目标的mAP通常能涨几个点。代价是训练速度变慢、显存占用变大。我用过的惯例是先640跑通流程再换960做最终版本。类别不平衡在这类地质数据集里几乎无法避免除了调整损失权重之外我还习惯在验证阶段按类别分别输出AP而不是只看整体的mAP。只关心石英的AP还是关心所有8个类别的平均性能直接决定训练策略的选择。如果某个类别目标是漏检重灾区可以用数据拼接的方式把该类别与其他类别组合成一张训练图让模型在每个batch里都看到这个类别。上面项目用Roboflow做增广时已经做了一部分工作但Roboflow的增广是离线增广效果有限。从那以后我每次训练任何数据集都会强制走一遍「统计类别分布 → 可视化抽检 → 清洗标签 → 跑baseline → 按类别查AP」这个流程。看起来多花了几小时但能从源头排除掉数据问题后面调参时才不会像无头苍蝇一样乱试。这套岩石矿物数据集对做地质目标检测入门来说手感不错标签质量和格式规范程度都算上乘希望帮到你。本文还有配套的精品资源点击获取
返回列表