# 教程 3: 自定义数据前处理流水线 ## 设计数据前处理流水线 参照惯例,MMPose 使用 `Dataset` 和 `DataLoader` 实现多进程数据加载。 `Dataset` 返回一个字典,作为模型的输入。 由于姿态估计任务的数据大小不一定相同(图片大小,边界框大小等),MMPose 使用 MMCV 中的 `DataContainer` 收集和分配不同大小的数据。 详情可见[此处](https://github.com/open-mmlab/mmcv/blob/master/mmcv/parallel/data_container.py)。 数据前处理流水线和数据集是相互独立的。 通常,数据集定义如何处理标注文件,而数据前处理流水线将原始数据处理成网络输入。 数据前处理流水线包含一系列操作。 每个操作都输入一个字典(dict),新增/更新/删除相关字段,最终输出更新后的字典作为下一个操作的输入。 数据前处理流水线的操作可以被分类为数据加载、预处理、格式化和生成监督等(后文将详细介绍)。 这里以 Simple Baseline (ResNet50) 的数据前处理流水线为例: ```python train_pipeline = [ dict(type='LoadImageFromFile'), dict(type='TopDownRandomFlip', flip_prob=0.5), dict(type='TopDownHalfBodyTransform', num_joints_half_body=8, prob_half_body=0.3), dict(type='TopDownGetRandomScaleRotation', rot_factor=40, scale_factor=0.5), dict(type='TopDownAffine'), dict(type='ToTensor'), dict( type='NormalizeTensor', mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), dict(type='TopDownGenerateTarget', sigma=2), dict( type='Collect', keys=['img', 'target', 'target_weight'], meta_keys=[ 'image_file', 'joints_3d', 'joints_3d_visible', 'center', 'scale', 'rotation', 'bbox_score', 'flip_pairs' ]), ] val_pipeline = [ dict(type='LoadImageFromFile'), dict(type='TopDownAffine'), dict(type='ToTensor'), dict( type='NormalizeTensor', mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), dict( type='Collect', keys=['img'], meta_keys=[ 'image_file', 'center', 'scale', 'rotation', 'bbox_score', 'flip_pairs' ]), ] ``` 下面列出每个操作新增/更新/删除的相关字典字段。 ### 数据加载 `LoadImageFromFile` - 新增: img, img_file ### 预处理 `TopDownRandomFlip` - 更新: img, joints_3d, joints_3d_visible, center `TopDownHalfBodyTransform` - 更新: center, scale `TopDownGetRandomScaleRotation` - 更新: scale, rotation `TopDownAffine` - 更新: img, joints_3d, joints_3d_visible `NormalizeTensor` - 更新: img ### 生成监督 `TopDownGenerateTarget` - 新增: target, target_weight ### 格式化 `ToTensor` - 更新: 'img' `Collect` - 新增: img_meta (其包含的字段由 `meta_keys` 指定) - 删除: 除了 `keys` 指定以外的所有字段 ## 扩展和使用自定义流水线 1. 将一个新的处理流水线操作写入任一文件中,例如 `my_pipeline.py`。它以一个字典作为输入,并返回一个更新后的字典。 ```python from mmpose.datasets import PIPELINES @PIPELINES.register_module() class MyTransform: def __call__(self, results): results['dummy'] = True return results ``` 1. 导入定义好的新类。 ```python from .my_pipeline import MyTransform ``` 1. 在配置文件中使用它。 ```python train_pipeline = [ dict(type='LoadImageFromFile'), dict(type='TopDownRandomFlip', flip_prob=0.5), dict(type='TopDownHalfBodyTransform', num_joints_half_body=8, prob_half_body=0.3), dict(type='TopDownGetRandomScaleRotation', rot_factor=40, scale_factor=0.5), dict(type='TopDownAffine'), dict(type='MyTransform'), dict(type='ToTensor'), dict( type='NormalizeTensor', mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), dict(type='TopDownGenerateTarget', sigma=2), dict( type='Collect', keys=['img', 'target', 'target_weight'], meta_keys=[ 'image_file', 'joints_3d', 'joints_3d_visible', 'center', 'scale', 'rotation', 'bbox_score', 'flip_pairs' ]), ] ```