岩石矿物检测实战:COCO双标注与实例分割训练全流程

发布时间:2026/9/11 20:59:13
岩石矿物检测实战:COCO双标注与实例分割训练全流程 简介面向地质勘探与矿物资源开发领域提供一套岩石、矿石表面矿物质检测与分割数据集可支撑目标检测、语义分割等算法的训练与评估。整个压缩包共2000个文件以1998张JPG图片为主配以2个JSON标注文件包体约215.94MB标注采用COCO格式同时包含分类、分割和目标检测信息。每张图片均经过马赛克增强处理丰富了样本多样性可帮助提升模型在复杂矿山环境下的鲁棒性与泛化能力。数据集对于矿产快速分类、矿物分布精细分析以及选矿加工中的目标定位都有直接应用价值支持基于卷积神经网络等深度学习模型的训练与验证可直接对接主流检测和分割框架。目前已有918人学习下载适合地质、遥感、计算机视觉等方向的研究人员和工程师用于模型训练、算法对比与实验验证。1. 岩石矿物检测为什么绕不开 COCO 双标注拿到一份岩石、矿石表面矿物质检测与分割数据集第一反应不是翻图片而是先打开标注 json。因为在这个场景里检测框和分割掩码经常相互“打架”——矿物颗粒边界极不规则一个 bbox 往往把周围大片背景圈进来纯目标检测模型训练出来就是高召回、低精度。这份超过 2600 张图像的矿物表面数据集同时给出语义分割与目标检测标注本质上就是在逼你在训练策略上做取舍。对于做地质勘探图像识别、选矿粒度分析或者矿物自动分类的工程师来说这份数据的价值不只是“能跑通 YOLO”而是能帮助你搞清楚如何在同一种 COCO 标注格式下把实例分割和边界框输出统一进一个训练管线。本文从标注结构、数据增强、模型配置到验证脚本完整拆一遍这套流程直接可复现。2. COCO 标注格式里 detection 与 segmentation 的数据组织2.1 一个 json 文件如何同时承载三类标注信息COCO 标注格式的核心是三个数组images、annotations、categories。这套岩石矿物数据集里的分类、检测、分割信息全部压缩在这三个数组的对应关系里不需要额外文件。import json with open(annotations/instances_train.json, r, encodingutf-8) as f: coco json.load(f) print(coco.keys()) # dict_keys([info, licenses, images, annotations, categories]) print(图像数:, len(coco[images])) print(标注实例数:, len(coco[annotations])) print(类别数:, len(coco[categories]))逻辑上先看顶层键。images数组里每条记录是单张图的id、file_name、width、height。annotations数组里的每一条是一个独立目标实例对应到某张图。categories数组则是矿物类别表。也就是说“分类”信息不是单独一个标签文件而是通过annotation.category_id指向categories表里的类别名“分割”通过annotation.segmentation字段编码“检测”通过annotation.bbox字段表达。三者共用同一份实例标注。这样设计的好处是训练 Mask R-CNN 这类双头模型时检测分支和分割分支共享同一个 RoI不需要额外同步两个标注文件。但也带来一个隐患语义分割的标签和检测框标签天然不一致时模型在边界框回归和掩码预测之间会产生梯度冲突。矿物表面矿物质扫描场景里颗粒边缘夹杂大量纹理噪声这个问题尤其严重。2.2 polygon、RLE 与 bbox 的几何一致性COCO 的segmentation字段有两种编码方式多边形坐标列表polygon和 RLE 游程编码。这份数据集如果是从 Roboflow 导出的默认往往是 polygon 格式形如[x1, y1, x2, y2, ..., xn, yn]扁平化坐标。而语义分割训练时多数框架要求把 polygon 转成 RLE 或直接生成 0/1 mask。import numpy as np from pycocotools import mask as maskUtils # 假设 annotation 是加载后的某条实例标注 seg annotation[segmentation] if isinstance(seg, list): rle maskUtils.frPyObjects(seg, h, w) # polygon - RLE rle maskUtils.merge(rle) # 合并多个多边形 else: rle seg # 已经是 RLE mask_2d maskUtils.decode(rle) # 解码为 HxW 的 0/1 mask print(mask shape:, mask_2d.shape, 前景像素数:, int(mask_2d.sum()))代码里做了两层判断segmentation是 list 就按 polygon 处理是 dict 就是 RLE。用frPyObjects把扁平化坐标还原成多边形对象再转 RLE最后解码成可视化的 mask。这个转换在训练脚本中会反复出现值得封装成工具函数。字段类型说明本数据集使用场景segmentationlist / dictpolygon 或 RLE语义分割监督信号bbox[x, y, w, h]像素坐标目标检测回归目标areafloatmask 面积小目标筛选用iscrowd0 / 1是否密集人群矿物粘连时置 1 需注意category_idint类别索引分类监督注意bbox和segmentation并非严格一致COCO 官方要求的 bbox 是目标外接矩形但很多标注工具导出时用的是 mask 的最小外接矩两者在斜向矿物颗粒上差异明显。我一般会在训练前写脚本统计 bbox 边缘与 mask 边缘的最大偏离距离超过 20 像素就要考虑重新校正。2.3 为什么这套标注适合做“分割为主、检测为辅”的基线矿物表面检测的痛点在于目标边界模糊、尺寸变化大、纹理重复度高。纯检测模型只能告诉你“这里有矿物”不能告诉你“矿物占据多大面积”。而岩石表面的矿物分布对工业指标至关重要比如选矿回收率估算依赖面积占比。因此这份数据集的 COCO 双标注可以拆出两条训练路线如果生产环境只做定位用 bbox如果要做品位分析必须用掩码。我倾向于在这份数据上以 Mask R-CNN 或 YOLOv8-seg 为主干把 bbox 作为辅助监督而不是反过来。3. 从 COCO 标注到训练数据的预处理流程3.1 目录组织与数据划分策略COCO 格式的目录通常按官方比赛结构组织。对于这份岩石矿物数据集我建议重新划分目录而不是直接用原打包结构训练便于后续增量标注和版本管理。dataset/ ├── images/ │ ├── train/ # 约 1850 张 │ └── val/ # 约 520 张 └── annotations/ ├── instances_train.json └── instances_val.json划分策略上矿物数据集有一个特殊性同一块岩石的连续采样照片极其相似如果随机划分训练集和验证集会泄漏大量相同纹理导致 mAP 虚高。我一般用基于图像采集时间戳的划分方法例如这个数据集文件名里的20200608_175240这类字段就是拍摄时间按时间切分确保同一采样批次只落在训练集或验证集一侧而不是两边都有。小目标过滤也是必须要做的事。岩石表面的细小矿物颗粒可能只有几十个像素标注面积占全图比例低于 0.5%这类样本在 COCO 评测中被归入 small 类别。如果训练数据里这类占比过高模型会对整体指标贡献很小反而分散学习能力。3.2 用 pycocotools 做数据质量审计数据质量审计的优先级高于搭模型。这一步的收益在后续实验里会成倍放大。下面这段代码输出每张图的类别分布和 mask 面积分布。from collections import Counter import numpy as np cat_id_to_name {c[id]: c[name] for c in coco[categories]} img_id_to_size {img[id]: (img[width], img[height]) for img in coco[images]} cat_counter Counter() area_list [] small_cnt 0 for ann in coco[annotations]: cat_counter[cat_id_to_name[ann[category_id]]] 1 w, h img_id_to_size[ann[image_id]] area_ratio ann[area] / (w * h) area_list.append(area_ratio) if area_ratio 0.005: small_cnt 1 print(类别分布:, dict(cat_counter)) print(面积占比 中位数: %.4f 最小: %.6f % (np.median(area_list), min(area_list))) print(小目标(占比0.5%): %d 条 % small_cnt)这段审计代码有两点意义。第一确认类别不均衡的严重程度热词里常见的“小目标检测”问题在此场景就体现为细微矿物颗粒漏检。第二面积占比信息决定后续数据增强的参数选择——如果中位数占比极低说明大目标稀少多尺度训练和 Copy-Paste 类的增强会比固定尺度训练更有效。如果small_cnt占比超过 40%anchor 尺度的设置就要往下调Mask R-CNN 默认的[32, 64, 128, 256, 512]在岩石细颗粒上明显偏大。3.3 Mosaic 增强在多目标标注下的正确打开方式这份数据集明确提到做了马赛克增强Mosaic。Mosaic 最早从 YOLOv4 流行开来把四张图拼成一张本质上是增加单张图的背景多样性和目标尺度多样性。但在 COCO 双标注训练里Mosaic 有个容易被忽略的坑拼接时四张图的边界框和掩码都要跟着做平移裁剪如果一张图的掩码区域在拼接边界处被截断area和bbox会变得不一致。import albumentations as A from albumentations.pytorch import ToTensorV2 transform A.Compose([ A.RandomResizedCrop(height640, width640, scale(0.5, 1.0)), A.Mosaic(p0.5), A.HorizontalFlip(p0.5), A.Normalize(mean(0.485, 0.456, 0.406), std(0.229, 0.224, 0.225)), ])albumentations 里的Mosaic支持同步变换 mask 和 bbox不需要自己写拼接逻辑。但注意scale参数和 mosaic 的min_area设定拼接后大量目标会被缩放到极小尺寸训练 Mask R-CNN 时MIN_SIZE太低会导致掩码分支的 RoI 特征分辨率不足。我更推荐的做法是 Mosaic 只在前 30 个 epoch 开启后面关闭让模型在接近真实数据分布上做微调。这类数据增强在语义分割数据集制作流程里是标配但用在矿物数据上参数要调得更保守。4. 基于 COCO 双标注的矿物表面检测与分割模型配置4.1 先跑通 YOLOv8-seg最小可行基线在部署层面YOLOv8-seg 是当前把检测和分割同时落地的最短路径。它对 COCO 格式的原生支持直接省去写 Dataset 类的工作。用一个 yaml 文件定义类别和数据路径即可。# mineral.yaml path: /data/mineral/ train: images/train val: images/val nc: 4 names: [hematite, malachite, quartz, pyrite]这个配置与热词里提到的 yolo 目标检测流程完全一致nc是类别数names按训练时类别顺序排列。注意这里的类别顺序必须与 COCO 标注 json 里的categories顺序对齐否则类别张冠李戴。如果不确定可以用脚本从 json 里动态生成这个 yaml。yolo detect train datamineral.yaml modelyolov8s-seg.pt epochs50 imgsz640 batch8这个命令默认会读取 COCO 格式标注yolov8s-seg 是轻量级分割模型适合第一轮跑通。训练完成后验证命令如下yolo segment val modelruns/segment/train/weights/best.pt datamineral.yaml输出里有两个指标需要区分对待mAP50和mAP50-95。如果mAP50高但mAP50-95低说明主要问题不在分类而在定位精度大概率是标注框边界偏松需要回到数据修正而不是加大模型。第一轮基线是个不错的起点但要满足选矿粒度分析这种要求往往需要换 Mask R-CNN 做更精细的掩码预测。4.2 Mask R-CNN 在 mmdetection 下的实践配置如果追求比 YOLOv8-seg 更精细的掩码边界可以用 mmdetection 里的 Mask R-CNN 配合 ResNet-50 主干。下面给一份能直接改路径就用的核心配置。_base_ [ ../_base_/models/mask_rcnn_r50_fpn.py, ../_base_/datasets/coco_instance.py, ../_base_/schedules/schedule_1x.py, ../_base_/default_runtime.py ] model dict( roi_headdict( bbox_headdict(num_classes4), mask_headdict(num_classes4) ) ) data dict( traindict( ann_file/data/mineral/annotations/instances_train.json, img_prefix/data/mineral/images/train/ ), valdict( ann_file/data/mineral/annotations/instances_val.json, img_prefix/data/mineral/images/val/ ) ) optimizer dict(typeSGD, lr0.01, momentum0.9, weight_decay0.0001) lr_config dict(policystep, step[16, 22]) total_epochs 24这份配置做了两处关键修改num_classes从 COCO 默认的 80 改成实际矿物类别数训练计划从默认的 12 epoch 延长到 24。原因在于矿物数据集类别少模型容量容易过拟合用更长的训练周期配合 step 学习率衰减可以稳定收敛。学习率方面虽然 batch size 通常只有 8但类别少、任务简单0.01 的初始学习率不会震荡。训练命令python tools/train.py configs/mineral/mask_rcnn_r50_fpn_1x.py --work-dir work_dirs/mineral4.3 语义分割与实例分割在矿物场景的选型差异这份数据集标注同时可用于语义分割和实例分割。热词里的 deeplabv3 语义分割是一个常见对比对象但在实例相互粘连严重的矿物表面纯语义分割输出的是像素级类别图无法区分同一矿物类别下不同的矿石颗粒。而选矿场景往往需要统计颗粒数目、大小分布实例分割信息不可或缺。如果你的用途仅限面积占比分析DeepLabV3 这类语义分割模型更轻、更快如果需要粒度分析和计数Mask R-CNN 或 YOLOv8-seg 是正确选择。这个选型差异在项目开始时就要确定因为它决定标注数据的最终消费方式。5. 从标注质量反推训练效果验证脚本与三类典型坑5.1 快速验证掩码质量的五步检查法训练之前先做一轮掩码可视化验证。直接叠加 mask 到原图上检查标注是否贴合矿物边缘。这一步比看 mAP 数字更直观。下面是一个简单的可视化检查代码。import cv2 from pycocotools import mask as maskUtils def draw_mask(img_path, ann): img cv2.imread(img_path) h, w img.shape[:2] rle maskUtils.frPyObjects(ann[segmentation], h, w) m maskUtils.decode(maskUtils.merge(rle)) # 彩色掩码叠加 color_img img.copy() color_img[m 0] (0, 0, 255) color_img[m 0] * 0.3 x, y, bw, bh ann[bbox] cv2.rectangle(color_img, (int(x), int(y)), (int(x bw), int(y bh)), (0, 255, 0), 2) return color_img每张图随机抽 5 个标注实例人工检查三类问题掩码是否包含背景纹理、bbox 是否紧贴外轮廓、同一目标的掩码是否有内部空洞。如果空洞多说明标注工具在复杂纹理处产生断线训练时模型会学到错误的“环状”掩码输出。5.2 类别不均衡与背景占比过高岩石数据集最常见的坑是类别不均衡。从前面审计脚本可以看出不同矿物类别在数据集里的实例数量可能差 10 倍以上。解决方案有两个层面。数据层面对少样本类别做过采样用repeat_factor或者自定义 sampler损失层面给交叉熵损失加类别权重。Mask R-CNN 里通过loss_cls_weight和loss_mask_weight调整。model dict( roi_headdict( bbox_headdict( num_classes4, loss_clsdict(typeCrossEntropyLoss, use_sigmoidFalse, class_weight[1.0, 3.0, 2.0, 5.0]) ) ) )这种加权方式让模型对少样本类别给予更多梯度关注。但注意权重不宜过大超过 5 会引发少样本类别误检率飙升。背景占比过高是另一个问题。岩石图像中矿物颗粒往往只占画面的一小部分R-CNN 系列的采样机制对背景候选框已经做了正负样本比例控制但如果分割分支的 mask 损失把背景像素全算进去dice loss一类的区域损失会比逐像素交叉熵更稳定。我一般会在掩码分支额外加一个小的 dice loss 辅助项对抗背景主导。5.3 边界不确定性与两阶段预测策略矿物颗粒的边界在图像上经常不清晰标注者之间的一致性也不高。针对这种边界模糊问题一个实用技巧是把预测任务拆成两阶段先用语义分割得到粗略的矿物分布热图再用检测框加掩码在全图上做精修。第一阶段类似热词里提到的 mtd 动目标检测思想——先框出“变化的区域”再做精细识别。第二阶段用 Mask R-CNN 的 RoI Align 输出精确边界。这样可以规避单阶段模型在模糊边界处的像素级歧义。在推理阶段把置信度阈值调低的收益比调高更明显矿物检测任务宁可多出几个假阳性框也不能漏掉稀有矿物颗粒。我一般会把score_thr从默认的 0.5 降到 0.3再用形态学开闭运算对 mask 后处理一次去除孤立小噪点填充内部小洞输出的面积数据才适合直接用于粒度统计。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询