☰
岩石矿物检测数据集:超1000张YOLO标注图,让目标检测训练少走弯路
2026/10/1 17:27:30 网站建设 项目流程

简介:一份面向地质学、矿业工程与计算机视觉研究者的目标检测数据集——岩石表面矿物质检测数据集,内含861张岩石表面jpg图像及对应1138个txt标注文件,已按YOLO格式完成预处理并做数据增广,可直接用于YOLO系列网络训练,省去格式转换环节;数据集划分了训练集与验证集,附class类别文件,并配有show.py脚本,可将检测框绘制到原图上,便于调试和评估模型。整体压缩包共2000个文件,大小约59.08MB,除图像与标签外另含1个Python可视化脚本,txt记录类别与边界框坐标,jpg为高分辨率岩面图像,py用于结果展示。类别覆盖石英、斑铜矿、黄铁矿等8种常见矿物,标签清晰、结构规范,能直接支撑矿物识别与定位实验。目前已有455人浏览学习,适合需要快速获取标注矿样数据、训练目标检测模型或验证算法性能的工程师与研究者。

1. 岩石表面矿物质检测数据集:超过 1000 张图和标签,拿到手就能训 YOLO

如果你是做地质、矿业或者材料视觉方向的人,可能体会过这种滋味:想训一个矿物识别模型,第一件事不是调参,而是到处找带标注的图片。公共数据集不是缺岩石类样本,就是几十张图只够当 demo 用,根本扛不住训练。

这份岩石表面矿物质检测数据集,超过 1000 张图片和标签,针对岩石表面场景收集。图片不是原始堆砌,而是已经处理成 YOLO 格式,也就是每个标注框和类别都写在同名 txt 文件里,数据集本身也划分好了训练集和验证集,并包含了 class 类别文件。对新手来说,最容易卡住的数据预处理环节已经被跨过了一大半;对熟手来说,这份数据可以直接拿来当训练基准,或者做迁移学习的起点,适配 YOLO 全系列网络。它适合两类人:一类是刚接触目标检测,想用现成数据完整走一遍训练流程的同学;另一类是矿物、地质检测方向的研究者,想快速验证 YOLO 在不规则纹理目标上的效果。整份资源的核心价值就一句话——省去从零整理的脏活,把时间留给模型和数据本身。

2. 从压缩包到可训练数据:读懂文件构成与 YOLO 标签格式

拿到数据集后,第一件事不是急着训练,而是先把文件结构和标签格式摸清楚。很多翻车事故都发生在这一层:路径配错、标签没对上、图片和 txt 编码不一致,后面所有训练结论全部作废。这一章先把格式讲透。

2.1 目录结构与文件分布

解压后,你看到的文件名长这样:

0011_jpg.rf.7a7655516b6ade13a199ad135383cba7.jpg 0011_jpg.rf.7a7655516b6ade13a199ad135383cba7.txt 0070_jpg.rf.16ee84cd49c4df36a32a40a4f9c98b9e.jpg 0070_jpg.rf.16ee84cd49c4df36a32a40a4f9c98b9e.txt

注意,图片和标签是同名文件,只是扩展名不同。文件名中间那串哈希字符是标注工具生成时留下的唯一编号,不需要关心它的含义,只要保证一对图片和 txt 的名字完全一致就行。这个数据集默认采用 Roboflow 系的数据组织方式,常见的目录结构是 images 与 labels 分开存放,外加 train.txt、valid.txt、class.txt 这类索引和类别文件。

# 解压后先统计图片和标签是否一一对应 unzip rock_mineral_dataset.zip -d rock_mineral cd rock_mineral find . -name "*.jpg" | wc -l find . -name "*.txt" | wc -l # 输出两个数字,正常情况下应该完全相等

如果图片数大于标签数,说明存在漏标注的图片;如果标签数大于图片数,说明有残留的无效 txt,建议单独建一个文件夹存起来,避免混入训练集。我一般会顺手跑一个脚本,把只有图没有 txt 的文件挑出来,单独备份而不是直接删,万一后面要对齐验证集还要回头查。

2.2 标签坐标:归一化后的四个字段

YOLO 格式的每个 txt 文件里,每行对应一个目标,行内是用空格分隔的五个数字:

class x_center y_center width height

举例来说,某一行长这样:

3 0.6145 0.5521 0.1720 0.2253

第一个数字 3 是类别 id,从 0 开始计数,对应 class.txt 里的第 4 行。后四个数字分别表示目标中心点的 x 坐标、y 坐标、框的宽度、框的高度,并且全部做了归一化处理——分子是像素坐标除以图片的宽或高,所以值域在 0 到 1 之间。这样做的好处是,无论图片分辨率是 640 还是 4000,标签都不受影响,模型输入尺寸可以随意缩放。

我习惯拿到数据后先写一个小脚本,把归一化坐标换算回像素坐标,再用肉眼确认几个值是否合理:

import os def read_yolo_label(label_path, img_w=1280, img_h=720): """ 读取 YOLO 格式标签,把归一化坐标换算成像素坐标。 img_w/img_h 用实际图片分辨率,这里只做示例。 """ with open(label_path, 'r', encoding='utf-8') as f: lines = f.readlines() for line in lines: parts = line.strip().split() if len(parts) != 5: print(f"异常行: {line.strip()}") continue cls_id = int(parts[0]) x_center = float(parts[1]) * img_w y_center = float(parts[2]) * img_h box_w = float(parts[3]) * img_w box_h = float(parts[4]) * img_h x1 = x_center - box_w / 2 y1 = y_center - box_h / 2 x2 = x_center + box_w / 2 y2 = y_center + box_h / 2 print(f"类别 {cls_id}: 左上角({x1:.1f}, {y1:.1f}) 右下角({x2:.1f}, {y2:.1f})") read_yolo_label("0011_jpg.rf.7a7655516b6ade13a199ad135383cba7.txt")

这段脚本做的事情很简单:把归一化坐标还原成像素坐标。运行后如果出现 x1、y1 小于 0 或者 x2、y2 大于图片宽高的情况,说明标注边界出界了,这类样本需要重视。正常数据集里偶尔有一两个出界框问题不大,但如果出界比例超过 5%,建议先做一轮清洗,否则训练时那些极端位置的锚框会干扰损失计算。顺便一提,某些标注工具导出的坐标是左上角和右下角的像素坐标,和 YOLO 格式不一样,别搞混了,这也是误用数据集时最常见的坑之一。

2.3 数据增强已经提前做过了

这份数据集在发布前已经做过数据增强(data augmentation)。图片里会出现同一块区域的多种变换版本,比如旋转、水平翻转、亮度调整。对应的标签也同步做了变换,所以不会出现图变了框没变的情况。这一点其实是双刃剑:正面来说,样本量被放大,模型见过更多形态变化;反面来说,如果训练集和验证集同时包含同一原始图的增强版本,会被模型“记住”,导致 mAP 指标虚高,这个我会在第五章节重点展开。

这里先记住一个验证原则:拿到增强过的数据集,第一步不是直接训练,而是检查 train 和 valid 之间是否存在来自同一张原始图的相似样本。你不需要去肉眼对比,写一个感知哈希的脚本就能快速筛出来,后面避坑章会给具体方案。

3. 8 个矿物类别与 class 文件:把类别体系落到训练配置里

数据集的类别个数是 8,涵盖石英、斑铜矿、黄铁矿等矿物类型。但类别检测的难点不在数量,而在类间相似度和纹理干扰。比如黄铁矿和某些铜矿在表面光照下的颜色非常接近,模型很容易混淆。这一章讲清楚如何把 class 文件转换成模型训练实际使用的配置。

3.1 从 class.txt 到 data.yaml

数据集里附带一个 class 文本文件,打开后大概是这样的格式:

Quartz Bornite Pyrite ...

如果做 YOLOv8 或 YOLOv5 训练,不能直接把这个文件喂给模型,需要手工写一个 data.yaml。常见做法是创建一个 data.yaml,内容包括路径、类别数和类别名:

# data.yaml path: ../rock_mineral # 数据集根目录 train: images/train # 训练图片目录 val: images/valid # 验证图片目录 nc: 8 # 类别数量,必须与 class.txt 行数一致 names: 0: Quartz 1: Bornite 2: Pyrite 3: Chalcopyrite 4: Galena 5: Sphalerite 6: Hematite 7: Malachite

这里的类别名只是示例,具体以你收到的 class 文本文件内容为准,不要照抄。names 列表的顺序必须和 class.txt 里的顺序完全一致,因为标签文件里写的类别 id 是按行号从 0 开始排的。如果顺序错位,整个模型就会系统性错检——比如把黄铁矿的样本当成了石英去训练,验证时 mAP 还很高,因为模型真的学到了一个错误映射,这也正是标注数据最难排查的坑。

一个稳妥的检查方式是写个脚本,把 class.txt 的内容加载到列表,再和 data.yaml 里的 names 做对比:

import yaml # 读取类别文件 with open("class.txt", "r") as f: class_names = [line.strip() for line in f if line.strip()] # 读取 data.yaml with open("data.yaml", "r", encoding="utf-8") as f: cfg = yaml.safe_load(f) yaml_names = [cfg["names"][i] for i in range(cfg["nc"])] print("类别文件数量:", len(class_names)) print("yaml数量:", cfg["nc"]) print("是否完全一致:", class_names == yaml_names)

如果输出 False,优先检查是不是 class.txt 末尾有空行被过滤掉了,或者 yaml 里 names 少写了一个。这个脚本很小,但每次换数据集我都会先跑一遍,已经帮我避免了两次低级的类别错位事故。

3.2 类别不均衡与增强样本量的取舍

岩石矿物的类别分布通常并不均匀,因为野外取样时石英表面相对常见,而斑铜矿这种出现频率就低。类别不均衡带来的典型问题是:模型对样本量少的类别学习不充分,验证时有一个类别的 recall 明显低于其他类。解决思路有三种:一是对少类别做过采样,二是调整 loss 中的类别权重,三是干脆用数据增强再多生成一些少类别样本。但第三种方案在这个数据集上要小心,因为原图已经增强过一轮,继续增强容易让模型对同一块岩石纹理过拟合。

先跑一个统计脚本,看清每个类别的样本量再决定策略:

import os from collections import defaultdict label_dir = "labels/train" class_count = defaultdict(int) for file in os.listdir(label_dir): if not file.endswith(".txt"): continue with open(os.path.join(label_dir, file), "r") as f: for line in f: parts = line.strip().split() if len(parts) == 5: class_count[int(parts[0])] += 1 print("各类别样本数:", dict(class_count))

输出大概长这样:

类别 id矿物类型(示例)框数量
0石英356
1斑铜矿122
2黄铁矿287
3-7其他五类每类 80-200

如果最低类别样本量不到最高类别的三分之一,训练时建议给数据加载器传入类别权重,或者计算一下每类框面积的中位数,看是不是存在大量小目标。岩石表面矿物检测里一个典型现象是:同一块岩石上,某个矿物只露出指甲盖大小,标注框很小,模型很难召回。这个数据集的图片来自岩石表面,天然带有这种挑战,训练时不必强求 mAP 50-95 拉满,先保证 mAP 50 和类别 recall 均衡更现实。

3.3 小目标与标注框面积分布

对小目标问题,我的习惯是训练前统计一下每个框面积占图片面积的比例。如果大量框面积占比小于 2%,YOLOv8 默认的 P2 检测头可能都不够用,需要开启多尺度训练或者把 imgsz 调大。比如原图是 1280 分辨率的,直接设 imgsz=640 训练,相当于所有目标缩小一半,小矿物框几乎消失了。

4. 交给模型前先可视化:show 脚本与自绘边界框验证

数据准备完成后,最忌讳直接开训。训练跑几十个 epoch 才发现某个类别的标签画错了位置,浪费的时间可能是一整天。可视化是训练前最后一道质检,这个数据集里带了 show 脚本,可以把边界框直接绘制在图像上,用来人工检查标注质量。

4.1 show 脚本的使用方式

show 脚本的作用是读取图片和对应标签,把检测框和类别文本画到图上。它的使用方式很直接,一般会接受两个参数,一个是图片目录,一个是标签目录:

python show.py --img_dir ./images --label_dir ./labels --save_dir ./visual_check

脚本会遍历图片目录,对每个图片找到同名 txt,读取五个字段,用 OpenCV 的 rectangle 和 putText 把框和类别画上去。输出目录里会生成带标注的图片,从头翻一遍就能发现大部分标注问题。参数含义大致是这样:

  • --img_dir:图片存放路径,脚本用 glob 搜索 jpg、png 文件。
  • --label_dir:标签 txt 路径,脚本按文件名匹配。
  • --save_dir:可视化结果的保存路径,建议单独建目录,不要覆盖原图。
  • 如果脚本支持--class_file参数,就传 class.txt,这样画出来的框上方是类别名称而不是数字,检查效率高很多。

如果脚本报错说不认识--img_dir,那可能是它的参数名不一样,比如--images或者--source。可以先用python show.py --help查看它实际支持的参数列表,改一下再执行。有的版本还带置信度阈值参数,但那是用来可视化模型推理结果的,用在这个数据集上意义不大,因为标签文件没有置信度。

4.2 不依赖 show 脚本的自绘兜底方案

如果 show 脚本的某个依赖库版本不兼容,或者你想快速验证某一张图,没必要去调试脚本,直接用 OpenCV 自己写一个绘制函数更省事:

import cv2 def draw_yolo_boxes(img_path, label_path, class_names): img = cv2.imread(img_path) h, w = img.shape[:2] with open(label_path, "r") as f: lines = f.readlines() for line in lines: parts = line.strip().split() if len(parts) != 5: continue cls_id = int(parts[0]) x_center = float(parts[1]) * w y_center = float(parts[2]) * h box_w = float(parts[3]) * w box_h = float(parts[4]) * h x1 = int(x_center - box_w / 2) y1 = int(y_center - box_h / 2) x2 = int(x_center + box_w / 2) y2 = int(y_center + box_h / 2) color = (0, 255, 0) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) label = class_names[cls_id] cv2.putText(img, label, (x1, y1 - 6), cv2.FONT_HERSHEY_SIMPLEX, 0.7, color, 2) return img # 使用示例 class_names = ["Quartz", "Bornite", "Pyrite"] img = draw_yolo_boxes("images/0011_jpg.rf.7a7655516b6ade13a199ad135383cba7.jpg", "labels/0011_jpg.rf.7a7655516b6ade13a199ad135383cba7.txt", class_names) cv2.imwrite("check_0011.jpg", img)

这段代码的逻辑很清晰:先读图片拿到实际宽高,再把归一化坐标还原成像素坐标,最后用矩形框和文字叠加到图上。一个细节是cv2.rectangle的坐标必须转成int,否则 OpenCV 会报 type error。检查时重点关注三类问题:框是否偏出图外、框是否明显过大或过小、框的中心点是否落在矿物纹理上。岩石表面数据里最常出现的问题是一个大框包含了好几种矿物,说明标注粒度偏粗,后续训练时模型学会的也是“把整片区域标成一类”,而不是精确定位单个矿物。

4.3 可视化检查的抽检比例

不需要每张图都看到吐,但建议至少在训练集和验证集里各抽 30 张,覆盖到每个类别至少 5 个框。抽检时不要只看前几张,因为文件夹排序往往导致同批次图片内容相似,要随机抽样。脚本里加个random.sample就能做到,这算是数据质检里成本最低收益最高的一步。

5. 训练避坑:标签、划分与数据增强的四个常见问题

数据集本身质量不错,但使用增强过的数据集训练,有几类问题几乎每个人都会遇到。这一章把最常见的四类问题拆开讲,每条都是按现象、原因、解决的顺序来,内容都是踩过坑之后沉淀下来的经验。

5.1 训练集和验证集同源,mAP 虚高

现象:训练完验证,mAP 50 高达 0.95 以上,但把模型放到现场拍摄的新照片上测试,效果惨不忍睹,检测框乱跳。

原因:数据增强是在发布前做的,同一张原始图经过翻转、旋转、调亮度后生成多个副本,这些副本如果被同时分到训练集和验证集,模型相当于提前见过验证图的变形版本,指标自然好看,但这个分数没有实际参考价值。

解决:先扫描训练集和验证集之间是否存在近重复图片。简单的方式是用文件名的哈希前缀判断,更可靠的方式是计算图片的感知哈希,把相似度高于阈值的图片对找出来,再从验证集里移除与训练集相似的样本。以这个数据集的命名规则为例,0011_jpg.rf.xxxxx.jpg里的0011_jpg是原始图标识,如果训练集和验证集出现同名但哈希不同的文件,说明是同一原始图的增强版本,需要处理。删掉验证集里的重复样本后,mAP 会降一些,但那个数字才是真实水平。

5.2 类别 id 偏移,模型系统性错检

现象:训练结果看起来收敛,但推理时黄铁矿的框总是标成石英,而且是所有图都错,不是偶发。

原因:class.txt、data.yaml 的 names 列表、标签文件里的 id 三者顺序不一致。例如 class.txt 里第 0 行是 Quartz,但 data.yaml 里第 0 行写成了 Pyrite,那标签里所有 id 为 0 的目标都会被当成 Pyrite 训练。这类错误在训练时几乎不会有明显征兆,因为损失的下降趋势是正常的。

解决:用第 3 章的对比脚本,把 class.txt 和 data.yaml 逐行比对。另外抽几张贴好标签的可视化图片,核对类别名称是否和肉眼判断一致。推荐在训练前跑固定流程:读取 class.txt 生成 names 列表,再按行号写入 data.yaml,而不是手打,这样能从源头避开 id 偏移。yaml 里的 names 顺序错了,模型是不会有任何报错的,这就是它隐蔽的地方。

5.3 空标签文件被静默跳过

现象:训练日志里显示的图片数量小于实际图片数量,或者某个类别完全没被模型学到,recall 为 0。

原因:数据集中某些 txt 文件是空的,0 字节,表示这张图没有任何标注框。这种文件在读取时会被跳过,但对应图片还是会被加载为纯背景图,相当于无形中给训练集加了无目标样本。少量空标签问题不大,但如果空标签集中分布在某个类别对应的图片上,就相当于该类别的正样本被削掉了一部分,模型自然学不到。

解决:扫描标签目录,统计非空 txt 的数量和空 txt 的数量:

find labels -name "*.txt" -size 0 | wc -l

如果空文件数量占总数超过 2%,建议把对应的图片和空 txt 一并放到 backup 目录,不参与训练。需要注意的是,不能只删 txt 不删图,否则图片目录和标签目录数量对不上,某些框架会在检查时报 mismatch 错误。处理完空标签后,重新统计每个类别的框数量,确认类别分布没有发生剧烈变化。

5.4 增强副本过多导致训练集内部高度相似

现象:训练损失降得很快,但在验证集上的表现停滞不前,甚至 epoch 越往后验证损失越高。

原因:数据增强生成了大量近似副本,训练集内部相似度太高,模型相当于在反复记忆同一块岩石纹理的轻微变化,而不是在学矿物形态的泛化特征。放大倍数过高时,这类增强反而变成过拟合催化剂。

解决:如果我们想处理这个数据集并用于严肃实验,建议做一个去重:对训练集内部图片两两计算感知哈希,删除高度相似的样本。但要注意,去重比例如果超过 20%,数据集的有效样本量就回到了原始规模,数据增强的意义被削弱了。一个折中做法是保留增强后的训练集,但把验证集换成完全没有参与增强的原始图。如果资源允许,最稳妥的还是自己重新划分一份全新的验证集,确保任何一张图在训练和验证阶段都没有以任何形式被模型提前见过。

6. 走通一次 YOLOv8 训练:目录焊接、参数设置与混淆矩阵验证

格式看懂了,类别核对了,可视化也通过了,现在可以进入真正的训练环节。这一章把 YOLOv8 作为示例框架,因为它是目前把配置和命令简化得比较成熟的版本。数据集的 YOLO 格式直接兼容,不需要任何转换脚本,你要做的只是把目录结构摆好。

6.1 把数据组织成 YOLOv8 需要的目录形态

YOLOv8 的默认约定是 images 和 labels 分开放,而且相对路径要写准确。我一般会搭成这样:

rock_mineral/ ├── images/ │ ├── train/ │ └── valid/ ├── labels/ │ ├── train/ │ └── valid/ ├── class.txt └── data.yaml

如果你的压缩包里图片和标签是混在一起放的,先用一行命令分开:

mkdir -p images/train images/valid labels/train labels/valid # 把训练图片移动到对应目录,按实际划分文件名索引来归类

注意 YOLOv8 会在训练时自动到 labels 目录下找与 images 相同文件名、后缀为 .txt 的文件。所以 images/train 里的一张图,其标签文件必须放在 labels/train 下,目录层级要对称,不能图在 train、标签在 valid,那样框架会直接报找不到标签。

6.2 训练命令与 mAP 指标解读

把前面写的 data.yaml 放到数据集根目录后,执行训练命令:

yolo train data=rock_mineral/data.yaml model=yolov8n.pt epochs=100 imgsz=640 batch=16

几个关键参数的考量:

  • model=yolov8n.pt是 nano 版本,适合第一次跑通流程,显存占用小。如果显卡是 8G 以上,换成yolov8s.pt或yolov8m.pt会明显提升小目标的召回。
  • imgsz=640是基准尺寸。如果原图里有大量小矿物框,建议试试imgsz=1280,但训练时间会增加到四倍左右,需要自行权衡。
  • batch=16要根据显存调整,用 nano 模型配合 16 基本能在 8G 卡上跑起来,如果报 CUDA out of memory,降成 8 或 4。

训练结束后,验证命令是:

yolo val model=runs/detect/train/weights/best.pt data=rock_mineral/data.yaml

关注两个指标:mAP 50 和 mAP 50-95。对于矿物检测,mAP 50 更符合实际需求,因为矿物表面边界本身存在模糊带,不需要非常精确的框。如果 mAP 50 超过 0.8 而 50-95 低于 0.4,说明框的定位精度一般但召回能力不错,这在岩石矿物这种天然纹理复杂的目标上是可以接受的。

6.3 混淆矩阵是定位类别混淆的利器

训练完不要只看 mAP,一定要打开runs/detect/train/confusion_matrix.png。混淆矩阵能精确告诉你哪两个类别互相认错。比如 Quartz 和 Pyrite 的混淆块颜色很深,说明这两个类别在特征空间里挨得太近。处理办法不是盲目加数据,而是回到类别定义——看看这两类矿物在标注时是否存在边界重叠或者把共生矿物标成一个框的情况。常见做法是把易混淆类别合并成一个大类,或者对样本较少的那个类做针对性增强。

如果没有现成的混淆矩阵图,也可以手动提取:

yolo val model=runs/detect/train/weights/best.pt data=rock_mineral/data.yaml --save_conf

之后在runs/detect/val/下查看生成的 .npz 文件,用代码加载并输出每类的 recall。从那以后我每次拿到新数据集,都会强制走一遍固定流程:先 diff 标签文件名,再核查类别 id 和 class.txt 是否对应,然后随机抽 30 张图看可视化,最后算一遍 train/valid 相似度,四步做完才敢点训练按钮。这套习惯帮我提前挡住过至少三次低级的标注错位事故,也节省了反复重训的时间。希望能帮到你,让这份岩石矿物数据集的每一步使用都尽量少走弯路。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询