DATA_cn.md 9.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
## 介绍
本模块是一个Python模块,用于加载数据并将其转换成适用于检测模型的训练、验证、测试所需要的格式——由多个np.ndarray组成的tuple数组,例如用于Faster R-CNN模型的训练数据格式为:`[(im, im_info, im_id, gt_bbox, gt_class, is_crowd), (...)]`

### 实现
该模块内部可分为4个子功能:数据解析、图片预处理、数据转换和数据获取接口。

我们采用`dataset.Dataset`表示一份数据,比如`COCO`数据包含3份数据,分别用于训练、验证和测试。原始数据存储与文件中,通过`dataset.source`加载到内存,然后使用`dataset.transform`对数据进行处理转换,最终通过`dataset.Reader`的接口可以获得用于训练、验证和测试的batch数据。

子功能介绍:

1. 数据解析  
     数据解析得到的是`dataset.Dataset`,实现逻辑位于`dataset.source`中。通过它可以实现解析不同格式的数据集,已支持的数据源包括:
- COCO数据源
     该数据集目前分为COCO2012和COCO2017,主要由json文件和image文件组成,其组织结构如下所示:

  ```
  data/coco/
  ├── annotations
  │   ├── instances_train2014.json
  │   ├── instances_train2017.json
  │   ├── instances_val2014.json
  │   ├── instances_val2017.json
  |   ...
  ├── train2017
  │   ├── 000000000009.jpg
  │   ├── 000000580008.jpg
  |   ...
  ├── val2017
  │   ├── 000000000139.jpg
  │   ├── 000000000285.jpg
  |   ...
  ```


- Pascal VOC数据源
     该数据集目前分为VOC2007和VOC2012,主要由xml文件和image文件组成,其组织结构如下所示:


  ```
  data/pascalvoc/
  ├──Annotations
  │   ├── i000050.jpg
  │   ├── 003876.xml
  |   ...
  ├── ImageSets
  │   ├──Main
              └── train.txt
              └── val.txt
              └── test.txt
              └── dog_train.txt
              └── dog_trainval.txt
              └── dog_val.txt
              └── dog_test.txt
              └── ...
  │   ├──Layout
               └──...
  │   ├── Segmentation
                └──...
  ├── JPEGImages
  │   ├── 000050.jpg
  │   ├── 003876.jpg
  |   ...
  ```



- Roidb数据源
    该数据集主要由COCO数据集和Pascal VOC数据集转换而成的pickle文件,包含一个dict,而dict中只包含一个命名为‘records’的list(可能还有一个命名为‘cname2cid’的字典),其内容如下所示:
```python
(records, catname2clsid)
'records'是一个list并且它的结构如下:
{
    'im_file': im_fname, # 图像文件名
    'im_id': im_id, # 图像id
    'h': im_h, # 图像高度
    'w': im_w, # 图像宽度
    'is_crowd': is_crowd, # 是否重叠
    'gt_class': gt_class, # 真实框类别
    'gt_bbox': gt_bbox, # 真实框坐标
    'gt_poly': gt_poly, # 多边形坐标
}
'cname2id'是一个dict保存了类别名到id的映射

```
我们在`./tools/`中提供了一个生成roidb数据集的代码,可以通过下面命令实现该功能。
```python
# --type: 原始数据集的类别(只能是xml或者json)
# --annotation: 一个包含所需标注文件名的文件的路径
# --save-dir: 保存路径
# --samples: sample的个数(默认是-1,代表使用所有sample)
python ./tools/generate_data_for_training.py
            --type=json \
            --annotation=./annotations/instances_val2017.json \
            --save-dir=./roidb \
            --samples=-1
```
 2. 图片预处理  
    图片预处理通过包括图片解码、缩放、裁剪等操作,我们采用`dataset.transform.operator`算子的方式来统一实现,这样能方便扩展。此外,多个算子还可以组合形成复杂的处理流程, 并被`dataset.transformer`中的转换器使用,比如多线程完成一个复杂的预处理流程。

 3. 数据转换器  
    数据转换器的功能是完成对某个`dataset.Dataset`进行转换处理,从而得到一个新的`dataset.Dataset`。我们采用装饰器模式实现各种不同的`dataset.transform.transformer`。比如用于多进程预处理的`dataset.transform.paralle_map`转换器。

 4. 数据获取接口  
     为方便训练时的数据获取,我们将多个`dataset.Dataset`组合在一起构成一个`dataset.Reader`为用户提供数据,用户只需要调用`Reader.[train|eval|infer]`即可获得对应的数据流。`Reader`支持yaml文件配置数据地址、预处理过程、加速方式等。

主要的APIs如下:




1. 数据解析  

 - `source/coco_loader.py`:用于解析COCO数据集。[详见代码](https://github.com/PaddlePaddle/models/blob/develop/PaddleCV/object_detection/ppdet/data/source/coco_loader.py)
 - `source/voc_loader.py`:用于解析Pascal VOC数据集。[详见代码](https://github.com/PaddlePaddle/models/blob/develop/PaddleCV/object_detection/ppdet/data/source/voc_loader.py)  
 [注意]在使用VOC数据集时,若不使用默认的label列表,则需要先使用`tools/generate_data_for_training.py`生成`label_list.txt`(使用方式与数据解析中的roidb数据集获取过程一致),或提供`label_list.txt`放置于`data/pascalvoc/ImageSets/Main`中;同时在配置文件中设置参数`use_default_label``true`
 - `source/loader.py`:用于解析Roidb数据集。[详见代码](https://github.com/PaddlePaddle/models/blob/develop/PaddleCV/object_detection/ppdet/data/source/loader.py)

2. 算子  
 `transform/operators.py`:包含多种数据增强方式,主要包括:  

```  python
RandomFlipImage水平翻转
RandomDistort随机扰动图片亮度对比度饱和度和色相
ResizeImage根据特定的插值方式调整图像大小
RandomInterpImage使用随机的插值方式调整图像大小
CropImage根据缩放比例长宽比例两个参数生成若干候选框再依据这些候选框和标注框的面积交并比(IoU)挑选出符合要求的裁剪结果
ExpandImage将原始图片放进一张使用像素均值填充(随后会在减均值操作中减掉)的扩张图中再对此图进行裁剪缩放和翻转
DecodeImage以RGB格式读取图像
Permute对图像的通道进行排列并转为BGR格式
NormalizeImage对图像像素值进行归一化
NormalizeBox对bounding box进行归一化
MixupImage按比例叠加两张图像
```
[注意]:Mixup的操作可参考[论文](https://arxiv.org/pdf/1710.09412.pdf)

`transform/arrange_sample.py`:实现对输入网络数据的排序。  
3. 转换  
`transform/post_map.py`:用于完成批数据的预处理操作,其主要包括:

```  python
随机调整批数据的图像大小
多尺度调整图像大小
padding操作
```
`transform/transformer.py`:用于过滤无用的数据,并返回批数据。
`transform/parallel_map.py`:用于实现加速。  
4. 读取  
`reader.py`:用于组合source和transformer操作,根据`max_iter`返回batch数据。
`data_feed.py`: 用于配置 `reader.py`中所需的默认参数.




### 使用
#### 常规使用
结合yaml文件中的配置信息,完成本模块的功能。yaml文件的使用可以参见配置文件部分。

 - 读取用于训练的数据

``` python
ccfg = load_cfg('./config.yml')
coco = Reader(ccfg.DATA, ccfg.TRANSFORM, maxiter=-1)
```
#### 如何使用自定义数据集?

- 选择1:将数据集转换为VOC格式或者COCO格式。
```python
 # 在./tools/中提供了labelme2coco.py用于将labelme标注的数据集转换为COCO数据集
 python ./tools/labelme2coco.py --json_input_dir ./labelme_annos/
                                --image_input_dir ./labelme_imgs/
                                --output_dir ./cocome/
                                --train_proportion 0.8
                                --val_proportion 0.2
                                --test_proportion 0.0
 # --json_input_dir:使用labelme标注的json文件所在文件夹
 # --image_input_dir:图像文件所在文件夹
 # --output_dir:转换后的COCO格式数据集存放位置
 # --train_proportion:标注数据中用于train的比例
 # --val_proportion:标注数据中用于validation的比例
 # --test_proportion: 标注数据中用于infer的比例
```
- 选择2:

1. 仿照`./source/coco_loader.py``./source/voc_loader.py`,添加`./source/XX_loader.py`并实现`load`函数。  
2.`./source/loader.py``load`函数中添加使用`./source/XX_loader.py`的入口。  
3. 修改`./source/__init__.py`


```python
if data_cf['type'] in ['VOCSource', 'COCOSource', 'RoiDbSource']:
    source_type = 'RoiDbSource'
# 将上述代码替换为如下代码:
if data_cf['type'] in ['VOCSource', 'COCOSource', 'RoiDbSource', 'XXSource']:
    source_type = 'RoiDbSource'
```

4. 在配置文件中修改`dataset`下的`type``XXSource`

#### 如何增加数据预处理?
- 若增加单张图像的增强预处理,可在`transform/operators.py`中参考每个类的代码,新建一个类来实现新的数据增强;同时在配置文件中增加该预处理。
- 若增加单个batch的图像预处理,可在`transform/post_map.py`中参考`build_post_map`中每个函数的代码,新建一个内部函数来实现新的批数据预处理;同时在配置文件中增加该预处理。