文章目錄
- 理論知識
-
- 按照COCO資料集的格式
- 定義自己的Dataset
- 實踐
理論知識
按照官網所說,建構自己的資料集有兩種方法,自己的資料時COCO資料集的格式或者自己定義個資料集的格式。
按照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)
可以從上面代碼中看出:
- 在Dataset的init中确實時使用load_annotations進行初始化
- __getitem__函數是重載Dataset的,就是在train過程中加載data和target的,其中用了prepare_train_img
- prepare_train_img使用了get_ann_info函數來加載target
定義自己的Dataset
在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資料集的格式