|
# 2: 在自定义数据集上进行训练 |
|
|
|
通过本文档,你将会知道如何使用自定义数据集对预先定义好的模型进行推理,测试以及训练。我们使用 [balloon dataset](https://github.com/matterport/Mask_RCNN/tree/master/samples/balloon) 作为例子来描述整个过程。 |
|
|
|
基本步骤如下: |
|
|
|
1. 准备自定义数据集 |
|
2. 准备配置文件 |
|
3. 在自定义数据集上进行训练,测试和推理。 |
|
|
|
## 准备自定义数据集 |
|
|
|
MMDetection 一共支持三种形式应用新数据集: |
|
|
|
1. 将数据集重新组织为 COCO 格式。 |
|
2. 将数据集重新组织为一个中间格式。 |
|
3. 实现一个新的数据集。 |
|
|
|
我们通常建议使用前面两种方法,因为它们通常来说比第三种方法要简单。 |
|
|
|
在本文档中,我们展示一个例子来说明如何将数据转化为 COCO 格式。 |
|
|
|
**注意**:MMDetection 现只支持对 COCO 格式的数据集进行 mask AP 的评测。 |
|
|
|
所以用户如果要进行实例分割,只能将数据转成 COCO 格式。 |
|
|
|
### COCO标注格式 |
|
|
|
用于实例分割的 COCO 数据集格式如下所示,其中的键(key)都是必要的,参考[这里](https://cocodataset.org/#format-data)来获取更多细节。 |
|
|
|
```json |
|
{ |
|
"images": [image], |
|
"annotations": [annotation], |
|
"categories": [category] |
|
} |
|
|
|
|
|
image = { |
|
"id": int, |
|
"width": int, |
|
"height": int, |
|
"file_name": str, |
|
} |
|
|
|
annotation = { |
|
"id": int, |
|
"image_id": int, |
|
"category_id": int, |
|
"segmentation": RLE or [polygon], |
|
"area": float, |
|
"bbox": [x,y,width,height], |
|
"iscrowd": 0 or 1, |
|
} |
|
|
|
categories = [{ |
|
"id": int, |
|
"name": str, |
|
"supercategory": str, |
|
}] |
|
``` |
|
|
|
现在假设我们使用 balloon dataset。 |
|
|
|
下载了数据集之后,我们需要实现一个函数将标注格式转化为 COCO 格式。然后我们就可以使用已经实现的 `COCODataset` 类来加载数据并进行训练以及评测。 |
|
|
|
如果你浏览过新数据集,你会发现格式如下: |
|
|
|
```json |
|
{'base64_img_data': '', |
|
'file_attributes': {}, |
|
'filename': '34020010494_e5cb88e1c4_k.jpg', |
|
'fileref': '', |
|
'regions': {'0': {'region_attributes': {}, |
|
'shape_attributes': {'all_points_x': [1020, |
|
1000, |
|
994, |
|
1003, |
|
1023, |
|
1050, |
|
1089, |
|
1134, |
|
1190, |
|
1265, |
|
1321, |
|
1361, |
|
1403, |
|
1428, |
|
1442, |
|
1445, |
|
1441, |
|
1427, |
|
1400, |
|
1361, |
|
1316, |
|
1269, |
|
1228, |
|
1198, |
|
1207, |
|
1210, |
|
1190, |
|
1177, |
|
1172, |
|
1174, |
|
1170, |
|
1153, |
|
1127, |
|
1104, |
|
1061, |
|
1032, |
|
1020], |
|
'all_points_y': [963, |
|
899, |
|
841, |
|
787, |
|
738, |
|
700, |
|
663, |
|
638, |
|
621, |
|
619, |
|
643, |
|
672, |
|
720, |
|
765, |
|
800, |
|
860, |
|
896, |
|
942, |
|
990, |
|
1035, |
|
1079, |
|
1112, |
|
1129, |
|
1134, |
|
1144, |
|
1153, |
|
1166, |
|
1166, |
|
1150, |
|
1136, |
|
1129, |
|
1122, |
|
1112, |
|
1084, |
|
1037, |
|
989, |
|
963], |
|
'name': 'polygon'}}}, |
|
'size': 1115004} |
|
``` |
|
|
|
标注文件时是 JSON 格式的,其中所有键(key)组成了一张图片的所有标注。 |
|
|
|
其中将 balloon dataset 转化为 COCO 格式的代码如下所示。 |
|
|
|
```python |
|
|
|
import os.path as osp |
|
import mmcv |
|
|
|
def convert_balloon_to_coco(ann_file, out_file, image_prefix): |
|
data_infos = mmcv.load(ann_file) |
|
|
|
annotations = [] |
|
images = [] |
|
obj_count = 0 |
|
for idx, v in enumerate(mmcv.track_iter_progress(data_infos.values())): |
|
filename = v['filename'] |
|
img_path = osp.join(image_prefix, filename) |
|
height, width = mmcv.imread(img_path).shape[:2] |
|
|
|
images.append(dict( |
|
id=idx, |
|
file_name=filename, |
|
height=height, |
|
width=width)) |
|
|
|
bboxes = [] |
|
labels = [] |
|
masks = [] |
|
for _, obj in v['regions'].items(): |
|
assert not obj['region_attributes'] |
|
obj = obj['shape_attributes'] |
|
px = obj['all_points_x'] |
|
py = obj['all_points_y'] |
|
poly = [(x + 0.5, y + 0.5) for x, y in zip(px, py)] |
|
poly = [p for x in poly for p in x] |
|
|
|
x_min, y_min, x_max, y_max = ( |
|
min(px), min(py), max(px), max(py)) |
|
|
|
|
|
data_anno = dict( |
|
image_id=idx, |
|
id=obj_count, |
|
category_id=0, |
|
bbox=[x_min, y_min, x_max - x_min, y_max - y_min], |
|
area=(x_max - x_min) * (y_max - y_min), |
|
segmentation=[poly], |
|
iscrowd=0) |
|
annotations.append(data_anno) |
|
obj_count += 1 |
|
|
|
coco_format_json = dict( |
|
images=images, |
|
annotations=annotations, |
|
categories=[{'id':0, 'name': 'balloon'}]) |
|
mmcv.dump(coco_format_json, out_file) |
|
``` |
|
|
|
使用如上的函数,用户可以成功将标注文件转化为 JSON 格式,之后可以使用 `CocoDataset` 对模型进行训练和评测。 |
|
|
|
## 准备配置文件 |
|
|
|
第二步需要准备一个配置文件来成功加载数据集。假设我们想要用 balloon dataset 来训练配备了 FPN 的 Mask R-CNN ,如下是我们的配置文件。假设配置文件命名为 `mask_rcnn_r50_caffe_fpn_mstrain-poly_1x_balloon.py`,相应保存路径为 `configs/balloon/`,配置文件内容如下所示。 |
|
|
|
```python |
|
# 这个新的配置文件继承自一个原始配置文件,只需要突出必要的修改部分即可 |
|
_base_ = 'mask_rcnn/mask_rcnn_r50_caffe_fpn_mstrain-poly_1x_coco.py' |
|
|
|
# 我们需要对头中的类别数量进行修改来匹配数据集的标注 |
|
model = dict( |
|
roi_head=dict( |
|
bbox_head=dict(num_classes=1), |
|
mask_head=dict(num_classes=1))) |
|
|
|
# 修改数据集相关设置 |
|
dataset_type = 'CocoDataset' |
|
classes = ('balloon',) |
|
data = dict( |
|
train=dict( |
|
img_prefix='balloon/train/', |
|
classes=classes, |
|
ann_file='balloon/train/annotation_coco.json'), |
|
val=dict( |
|
img_prefix='balloon/val/', |
|
classes=classes, |
|
ann_file='balloon/val/annotation_coco.json'), |
|
test=dict( |
|
img_prefix='balloon/val/', |
|
classes=classes, |
|
ann_file='balloon/val/annotation_coco.json')) |
|
|
|
# 我们可以使用预训练的 Mask R-CNN 来获取更好的性能 |
|
load_from = 'checkpoints/mask_rcnn_r50_caffe_fpn_mstrain-poly_3x_coco_bbox_mAP-0.408__segm_mAP-0.37_20200504_163245-42aa3d00.pth' |
|
``` |
|
|
|
## 训练一个新的模型 |
|
|
|
为了使用新的配置方法来对模型进行训练,你只需要运行如下命令。 |
|
|
|
```shell |
|
python tools/train.py configs/balloon/mask_rcnn_r50_caffe_fpn_mstrain-poly_1x_balloon.py |
|
``` |
|
|
|
参考[情况 1](./1_exist_data_model.md)来获取更多详细的使用方法。 |
|
|
|
## 测试以及推理 |
|
|
|
为了测试训练完毕的模型,你只需要运行如下命令。 |
|
|
|
```shell |
|
python tools/test.py configs/balloon/mask_rcnn_r50_caffe_fpn_mstrain-poly_1x_balloon.py work_dirs/mask_rcnn_r50_caffe_fpn_mstrain-poly_1x_balloon.py/latest.pth --eval bbox segm |
|
``` |
|
|
|
参考[情况 1](./1_exist_data_model.md)来获取更多详细的使用方法。 |
|
|