news 2026/9/24 23:55:12

气球COCO数据集:Mask R-CNN实例分割训练全流程指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
气球COCO数据集:Mask R-CNN实例分割训练全流程指南

简介:这是一份面向计算机视觉入门与进阶学习者的气球实例分割数据集,基于 Mask R-CNN 构建并已完整转换为 COCO 格式,可直接放入最新 MMDetection 框架中训练与测试,免去自行标注和格式转换的繁琐步骤。资源包大小 36.89MB,共包含 76 个文件,其中 74 张 JPG 图片按 train2017 与 val2017 划分,另有 instances_train2017.json 和 instances_val2017.json 两个标注文件;压缩包内目录包含 train2017、val2017 和 annotations,路径结构清晰,可直接对应 COCO 标准数据加载要求。已有 512 人浏览学习该资源,适合用于快速跑通 Mask R-CNN 训练流程、对比不同 backbone 的效果或开展气球检测与分割方向的实验。通过这套数据,可以直观理解实例分割的数据组织方式、标注文件字段含义以及 MMDetection 的配置与调用逻辑,也能借此体验从数据加载、模型训练到 mAP 评估的完整流程,为后续在自定义数据集上复现 Mask R-CNN 提供完整可参考的样例。

1. 做实例分割第一关是数据:这份气球 COCO 数据集让 Mask R-CNN 训练省一半事

做实例分割的都知道,模型结构可以抄,但一份带像素级掩码的标注数据很难凑。网上的开源数据集里全是规规矩矩的 COCO 格式,自己手里的图却往往是散的 JPG 加一片一片的 PNG mask,光写转换脚本就得调一天。第一次拿到这份「气球 Mask R-CNN 转 COCO 格式」的数据集时,最大的感受是它把最脏的活干完了:图片分好 train/val,标注整理成 instances_train2017.json 和 instances_val2017.json,类目只有一个 balloon,解压后直接用 MMDetection 就能训练 Mask R-CNN,甚至测试效果比从 COCO 里随机抠子集要好得多。它适合两类人:一是刚入门实例分割、想用现成数据跑通 Mask R-CNN 基线的新手;二是需要验证某个分割方案、不想把时间耗在标注格式上的算法工程师。这篇文章从 COCO 标注内部结构讲起,一直讲到训练、避坑、自己转换同类数据,最后给一套微调和评估习惯。

2. 先看懂 COCO 标注再动手:数据集的目录、字段与掩码表示

2.1 压缩包内部结构:train2017 / val2017 / annotations 三件套

解压 ballon_mask_rcnn.rar 后,目录是典型的 COCO 布局:

ballon_mask_rcnn/ ├── annotations/ │ ├── instances_train2017.json │ └── instances_val2017.json ├── train2017/ │ ├── 7308740338_591f27b631_k.jpg │ ├── 7178882742_f090f3ce56_k.jpg │ └── ... └── val2017/ ├── 8053085540_a72bd21a64_k.jpg ├── 4581425993_72b9b15fc0_b.jpg └── ...

文件名里的数字是 Flickr 图片 ID,不是 COCO 原始编号,这个不重要;重要的是目录名和 JSON 文件名是配套的。MMDetection 的 CocoDataset 默认会根据配置里的ann_file去读 JSON,再根据img_prefix拼图片路径,所以目录起成 train2017/val2017 是为了省事,你也可以改成别的名字,只要配置里对应改就行。

这份资源里还有一个细节:annotations 目录下只有 instances_train2017.json 和 instances_val2017.json,没有 captions 或 stuff 文件,因为 Mask R-CNN 训练只需要实例标注。图片是从开放图片库里挑出来的包含气球的图像,总量不大,正好适合在单卡上做实验,而不是一上来就面对一百多 G 的完整 COCO。

2.2 从 instances_train2017.json 里抽取三个关键数组

先别急着开训,拿 Python 把 JSON 读出来看一遍,能省很多排查时间。COCO 标注 JSON 顶层有三个必填字段:imagesannotationscategories。我一般会写个几十行的检查脚本:

import json from collections import Counter ann = json.load(open('annotations/instances_train2017.json')) print('images:', len(ann['images'])) print('annotations:', len(ann['annotations'])) print('categories:', ann['categories']) # 统计每一类别的实例数量 cnt = Counter([a['category_id'] for a in ann['annotations']]) print('annotations per category:', dict(cnt)) # 查看有标注的图片数量 img_with_ann = set(a['image_id'] for a in ann['annotations']) print('images with annotations:', len(img_with_ann)) # 看前两条 annotation 的完整内容 for a in ann['annotations'][:2]: print(a)

这段脚本逻辑很简单:先加载 JSON,然后打印各集合数量。关键是要看categories的内容。这份数据集的categories通常长这样:

[{"id": 1, "name": "balloon"}]

只有一个类,id 从 1 开始。再看 annotation 字典,能看到segmentationareabbox等字段。注意area是掩码真实面积,不是像素数乘上什么系数;bbox[x, y, width, height]的浮点列表,对应的是该实例外接矩形的左上角坐标和宽高。

这里容易踩的一个概念坑是:COCO 的category_id是 1,但 MMDetection 里如果直接用官方 COCO 预训练模型,它的 80 类是从 1 到 80 的,没有 id=0 的类别。如果你把num_classes设成 1,后台实际做的是把分类分支的输出从 81 变成 2(包括背景类),所以 1 类数据集的num_classes=1是没问题的。真实在配置里写的 1,不是 1+1。

另一个值得做的检查是验证标注框和掩码是否对齐。因为转换脚本偶尔会把 bbox 和 segmentation 来自不同的 mask 源,导致训练时 mask head 的 loss 正常、box head 的 loss 异常。可以用下面的代码做粗粒度校验:

from pycocotools.coco import COCO coco = COCO('annotations/instances_train2017.json') for ann_id in coco.getAnnIds()[:10]: ann = coco.loadAnns(ann_id)[0] mask = coco.annToMask(ann) x, y, w, h = [int(v) for v in ann['bbox']] # mask 里非零像素是否集中在 bbox 范围内 inside = mask[y:y+h, x:x+w].sum() total = mask.sum() if inside < 0.5 * total: print('bbox and mask mismatch:', ann_id)

这个脚本用coco.annToMask(ann)把标注转成二值 mask,再判断 bbox 是否包住了大部分正像素。如果 mismatch 比例高,说明数据源本身不可靠,训练前就得止损。

2.3 多边形坐标 vs RLE:这份数据集里掩码长什么样

COCO 的segmentation字段有两种写法:多边形点列表(polygon)和 RLE 游程编码。标注工具导出的通常是 polygon,格式是[x1, y1, x2, y2, ...],点按顺序围出目标轮廓。RLE 则更像压缩后的位图,适合存储大而复杂的掩码。实例分割训练时,MMDetection 的 CocoDataset 会通过 pycocotools 把 polygon 转成 mask,也可以直接使用 RLE。

这份气球数据集在 JSON 里用的是 RLE 还是 polygon,取决于原始转换脚本。无论哪种,训练前最好用 pycocotools 验证一下能不能正确解码:

from pycocotools.coco import COCO coco = COCO('annotations/instances_train2017.json') img_ids = coco.getImgIds()[:5] for img_id in img_ids: ann_ids = coco.getAnnIds(imgIds=img_id) for ann_id in ann_ids: ann = coco.loadAnns(ann_id)[0] mask = coco.annToMask(ann) # 返回 HxW 的 0/1 mask print(ann['image_id'], mask.sum(), ann['bbox'], ann['segmentation'].__class__.__name__)

这里的coco.annToMask(ann)是 pycocotools 提供的解码接口,polygon 和 RLE 都能处理。如果mask.sum()是 0,说明标注有问题,需要回到转换脚本里查。看到输出里 bbox 和 mask 面积量级一致,再进入训练环节就不容易出幺蛾子。这个习惯我建议保留,拿到任何 COCO 数据集都先跑一遍。

annotation 字段里还有一个iscrowd,表示该实例是否是一堆密集物体。COCO 官方对 crowd 区域使用 RLE 且不需要多边形;这份气球数据集几乎都是单体气球,iscrowd基本都是 0。如果以后自己转换,记得把iscrowd设 0,否则 MMDetection 在训练时会走另一条 crowd 分支,容易出现奇怪的行为。

下表是这份 annotation 里最常见的字段说明,排查数据时对照着看:

字段类型含义
idint标注实例的唯一编号
image_idint所属图片在 images 数组中的 id
category_idint类别 id,这里为 1
bboxlist[float][x, y, width, height],左上角坐标加宽高
areafloat掩码面积,像素单位
segmentationdict/listRLE 字典或多边形点列表
iscrowdint0 表示普通实例,1 表示群体区域

2.4 为什么 COCO 格式能直接对接 MMDetection

很多人问:不是有 VOC 格式吗,为什么非转 COCO?关键原因是 MMDetection 的 CocoDataset 在数据加载阶段已经实现了 COCO JSON 的解析、mask 解码、多尺度裁剪拼接这一整套逻辑,你只需要给一个ann_file路径。而 VOC 格式需要额外的 xml 解析,且 mask 通常是以独立 PNG 文件存储,数据加载路径多一层间接性。COCO 的单 JSON 文件把所有实例标注集中在一起,训练前做 cache 也更方便,尤其适合小数据集快速迭代。

也正是因为这份气球数据是标准 COCO 格式,CocoDataset可以拿到annotations后直接做annToMask,不需要再写任何自定义 Dataset 类,下游的 mask head 训练、评估阶段的 mAP 计算都能复用 COCO 官方 API。所以「转成 COCO」不是一种强迫症,是节省工程成本的选择。

3. 直接训练 Mask R-CNN:MMDetection 配置修改与命令行实操

3.1 用官方 mask_rcnn_r50_fpn 做基类,覆盖类别数和数据路径

MMDetection 的配置文件做了很好的继承机制。我们不需要从零写一个 Mask R-CNN,而是在官方提供的mask_rcnn_r50_fpn_1x_coco.py基础上改几处。先建一个独立配置目录,比如configs/balloon/,新建文件mask_rcnn_r50_fpn_1x_coco.py

_base_ = 'configs/mask_rcnn/mask_rcnn_r50_fpn_1x_coco.py' model = dict( roi_head=dict( bbox_head=dict(num_classes=1), mask_head=dict(num_classes=1) ) ) dataset_type = 'CocoDataset' data_root = 'data/balloon/' classes = ('balloon',) data = dict( samples_per_gpu=2, workers_per_gpu=2, train=dict( classes=classes, ann_file=data_root + 'annotations/instances_train2017.json', img_prefix=data_root + 'train2017/' ), val=dict( classes=classes, ann_file=data_root + 'annotations/instances_val2017.json', img_prefix=data_root + 'val2017/' ), test=dict( classes=classes, ann_file=data_root + 'annotations/instances_val2017.json', img_prefix=data_root + 'val2017/' ) )

这段配置做了三件事:第一,告诉模型num_classes=1,覆盖 bbox head 和 mask head 的输出维度;第二,指定数据格式为CocoDataset,并设置classes=('balloon',),让 dataset 内部的类别映射保持正确;第三,把ann_fileimg_prefix指到实际路径。注意samples_per_gpu是每块卡上的 batch size,这里设 2,如果你的显卡显存有限,改成 1 也能跑。

为什么num_classes要写 1?因为 Mask R-CNN 的分类头输出是num_classes + 1通道,那个 1 是背景。官方 COCO 配置里写的是 80,但实际上有 80 个目标类,所以这里如果写81就错了,MMDetection 内部不会帮你再加 1。同理,如果数据里有 3 个类,这里就写 3。

如果你用的是最新版 MMDetection 3.x,data这个字段被拆得更细,但核心的ann_fileimg_prefixclasses还在,只是包在了train_dataloaderval_dataloader下。建议先按项目实际安装的版本来,如果跑的是 2.x,上面这份配置可以直接用。

3.2 单卡训练:batch size、学习率与 Epoch 怎么定

数据集不大,单卡训练是常态。在资源有限的情况下,我一般先用 2 的 batch size 跑通流程,再考虑调大。学习率方面,MMDetection 默认的 1x 配置是 0.02,那是基于 8 卡、每卡 2 张图的 batch size 16 算出来的。如果只有单卡 2 张图,总 batch size 变成 4,学习率要等比缩放,常见做法是线性缩放:lr_new = lr_base * new_batch / old_batch。这样算出来大约是 0.005。

python tools/train.py configs/balloon/mask_rcnn_r50_fpn_1x_coco.py \ --work-dir work_dirs/balloon \ --cfg-options optimizer.lr=0.005 data.samples_per_gpu=2

--cfg-options是 MMDetection 提供的命令行覆盖入口,optimizer.lr会直接改写配置里的优化器学习率。data.samples_per_gpu对应 3.1 配置文件里面设的 2,如果前面已经写在配置里,这里可以不加。注意samples_per_gpu在 3.x 里被移到了train_dataloader.batch_size,但思路一样。

Epoch 数量不要直接照抄官方 12。官方 1x 是指 COCO 的 12 epoch,那个数据量大;这个气球数据总计可能就几十到一百多张图,训练很快收敛。我通常先跑 50 epoch,观察 loss 是否稳定。如果验证集 mAP 在 20 epoch 后就不再上升,说明已经过拟合,可以早停。

如果中途断了,想接着训练,用--resume-from

python tools/train.py configs/balloon/mask_rcnn_r50_fpn_1x_coco.py \ --resume-from work_dirs/balloon/epoch_30.pth

resume-from会同时恢复优化器状态和模型权重,而不是只加载权重。这比load-from更适合断点续训。

3.3 测试与可视化:test.py 参数和结果分析

训练结束后,在验证集上跑评估:

python tools/test.py configs/balloon/mask_rcnn_r50_fpn_1x_coco.py \ work_dirs/balloon/epoch_50.pth \ --eval segm

--eval segm是告诉脚本用 COCO mask 评估协议,输出的是 mask AP。如果只做目标检测,可以用--eval bbox,但这里是实例分割,所以重点关注 segm。默认输出结果是一张表的摘要,包括APAP_50AP_75AP_sAP_mAP_l这几项。对于这种单一类别的小目标数据,AP_50通常是最先看的指标,因为 mask 预测的 IoU 阈值在 0.5 时比较稳定。

想要可视化预测结果,可以加--show-dir

python tools/test.py configs/balloon/mask_rcnn_r50_fpn_1x_coco.py \ work_dirs/balloon/epoch_50.pth \ --eval segm --show-dir work_dirs/balloon/viz/

脚本会把每张测试图的预测框、掩码叠加在原图上,保存到viz目录。这一步很关键,因为 mAP 只能告诉你整体好坏,而可视化能让你一眼看出模型是不是把气球区域整个抠出来了,还是只分割了半边。我第一次跑这份数据集时,看 mAP 觉得还能接受,看了可视化才发现模型对深色背景下的暗红气球识别率极低,这才针对性加了更多数据增强。

4. 避坑指南:数据路径、类别数、显存和 RLE 解码

4.1 训练一开始就报 FileNotFoundError:路径拼错导致找不到图片

现象:执行训练脚本后,日志里跳出 FileNotFoundError,提示找不到类似于data/balloon/val2017/8053085540_a72bd21a64_k.jpg的文件,或者报Directory not found

原因:最常见的是三种:一是data_root写成了绝对路径,但实际数据放在其他盘;二是解压后的目录名与配置里的img_prefix大小写不一致,比如把气球数据解压成了Balloon_mask_rcnn,而配置里用的是全小写;三是在 Windows 上解压后产生的反斜杠路径在某些脚本拼接时出错。

解决:先在命令行里用一条命令确认路径能对上:

find data/balloon -maxdepth 2 -type f | head -5

把输出和配置里的ann_fileimg_prefix逐段比对。我一般会在配置里用os.path.abspath打印一遍最终路径,写进 debug 脚本里。最省事的方法是直接把data_root改成相对路径,并保证工作目录在mmdetection项目根目录下启动训练。另外检查一下ann_file里面的image字段的file_name是否和train2017目录里的实际文件名一致,因为有些转换脚本会错误地带上子目录前缀,比如train2017/xxx.jpg,而img_prefix又加了一次train2017/,导致重复路径。

4.2 训练直接报 num_classes mismatch:忘了覆盖 bbox head 和 mask head

现象:训练刚开始,在第一次 forward 时报size mismatchRuntimeError: Error(s) in loading state_dict for RPNHead,报错里提到bbox_predmask_fcn的形状对不上,期待维度是 82,实际维度是 2。

原因:这份气球数据集只有 1 个类,但配置里漏写了model.roi_head.bbox_head.num_classes,导致模型仍然按官方 COCO 的 80+1 类输出分类分数。加载预训练权重时,最后一层 FC 的输出维度对不上,直接报错。

解决:回到 3.1 的配置,确认以下两行都存在,并且都改成num_classes=1

model = dict( roi_head=dict( bbox_head=dict(num_classes=1), mask_head=dict(num_classes=1) ) )

如果用了--cfg-options临时覆盖,也要同时覆盖这两个字段:

--cfg-options model.roi_head.bbox_head.num_classes=1 model.roi_head.mask_head.num_classes=1

这里有一个很多人翻车的细节:bbox_headmask_head都要改,只改 bbox head 会让 mask head 仍然按原来的 80 类输出。代码跑起来可能不报错,但训练出来的 mask 分支完全失效。

4.3 显存溢出 OOM:先降 batch size,不要急着换模型

现象:训练刚开始,显存占用直接拉满,日志报CUDA out of memory,程序退出。

原因:Mask R-CNN 本身就吃显存,R50 backbone 加上 FPN,单图分辨率如果偏大,batch size=2 也可能爆卡。尤其是有些图片尺寸很大,训练时 Resize 没有限制最大边,导致显存峰值过高。

解决:先降 batch size 到 1:

data = dict( samples_per_gpu=1, workers_per_gpu=2, ... )

如果还是 OOM,检查输入尺寸的配置。可以在data里加上 train pipeline 的Resize限制,把最大边限制在(1333, 800),这是 COCO 训练的默认值。实际这份气球数据里的图片来自 Flickr,长宽比各异,有些原图非常大,建议把img_scale设置在(800, 1333),减少显存压力。还可以用梯度累积来模拟更大的 batch size:

--cfg-options optimizer_config.grad_clip.max_norm=35

但梯度累积在 MMDetection 2.x 里没有内置参数,需要改训练循环,不如直接降 batch size 实在。只要模型能塞进显存,单卡 batch size=1 也是能训的,就是收敛慢一点。

4.4 测试结果全黑、没有 mask:score_thr、mask_thr 与 RLE 解码

现象:测试后test.py输出的 mAP 是 0,或者用--show-dir保存的图片只有原图,没有任何颜色覆盖,看起来像模型完全没预测到东西。

原因:可能性很多,最常见的是 score threshold 设得过高。MMDetection 测试时默认score_thr=0.05,如果你手动改高了,比如 0.8,模型输出置信度普遍在 0.5 左右时,所有预测都会被过滤掉。另一种可能是数据标注里iscrowd=1的实例过多,模型把目标都当成 crowd 掩盖了,但这份数据集很少见。

解决:先用默认阈值测试一次,再做可视化时调低阈值:

python tools/test.py configs/balloon/mask_rcnn_r50_fpn_1x_coco.py \ work_dirs/balloon/epoch_50.pth \ --eval segm --show-dir work_dirs/balloon/viz/ \ --cfg-options model.test_cfg.score_thr=0.3

model.test_cfg.score_thr是测试阶段后处理的置信度阈值。对单一类别且图像较简单的数据集,0.3 通常能看到部分预测。如果 0.05 下 mAP 仍然为 0,那问题大概率出在数据加载上,回到第 2 章,先确认coco.annToMask()能正确输出非零 mask。RLE 解码失败通常是因为转换脚本没有把counts从 bytes 转成 str,pycocotools 在 Python 3 下会处理这种差异,但某些自定义 Dataset 不会。你在自己写转换脚本时,一定要在maskUtils.encode()后加上rle['counts'] = rle['counts'].decode('ascii')

5. 数据集从哪来:任意分割标注转 COCO 格式的通用脚本

5.1 从二值掩码到 RLE:推荐 pycocotools 的 mask 编码路径

这份气球数据集已经是 COCO 格式,但你下次拿到的可能是 LabelMe 的 json,或者一堆黑底白色的 PNG 掩码。掌握「二值掩码转 COCO annotation」的思路,才是真正的一劳永逸。转换的核心是先得到二值 mask,然后用 pycocotools 编码成 RLE。

import numpy as np from pycocotools import mask as maskUtils def encode_mask(mask_binary): # mask_binary: HxW 的 0/1 数组,dtype 可以是 bool 或 uint8 mask = np.asfortranarray(mask_binary.astype(np.uint8)) rle = maskUtils.encode(mask) rle['counts'] = rle['counts'].decode('ascii') return rle

这段代码里的关键点是np.asfortranarray。COCO 的 RLE 编码内部按列优先处理,必须先把数组转成 Fortran 序,否则编码结果和实际 mask 不一致,解码后会出现掩码错位的现象。rle['counts']在 Python 3 下是 bytes 类型,直接写进 JSON 会序列化失败,所以要先decode('ascii')转成字符串。

如果你手里的是多边形顶点坐标,可以用maskUtils.frPyObjects先转成 RLE:

polygons = [x1, y1, x2, y2, ...] # 扁平列表 rle = maskUtils.frPyObjects([polygons], height, width) rle = maskUtils.merge(rle)

frPyObjects的输入需要[polygon_list],即使只有一个多边形也要再包一层列表。它返回一个 RLE 对象,因为 poly 转 RLE 时可能拆成多个小段,所以通常还要merge合并。如果原图目标有孔洞,多边形是外轮廓加内轮廓,frPyObjects也能处理,但要保证轮廓点的顺序正确,内轮廓方向与外轮廓相反。

5.2 构造 annotation 字段:bbox、area、segmentation、iscrowd

拿到 RLE 后,不要手算 bbox 和面积,直接交给 pycocotools:

def build_coco_annotation(ann_id, image_id, category_id, mask_binary): rle = encode_mask(mask_binary) bbox = maskUtils.toBbox(rle).tolist() # [x, y, w, h] area = float(maskUtils.area(rle)) annotation = { "id": ann_id, "image_id": image_id, "category_id": category_id, "bbox": bbox, "area": area, "segmentation": rle, "iscrowd": 0 } return annotation

maskUtils.toBbox(rle)返回的是一个 numpy 数组,所以要用.tolist()转成 Python list。maskUtils.area(rle)返回的是 RLE 对应的真实像素面积,单位是像素。这里不需要自己算最小外接矩形,因为 COCO 的 bbox 定义就是「能包住 mask 的轴对齐矩形」,pycocotools 的实现和评估时用的完全一致,手工算容易在边缘情况下差一两个像素。

iscrowd一般设 0。只有当一张图里有大量重叠目标且无法逐目标标注时,才把整个区域标成 crowd 并设 1。注意 crowd 的segmentation必须是 RLE,不能是 polygon,且训练时 MMDetection 对 crowd 的处理是忽略其 loss,所以普通数据不要乱设。

5.3 组装 images 与 categories:保证 ID 连续并做数据切分

有了 annotation 列表,还要组装images数组。images里的每个元素需要包含idfile_namewidthheight,其他字段比如licensedate_captured可以省略。

from PIL import Image import os images = [] annotations = [] ann_id = 1 for img_id, filename in enumerate(os.listdir('train_imgs'), start=1): w, h = Image.open(os.path.join('train_imgs', filename)).size images.append({ "id": img_id, "file_name": filename, "width": w, "height": h }) mask_path = os.path.join('train_masks', filename.replace('.jpg', '.png')) mask_binary = np.array(Image.open(mask_path).convert('L')) > 0 annotations.append(build_coco_annotation(ann_id, img_id, 1, mask_binary)) ann_id += 1 categories = [{"id": 1, "name": "balloon"}] coco_json = { "images": images, "annotations": annotations, "categories": categories } with open('instances_train2017.json', 'w') as f: json.dump(coco_json, f)

这段脚本里img_id从 1 开始递增,ann_id也从一个独立的计数器递增。注意image_id必须和images数组里的id对应上,不能复用文件名里的数字。file_name只需要写文件名,img_prefix由 MMDetection 配置负责拼接。如果一张图有多个 mask,比如多个气球,你的循环要分别对每个 mask 调用build_coco_annotation,并且image_id相同但ann_id不同。

切分数据时要注意:不能直接按文件顺序随机分,而是按场景分。气球数据集里同一张照片可能连着好几张,如果同一场景的图同时进了 train 和 val,验证集会虚高。这一点很多教程不会提,我自己第一次做类似数据集时就吃过亏,mAP 高得离谱,换一批真实场景图直接掉点。

6. 进阶技巧:用 COCO 预训练权重微调,只看 mask AP 评估效果

这份气球数据量小,从头训练 Backbone 很容易过拟合。正确做法是加载 COCO 预训练权重,只让后面的 head 重新学。在 MMDetection 里,只要在配置里加一行:

load_from = './checkpoints/mask_rcnn_r50_fpn_1x_coco.pth'

由于气球只有 1 类,而预训练模型是 80 类,加载时最后一个分类层和 mask 分支的维度不匹配。MMDetection 默认会忽略形状不一致的权重,只加载 backbone 和 FPN 的部分,这正好是我们想要的。如果你希望连 RPN 也复用,直接默认即可,不用额外写代码。

微调时的学习率不宜过大,我一般设 0.001 到 0.002,是正常训练学习率的一半以下。训练 30 epoch 左右就能看到验证集 mAP 稳定。紧接着用第 3 章的测试命令评估,重点看下面这行输出:

Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.672 Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=100 ] = 0.912 Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=100 ] = 0.788

对单个类别的小数据集,AP_50到 0.9 以上说明模型基本能框住并分割出气球;AP_75也能到 0.7 以上,说明掩码边缘质量不错。如果你的AP_50高但AP_75掉得很惨,大概率是 mask 边缘不够精细,优先检查数据集标注边缘是否平滑,其次再考虑更换更强的 backbone。从那以后,我每次拿到新的分割数据都会先写一个 20 行的检查脚本验证 JSON 解码,再用预训练权重跑 10 个 epoch 做 smoke test,确认 loss 在降、mAP 能过 0.5,才开始全量调参。希望帮到你。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 23:54:48

OpenNI多Kinect同步实战:USB隔离、双上下文与时间戳对齐

简介&#xff1a;本资源是一份面向计算机视觉与多传感器开发者的实用技术文档&#xff0c;聚焦于使用OpenNI框架在单台PC上同时读取多个Kinect设备的完整实现方案&#xff0c;适用于机器人感知、三维重建、多人交互等需要多视角深度数据的进阶应用场景。文档以C代码为核心&…

作者头像 李华
网站建设 2026/9/24 23:53:36

TCP端口为什么是65535?从16位字段到实践排查全解析

1. 从一道“送命题”说起做网络开发、运维或者后端服务的同学&#xff0c;几乎都遇到过这样一幕&#xff1a;面试官漫不经心地问一句“TCP/UDP端口的范围为什么是0到65535&#xff0c;总共65536个&#xff1f;为什么不是65535个&#xff1f;”——注意&#xff0c;这里已经有一…

作者头像 李华
网站建设 2026/9/24 23:53:09

大模型代码评审如何省下九成token?开源工具架构与落地实践

1. 从"九分之一 token"说起&#xff1a;这个开源工具到底解决了什么痛点第一次看到"token 只花九分之一"这个说法&#xff0c;我的反应是&#xff1a;要么是标题党&#xff0c;要么是评测口径有猫腻。做代码评审自动化的人都知道&#xff0c;大模型跑一次全…

作者头像 李华
网站建设 2026/9/24 23:51:59

AgentScope 2.0多智能体编排实战:从Python到Java企业级应用

1. 为什么我把AgentScope当成多智能体项目的首选框架1.1 一个差点被我错过的高性能多智能体编排框架先说结论&#xff1a;如果你正在做多智能体应用&#xff0c;想找一套能支撑真实业务、能上生产环境、又不用被底层通信细节折磨的编排框架&#xff0c;AgentScope值得认真看一眼…

作者头像 李华
网站建设 2026/9/24 23:51:52

基于YOLOv5的智能人脸标注工具:从预标注到高效数据标注实战

简介&#xff1a;基于YOLOv5的人脸数据集标注工具&#xff0c;面向需要快速构建人脸数据集的算法工程师与开发者。其核心价值是自动化人脸标注流程&#xff0c;支持自定义人脸检测模型&#xff0c;并可将标注结果导出为PASCAL VOC XML、MS COCO JSON、YOLO TXT等主流格式&#…

作者头像 李华