按照官网所说,构建自己的数据集有两种方法,自己的数据时COCO数据集的格式或者自己定义个数据集的格式。
这种方式要求数据按照COCO数据集的格式组织,COCO数据集的详细解释参考另一篇博客,主要是annotations中的json文件的内容需要注意。
接下来我们看一下mmdetection是如何调用数据集的,首先看一下训练的config文件中对数据集的定义部分:其中定义了dataset_type时COCODataset的类型,然后定义了COCO数据集的位置,train_pipeline定义了读取图片过程中的操作(包括读取,归一化,增广),data定义了train、val、test的具体位置。
# ./configs/faster_rcnn_r50_fpn_1x.py
# dataset settings
# dataset settings
dataset_type = 'CocoDataset'
data_root = './data/coco/'
img_norm_cfg = dict(
mean=[123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
train_pipeline = [
dict(type='LoadImageFromFile'),
dict(type='LoadAnnotations', with_bbox=True),
dict(type='Resize', img_scale=(1333, 800), keep_ratio=True),
dict(type='RandomFlip', flip_ratio=0.5),
dict(type='Normalize', **img_norm_cfg),
dict(type='Pad', size_divisor=32),
dict(type='DefaultFormatBundle'),
dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']),
]
test_pipeline = [
dict(type='LoadImageFromFile'),
dict(
type='MultiScaleFlipAug',
img_scale=(1333, 800),
flip=False,
transforms=[
dict(type='Resize', keep_ratio=True),
dict(type='RandomFlip'),
dict(type='Normalize', **img_norm_cfg),
dict(type='Pad', size_divisor=32),
dict(type='ImageToTensor', keys=['img']),
dict(type='Collect', keys=['img']),
])
]
data = dict(
imgs_per_gpu=2,
workers_per_gpu=2,
train=dict(
type=dataset_type,
ann_file=data_root + 'annotations/instances_train2017.json',
img_prefix=data_root + 'train2017/',
pipeline=train_pipeline),
val=dict(
type=dataset_type,
ann_file=data_root + 'annotations/instances_val2017.json',
img_prefix=data_root + 'val2017/',
pipeline=test_pipeline),
test=dict(
type=dataset_type,
ann_file=data_root + 'annotations/instances_val2017.json',
img_prefix=data_root + 'val2017/',
pipeline=test_pipeline))
然后看一下COCODataset的定义:对外可调用的函数只有load_annotations和get_ann_info两个
# ./mmdnet/datasets/coco.py
class CocoDataset(CustomDataset):
def load_annotations(self, ann_file): # 用于初始化CocoDataset的,主要初始化算imgs的位置,imgs和annotations的关联关系等
...
def get_ann_info(self, idx): # 用于在train/val/test中调取annotations
...
然后看一下在训练中时如何调用的,COCODatset继承CustomDatset,在train过程中调用的时CustomDataset的函数:
# ./mmdnet/datasets/custom.py
class CustomDataset(Dataset):
def __init__(...):
...
# load annotations (and proposals)
self.img_infos = self.load_annotations(self.ann_file)
...
# processing pipeline
self.pipeline = Compose(pipeline)
def __getitem__(self, idx):
if self.test_mode:
return self.prepare_test_img(idx)
while True:
data = self.prepare_train_img(idx)
if data is None:
idx = self._rand_another(idx)
continue
return data
def prepare_train_img(self, idx):
img_info = self.img_infos[idx]
ann_info = self.get_ann_info(idx)
results = dict(img_info=img_info, ann_info=ann_info)
if self.proposals is not None:
results['proposals'] = self.proposals[idx]
self.pre_pipeline(results)
return self.pipeline(results)
可以从上面代码中看出:
在GETTING_START.md中出现
“You can write a new Dataset class inherited from CustomDataset, and overwrite two methods load_annotations(self, ann_file) and get_ann_info(self, idx), like CocoDataset and VOCDataset.”
根据上述代码,可以看到CustomDataset中使用load_annotations初始化dataset,使用get_ann_info加载target,所以继承CustomDataset需要定义这两个函数,就可以完成自己Dataset的定义。
本次实践采用第一种方法,定义一个自己的COCODataset。在网上的另一篇博客【干货】mmdetection使用coco格式的CrowdHuman数据集进行训练及测试(附调参过程)是直接修改了COCODataset,以至于出现很多错误,这种方法并不是官方推荐的。需要修改的文件如下:
1、在./mmdet/datasets/目录下新建一个.py用于定义自己的Dataset,如myDataset.py,按照官方教程定义即可
from .coco import CocoDataset
from .registry import DATASETS
@DATASETS.register_module
class MyDataset(CocoDataset): # 继承CocoDataset,使用CocoDataset的初始化和加载函数,这里只需要自己定义本数据集中包含的类别
CLASSES = ("pos",) # 本数据集只包含1类,叫做pos
2、在./mmdet/datasets/__init__.py中加入自己定义的数据集
from .builder import build_dataset
from .cityscapes import CityscapesDataset
from .coco import CocoDataset
from .custom import CustomDataset
from .dataset_wrappers import ConcatDataset, RepeatDataset
from .loader import DistributedGroupSampler, GroupSampler, build_dataloader
from .registry import DATASETS
from .voc import VOCDataset
from .wider_face import WIDERFaceDataset
from .xml_style import XMLDataset
from .myDataset import MyDataset # 添加
__all__ = [
'CustomDataset', 'XMLDataset', 'CocoDataset', 'VOCDataset',
'CityscapesDataset', 'GroupSampler', 'DistributedGroupSampler',
'build_dataloader', 'ConcatDataset', 'RepeatDataset', 'WIDERFaceDataset',
'DATASETS', 'build_dataset', 'MyDataset' # 添加
]
3、修改config文件中的dataset有关项
# dataset settings
dataset_type = 'myDataset' # 添加
至此,构建自己的数据集全部完成,并且能在训练中进行调用!!!
另外在转数据集的过程中,尤其要关注annotations中文件的生成,其中踩坑过程详见【mmdetection采坑记录】(一)将自己的数据转成COCO数据集的格式