MMSegmentation 新增数据增强(Transform)完全指南:自定义 Flip 到注册配置与源码剖析
MMSegmentation 新增数据增强Transform完全指南自定义 Flip 到注册配置与源码剖析【免费下载链接】mmsegmentationOpenMMLab Semantic Segmentation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmsegmentation本篇技术指南聚焦 OpenMMLab 语义分割工具箱 MMSegmentation 中数据增强Transform的自定义与接入方法。你将学会如何基于BaseTransform编写自己的数据增强类、通过TRANSFORMS注册表将其接入数据流程pipeline并在配置文件与训练脚本中直接使用同时结合仓库源码理解字典字段的增删约定与注册机制。文章以 docs/zh_cn/advanced_guides/add_transforms.md 为主线辅以mmseg/datasets/transforms/下的实现代码与测试用例进行纵深解析。一、数据增强在 MMSegmentation 中的角色定位在 MMSegmentation 1.x 中数据准备流程与数据集是解耦的数据集负责定义如何处理标注如reduce_zero_label、类别映射而数据流程pipeline负责定义准备数据字典的所有步骤。每一个数据增强操作Transform接收一个字典作为输入处理后返回同样结构或增删字段后的字典供下一个操作使用。所有内置转换都继承自 MMCV 的BaseTransform其输入和输出类型均为字典。以一个简单示例说明从 transforms.md 中可以看到使用LoadAnnotations处理数据字典后会新增gt_seg_map与seg_fields两个字段from mmseg.datasets.transforms import LoadAnnotations transforms LoadAnnotations() results dict( img_path./data/cityscapes/leftImg8bit/train/aachen/aachen_000000_000019_leftImg8bit.png, seg_map_path./data/cityscapes/gtFine/train/aachen/aachen_000015_000019_gtFine_instanceTrainIds.png, reduce_zero_labelFalse, seg_fields[]) data_dict transforms(results) print(data_dict.keys()) # dict_keys([img_path, seg_map_path, reduce_zero_label, seg_fields, gt_seg_map])从 mmseg/datasets/transforms/init.py 可以看到仓库目前已内置并导出了RandomFlip、RandomCrop、RandomResize、Resize、PhotoMetricDistortion、PackSegInputs、LoadAnnotations等二十余种变换它们被组织在mmseg/datasets/transforms/下的三个文件中文件负责的变换类型loading.py数据加载LoadImageFromFile、LoadAnnotations等transforms.py预处理RandomCrop、RandomRotate、PhotoMetricDistortion、Resize等formatting.py格式修改PackSegInputs等这正是 transforms.md 中划分的三大类操作数据加载、预处理与格式修改此外还有测试阶段专用的测试数据增强。二、自定义数据增强的完整步骤自定义数据增强必须继承BaseTransform并实现transform函数。以 add_transforms.md 中给出的简单翻转变换MyFlip为例完整流程分为四步。步骤 1编写并注册变换类import random import mmcv from mmcv.transforms import BaseTransform, TRANSFORMS TRANSFORMS.register_module() class MyFlip(BaseTransform): def __init__(self, direction: str): super().__init__() self.direction direction def transform(self, results: dict) - dict: img results[img] results[img] mmcv.imflip(img, directionself.direction) return results关键点说明继承BaseTransform它来自mmcv.transforms是 MMCV 2.x 中所有数据变换的基类。基类实现了__call__协议因此transform实例可以直接被transform(data_dict)调用同时基类还内置了cache_randomness等用于随机性管理的机制详见下文。实现transform(self, results: dict) - dict接收数据字典返回处理后的字典。这里通过mmcv.imflip对results[img]执行水平或垂直翻转。使用TRANSFORMS.register_module()装饰器这是接入配置系统的关键注册后即可用配置字符串dict(typeMyFlip, directionhorizontal)的方式实例化。步骤 2确保新类被导入注册只是将类登记到注册表要让 MMSegmentation 在运行时能看见它还必须保证包含该类的文件被执行导入from .my_pipeline import MyFlip实际项目中通常将自定义变换放入自定义模块文件如my_pipeline.py然后在入口脚本或包__init__.py中导入。步骤 3实例化并处理数据字典定义完成后可以直接在 Python 脚本中实例化并处理数据字典import numpy as np transform MyFlip(directionhorizontal) data_dict {img: np.random.rand(224, 224, 3)} data_dict transform(data_dict) processed_img data_dict[img]这里data_dict至少需要包含img键输出字典中img被更新为翻转后的图像。步骤 4在配置文件的 pipeline 中使用更常见的用法是接入训练/测试配置中的数据流程。以 PSPNet 的train_pipeline为参照来自 transforms.md自定义变换可以这样插入crop_size (512, 1024) train_pipeline [ dict(typeLoadImageFromFile), dict(typeLoadAnnotations), dict( typeRandomResize, scale(2048, 1024), ratio_range(0.5, 2.0), keep_ratioTrue), dict(typeRandomCrop, crop_sizecrop_size, cat_max_ratio0.75), dict(typeRandomFlip, prob0.5), dict(typePhotoMetricDistortion), dict(typePackSegInputs) ] # 插入自定义变换后的 pipeline train_pipeline [ dict(typeLoadImageFromFile), dict(typeLoadAnnotations), dict( typeMyFlip, # 自定义变换 directionhorizontal), dict(typePackSegInputs), ]重要注意事项如果要在配置文件中使用MyFlip必须确保在运行时导入了包含MyFlip的文件。否则配置解析时会抛出找不到该类型的错误。三、深入源码TRANSFORMS 注册表机制为什么注册之后就能通过字符串配置实例化这得益于 MMEngine 的注册表机制。在 mmseg/registry/registry.py 中MMSegmentation 定义了自己的TRANSFORMS注册表TRANSFORMS Registry( transform, parentMMENGINE_TRANSFORMS, locations[mmseg.datasets.transforms])从源码可以解读出三层信息继承自 MMENGINE 的TRANSFORMS这意味着 MMCV/MMEngine 内置的所有变换如RandomResize、Resize、LoadImageFromFile也可以直接在 MMSegmentation 的 pipeline 中通过字符串使用。locations指定默认搜索路径注册表会在mmseg.datasets.transforms模块中自动搜索已注册的类这也是为什么所有内置变换都集中在该目录下。字符串实例化配置中的dict(typeMyFlip, directionhorizontal)会被解析为TRANSFORMS.build(...)底层等价于MyFlip(directionhorizontal)。这一点在 tests/test_datasets/test_transform.py 的测试用例中得到印证——测试中正是通过TRANSFORMS.build(transform)来构建Resize、RandomResize等变换并断言其输出img_shape的。同时mmseg/datasets/transforms/init.py 中集中导出了所有内置变换例如RandomFlip实际上继承自 MMCV 的同名类见 transforms.py并在其基础上补充了分割图相关的字段处理逻辑。自定义变换若要获得同样的默认可用性也应在包的__init__.py中导出。四、理解数据字典字段约定添加 / 更新 / 删除编写高质量的自定义变换必须清楚每个操作对字典字段的影响。原文档 transforms.md 按添加 / 更新 / 删除三个维度总结了各内置变换的字段约定这是设计自定义变换时最重要的参考规范变换类别添加字段更新字段删除字段LoadImageFromFile数据加载img、img_shape、ori_shape——LoadAnnotations数据加载seg_fields、gt_seg_map——RandomResize预处理scale、scale_factor、keep_ratioimg、img_shape、gt_seg_map—Resize预处理scale、scale_factor、keep_ratioimg、gt_seg_map、img_shape—RandomCrop预处理—img、gt_seg_map、img_shape—RandomFlip预处理flip、flip_directionimg、gt_seg_map—PhotoMetricDistortion预处理—img—PackSegInputs格式修改inputs、data_sample—由meta_keys指定的键并入data_sample元信息及其余所有键4.1 从源码看字段约定的落地这些约定并非文档虚构而是真实体现在源码实现中。例如RandomCroptransforms.py构造函数支持crop_sizeint 或 (h, w) 元组、cat_max_ratio单类占比上限默认 1.0与ignore_index默认 255transform中通过results.get(seg_fields, [])遍历所有分割图字段并同步裁剪最后更新results[img_shape]当cat_max_ratio 1.0时会最多重试 10 次生成裁剪框使裁剪区域内最大类别占比不超过该阈值这是语义分割中避免裁剪区域被单一类别如背景主导的经典技巧。又如PhotoMetricDistortiontransforms.py其按固定顺序对图像施加光度失真每个子变换的应用概率为 0.5随机对比度的位置是第二或倒数第二模式 0 或 11. 随机亮度 2. 随机对比度模式 0 3. 将颜色从 BGR 转换为 HSV 4. 随机饱和度 5. 随机色调 6. 将颜色从 HSV 转换为 BGR 7. 随机对比度模式 1再如LoadAnnotationsloading.py其参数reduce_zero_label用于将背景标签 0 整体减 1 映射实现中将 0 先置为 255 再统一减 1避免下溢imdecode_backend控制解码后端默认pillow这些参数在配置中均可直接指定。4.2 PackSegInputspipeline 的收尾器PackSegInputsformatting.py通常作为 pipeline 的最后一步负责把处理好的数据打包成模型前向所需的结构将img从 HWC 转为 CHW 并封装为torch.Tensor存入inputs将gt_seg_map转换为SegDataSample下的PixelDatagt_sem_seg存入data_sample将meta_keys指定的元信息默认含img_path、ori_shape、img_shape、pad_shape、scale_factor、flip、flip_direction、reduce_zero_label等收集到data_sample的 metainfo 中其余字段全部从结果字典移除。因此自定义变换若放在PackSegInputs之前只要保证img、gt_seg_map分割任务等关键字段存在即可若需要把自定义信息带入模型则需考虑将其加入meta_keys或放入data_sample。五、测试驱动如何验证自定义变换仓库的测试代码提供了自定义变换验证的范式。在 tests/test_datasets/test_transform.py 中测试通过如下模式构建并调用变换from mmseg.datasets.transforms import * # noqa from mmseg.registry import TRANSFORMS init_default_scope(mmseg) # 初始化 mmseg 默认作用域 transform dict(typeResize, scale(1333, 800), keep_ratioTrue) resize_module TRANSFORMS.build(transform) results dict() img mmcv.imread(tests/data/color.jpg, color) results[img] img results[img_shape] img.shape results[ori_shape] img.shape results[pad_shape] img.shape results[scale_factor] 1.0 resized_results resize_module(results.copy()) assert resized_results[img_shape] (750, 1333)对自定义MyFlip而言可以采用同样的方式验证构造包含img的results字典用TRANSFORMS.build(dict(typeMyFlip, directionhorizontal))构建后调用并断言img的数值与mmcv.imflip的预期输出一致。注意两点init_default_scope(mmseg)保证自定义注册表作用域正确初始化测试环境需要先安装并导入mmseg包使mmseg.datasets.transforms中的内置变换完成注册。六、从零编写自定义变换的检查清单与最佳实践综合原文档与源码在 MMSegmentation 中新增一个可投入训练的自定义数据增强建议按以下清单自查继承BaseTransform实现transform(self, results: dict) - dict用TRANSFORMS.register_module()注册保证配置字符串可用确保运行时导入在入口脚本或包__init__.py中from my_module import MyFlip遵守字段约定明确声明并实现添加 / 更新 / 删除哪些字典键并在 docstring 中记录Required Keys、Modified Keys、Added Keys仓库内置变换均遵循此文档规范同步处理分割图若变换会修改图像几何翻转、裁剪、缩放、旋转必须同步处理results.get(seg_fields, [])中所有分割图字段且分割图插值应使用nearest模式避免类别标签被插值污染注意随机性管理涉及随机采样的变换如随机参数生成建议使用基类的cache_randomness装饰器仓库中RandomCrop.crop_bbox、RandomRotate.generate_degree均如此保证多次调用时随机结果一致且可复现置于PackSegInputs之前所有需要保留到模型输入的字段必须在PackSegInputs之前完成注入补充测试用例参照 tests/test_datasets/test_transform.py 的模式覆盖参数分支如directionhorizontal与vertical与边界情况。此外当自定义变换需要与其他 MMCV 变换混用时可直接在 pipeline 中并列书写因为 MMSegmentation 的TRANSFORMS注册表以 MMEngine 的TRANSFORMS为父注册表MMCV 内置的RandomResize、Resize、LoadImageFromFile等无需重复实现即可使用。这也是 transforms.md 中 PSPNet 示例 pipeline 能直接混用RandomResize来自 MMCV与PackSegInputs来自 MMSegmentation的底层原因。七、结语数据增强是语义分割训练流程中最灵活的定制点之一。通过本文你已掌握在 MMSegmentation 中新增数据增强的完整链路继承BaseTransform编写transform函数 → 通过TRANSFORMS注册 → 导入模块 → 在配置 pipeline 中字符串化使用并理解了其背后的注册表机制与字典字段约定。若需进一步了解数据流程的整体设计如RandomResize、RandomCrop等内置变换的字段明细可继续阅读 docs/zh_cn/advanced_guides/transforms.md若想学习如何为自定义数据集接入这些变换可参考 docs/zh_cn/advanced_guides/add_datasets.md。【免费下载链接】mmsegmentationOpenMMLab Semantic Segmentation Toolbox and Benchmark.项目地址: https://gitcode.com/GitHub_Trending/mm/mmsegmentation创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →