ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

COCO数据集与MMDetection训练实战:气球Mask R-CNN避坑指南

COCO数据集与MMDetection训练实战:气球Mask R-CNN避坑指南 简介面向使用MMDetection进行实例分割的研究者与开发者这是一份气球Mask R-CNN标注转COCO格式的现成数据集可直接用于模型训练与测试免去繁琐的数据转换步骤。压缩包共76个文件包含74张jpg图像和2个json标注文件整体约36.89MB目录下区分了train2017与val2017子集json文件按COCO标准组织边界框与分割掩模信息方便框架直接读取。已有512人学习/下载。数据集贴合气球检测与分割场景适合作为入门实例分割的练手数据也可用于快速验证Mask R-CNN在该类任务上的效果结合MMDetection的模块化配置能帮助使用者专注于模型调参与结果分析减少数据预处理投入。1. 拿到一份 COCO 格式气球数据集最该先做的事是什么如果你手里已经拿到了解压出train2017、val2017和两个instances_*.json的资源说明这不是一张普通图片包而是一份可以直接喂给 MMDetection 的 COCO 格式数据集。这份气球 Mask R-CNN 数据集的核心价值是把经典 balloon 示例里的图片和标注按 COCO 2017 的目录规范重新整理过解压后不需要补写转换脚本改改配置就能直接跑训练。它的图片规模不大、类别只有气球一类目标大小差异却很典型特别适合刚入门实例分割的人用来打通「数据集 → 配置文件 → 训练 → 验证」整条链路。如果你已经在看 mmdetection 官方文档正好缺一份能快速跑起来的小数据集这份资源可以省掉你自己导标注的功夫。2. 拆开压缩包先别急着训练COCO 格式核对与标注检查2.1 资源里到底有哪些文件目录怎么摆从文件清单看这个压缩包采用的是 COCO 2017 的同款目录命名train2017/和val2017/放图片annotations/下放instances_train2017.json和instances_val2017.json。几乎所有以CocoDataset为基类的目标检测配置默认都会去data/coco/下找这组路径所以把目录摆放成 mmdet 熟悉的样子后面就少改一行代码。文件 / 目录作用train2017/训练图片JPG 格式文件名带长数字 IDval2017/验证图片结构和训练集一致instances_train2017.jsonCOCO 格式训练标注包含 bbox、mask、类别instances_val2017.jsonCOCO 格式验证标注用于测试和算 mAP文件名里的_b、_k后缀是 Flickr 原图 ID 的一部分不是类别标签。我第一次拿到的时候也差点以为_k是某种特殊标注实际读 JSON 之后确认它只影响文件名的唯一性不影响训练。下面所有处理都以目录结构为准不要把文件名后缀当特征。2.2 instances_*.json 的三个顶层字段决定了你能不能直接 trainCOCO 标注 JSON 的顶层只有images、annotations、categories三个字段。很多转出来的数据集格式看着像 COCO但内部字段缺胳膊少腿一喂给 mmdetection 就报 KeyError。所以第一步先用脚本把结构打出来import json ann_path instances_train2017.json with open(ann_path, r, encodingutf-8) as f: data json.load(f) print(images 数量:, len(data[images])) print(annotations 数量:, len(data[annotations])) print(categories 内容:, data[categories]) print(第一张图字段:, list(data[images][0].keys())) print(第一个标注字段:, list(data[annotations][0].keys()))images中的每个元素至少要有id、file_name、width、height。annotations中每个元素要有id、image_id、category_id、bbox、segmentation、area、iscrowd。categories则定义 id 到类别名的映射。跑完这段如果三个字段都齐全数据集基本可以直接进训练管线。如果哪一项缺失后面对应的数据增强或损失计算就会在某个环节崩掉。2.3 用手头代码做一次“数据集体检”光看字段还不够我一般会再跑一段体检脚本确认 bbox 没有落在图片外面segmentation 类型能被 mmdet 正确解析。COCO 的segmentation有两种形态列表表示多边形多边形点集字典表示 RLE 压缩掩码两者 mmdet 都能处理但校验方式不一样。from pycocotools.coco import COCO import os coco COCO(instances_train2017.json) img_ids coco.getImgIds()[:50] ann_ids coco.getAnnIds(imgIdsimg_ids) anns coco.loadAnns(ann_ids) for a in anns[:5]: img coco.loadImgs(a[image_id])[0] x, y, w, h a[bbox] if x w img[width] or y h img[height]: print(bbox 超界:, a[id]) print(iscrowd:, a[iscrowd], seg 类型:, type(a[segmentation]))bbox的坐标是xywh不是xyxy这是新手最容易看错的地方。mmdetection 内部实际是把bbox转回xyxy参与 IoU 计算所以转换时一旦把顺序写反loss 会剧烈震荡。iscrowd1的标注在训练中会被忽略COCO 里 crowd 区域通常是一群重叠目标对单类气球数据集影响不大但检查出来总比训练到一半莫名报 NaN 强。2.4 为什么这份资源能直接兼容最新 MMDetectionMMDetection 3.x 里CocoDataset的加载逻辑非常固定先读annotations里的 JSON再按data_prefix拼出图片路径然后通过metainfo处理类别名。这份气球数据集已经在 JSON 内部把categories定义成了气球而不是完整 80 类所以只要在配置里把num_classes改成 1并在metainfo里声明(balloon,)框架就不会把背景当作第一个类别。相比那些从 VOC 或 Labelme 手工转出来、还带着背景类的数据集这份资源省掉了最长的调试环节。你真正需要做的只是把目录摆对、把类别数量改对。3. 用最新 MMDetection 训练从 config 到命令行3.1 目录组织与软链接把文件摆成 mmdet 认识的样子MMDetection 的默认数据目录是./data/coco/如果你的配置文件写到别的地方就要同步改data_root。我习惯用软链接而不是把几个 GB 的图片复制进项目里省磁盘也方便切换数据集。mkdir -p data/coco/annotations ln -s /your_path/balloon_dataset/train2017 data/coco/train2017 ln -s /your_path/balloon_dataset/val2017 data/coco/val2017 ln -s /your_path/balloon_dataset/instances_train2017.json data/coco/annotations/instances_train2017.json ln -s /your_path/balloon_dataset/instances_val2017.json data/coco/annotations/instances_val2017.json ls -l data/coco/软链接路径要用绝对路径否则换个工作目录就失效。这个结构里data_root就是data/coco/ann_file是annotations/instances_train2017.jsondata_prefix里的img是train2017/。三段路径拼接起来正好是实际文件路径缺一段就会报 FileNotFoundError。3.2 改配置不到 20 行的关键改动以 mmdet 自带的mask-rcnn_r50_fpn_1x_coco配置为基底通常只需要改动四个地方data_root、metainfo、num_classes、batch_size。如果你是 MMDetection 3.x推荐用显式配置块num_classes 1 metainfo dict(classes(balloon,)) data_root data/coco/ train_dataloader dict( batch_size2, datasetdict( typeCocoDataset, data_rootdata_root, metainfometainfo, ann_fileannotations/instances_train2017.json, data_prefixdict(imgtrain2017/), filter_cfgdict(filter_empty_gtTrue, min_size32), ), )这里最容易漏的是num_classes。Mask R-CNN 有两个输出头bbox_head和mask_head都要改成 1不能只改一个。很多教程只写model.roi_head.bbox_head.num_classes1结果跑到 mask 分支的时候维度对不上直接报错。改动之后如果不想改配置文件也可以启动训练时用--cfg-options临时覆盖但类别相关的改动建议写进 config方便复现。3.3 训练命令与常用参数配置改完后启动训练没有太多玄学核心是把工作目录指定好方便断点续训和查看产物python tools/train.py \ work_dirs/mask_rcnn_r50_fpn_1x_balloon.py \ --work-dir work_dirs/balloon \ --amp--amp开启混合精度训练对 8G 显存的卡非常友好。显存还是不够时把train_dataloader的batch_size降到 1同时把optim_wrapper里的accumulative_counts设成 4相当于用梯度累积模拟 batch_size4。训练中如果想中途恢复重新执行同一条命令并加上--resume即可mmdet 会从work_dir里自动找最新的 checkpoint。训练完成后再启动验证就能看到 COCO 风格的bbox_mAP和segm_mAP。这里有一个需要提前认识的点Mask R-CNN 的测试不仅输出检测框还输出每个框的掩码所以控制台打印的是两套 AP千万别只盯着 bbox 那一行。3.4 训练日志里看什么小数据集很容易过拟合日志里的loss_cls降得很快是正常的关键是看loss_mask和loss_bbox。如果loss_mask在前几个 epoch 一直不降多半是 mask 标注有问题比如 segmentation 的多边形点顺序错误或者面积太小。正常情况下一张图只有几个气球20 个 epoch 以内 loss 就能很明显下降。肉眼观察几张验证图会比单纯看 loss 曲线更直观地判断模型有没有真的学会分割轮廓。4. 避坑喂给 MMDetection 前和训练中容易翻车的 5 个细节4.1 路径错位FileNotFoundError 与自动下载的假象现象训练脚本刚开始就跑出大量FileNotFoundError提示找不到xxx.jpg或者界面看起来像在下载数据。原因data_prefix和data_root拼接后的路径与图片实际所在目录不一致。很多人把train2017直接放在项目根目录却让配置去data/coco/train2017/找文件。MMDetection 3.x 的CocoDataset在data_prefix里默认加了img: 如果图片实际在别的子目录必须显式指定。解决打印出第一个样本的完整图片路径确认存在再开训练。我一般会在加载后手动用os.path.exists检查data_root data_prefix[img] file_name。这份气球数据集本身文件名很长后缀又有_k、_b复制粘贴路径时很容易丢字符建议直接用软链接统一目录。4.2 类别映射错mAP 直接为 0现象训练时 loss 在正常下降验证时bbox_mAP 0.0000segm_mAP也是 0一张图都没检测到。原因数据集的categories里 id 是 1但配置里没设置metainfo框架默认按 COCO 80 类去映射把气球的类别 id 对应到“人”上导致预测的类别和标注类别永远对不上。另一种常见原因是num_classes改成了 1但忘记背景类导致模型输出维度错位。解决在 config 里同时设置metainfodict(classes(balloon,))并确认model.roi_head.bbox_head.num_classes1。如果两个都改好仍然为 0先打印data[categories]看 id必要时用--cfg-options model.roi_head.bbox_head.num_classes1 model.roi_head.mask_head.num_classes1强制覆盖。4.3 segmentation 是 RLE 还是 polygon掩码与框不一致现象训练能跑通但验证时输出的掩码出现整张图被填满、或者一只气球被割成好几块。原因从其他工具转 COCO 时segmentation是 polygon 点集但bbox还沿用旧的未更新坐标。Mask R-CNN 的 mask 分支在 RoI 内部做全卷积预测如果 bbox 框住的区域里根本没有完整目标模型只能在框里瞎猜掩码自然乱。还有一部分数据集的segmentation是 RLE dictpycocotools能读但某些自定义转码工具会把counts写错导致掩码面积和实际目标面积差一个量级。解决用pycocotools的annToMask()把每个 annotation 转成 mask再和 bbox 覆盖的区域做对比统计 mask 像素在 bbox 内的占比。如果发现大量标注的 mask 跑到 bbox 外面说明标注源头就有问题这类数据直接删掉比硬留着训练更划算。4.4 显存不够batch_size 与梯度累积现象训练刚开始没几步就报CUDA out of memory。默认mask-rcnn_r50_fpn_1x_coco的 batch_size 是 2在 8G 显卡上跑 ResNet-50 FPN 很容易爆显存。原因Mask R-CNN 比纯检测模型多一个 mask 分支显存占用比 Faster R-CNN 明显高。很多人只调了batch_size没调num_workers和优化器里的梯度累积结果小 batch 导致 loss 剧烈抖动收敛变慢。解决显存不够时先batch_size1再在optim_wrapper里配置accumulative_counts2或 4这一步可以保持等效 batch size 不变。如果还想提速把data_preprocessor的batch_augments里的mixup关掉这类数据增强对显存也不友好。4.5 数据集划分不检查验证集和训练集混在一起现象训练时 mAP 很高一换真实场景图片效果立刻变差典型的“看着好、用不了”。原因这类气球图片本身来自同一批 Flickr 相册如果压缩包在整理时没有严格按图片名去重train2017和val2017里可能混进相似度极高的图。模型在训练时见过几乎一样的背景验证 AP 自然虚高。解决我拿到这份资源后第一件事就是跑一个脚本把两个 json 里的file_name取交集再看图片长度的重复比。如果发现重复就手动把重复图片从训练集挪到验证集或者干脆把 epoch 数调大、用更强的正则化来抑制过拟合让 mask 学的是气球轮廓而不是图片背景。5. 验证模型不是玄学test、mAP 与 mask 可视化训练结束后别急着把模型拿去部署先用 mmdet 自带的 test 脚本跑一遍验证集把segm_mAP和bbox_mAP都记下来。COCO 格式的测试命令比训练简单指定配置、checkpoint 和输出目录即可python tools/test.py \ work_dirs/mask_rcnn_r50_fpn_1x_balloon.py \ work_dirs/balloon/epoch_20.pth \ --metrics bbox segm \ --show-dir results/balloon \ --out results/balloon.pkl--metrics bbox segm是同时输出检测框和分割掩码的 AP只看 bbox 会漏掉 Mask R-CNN 一半的能力--show-dir会把带掩码的预测图直接画出来这是最直观的验证方式。mAP 数字只反映整体水平不代表每个目标都分割得好。我会额外写一段推理脚本挑几张典型图片看掩码边缘是否贴合气球轮廓from mmdet.apis import init_detector, inference_detector model init_detector( work_dirs/mask_rcnn_r50_fpn_1x_balloon.py, work_dirs/balloon/epoch_20.pth, devicecuda:0, ) result inference_detector(model, data/coco/val2017/flickr_sample.jpg) model.show_result( data/coco/val2017/flickr_sample.jpg, result, out_fileresults/flickr_sample_pred.jpg, )这就是我踩过不少坑之后总结出来的习惯每拿到一个“转好的 COCO 数据集”第一件事永远是先跑一遍第 2 章那个体检脚本确认json里的图片名和图片目录能一一对上、bbox没有越界、segmentation能正常转成 mask再动 config。这份气球数据集的标注质量算是比较省心的但检查路径和类别映射这两步我从来不会跳过。从那以后凡是要用 mmdetection 训练自数据集我都会强制走一遍「目录软链 → json 体检 → num_classes 核对 → 小 batch 启动」这条标准流程少走了很多冤枉路。希望帮到你。本文还有配套的精品资源点击获取
返回列表