天天看點

【mmdetection實踐】(一)建構自己的資料集理論知識實踐

文章目錄

  • 理論知識
    • 按照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資料集的格式

繼續閱讀