본문 바로가기

컴린이 탈출기/Vision

공부하며 정리해보는 Detectron2 튜토리얼 🌠 (1) - Dataset, Dataloader, Data Augmentation

반응형

https://detectron2.readthedocs.io/en/latest/

 

Welcome to detectron2’s documentation! — detectron2 0.5 documentation

© Copyright 2019-2020, detectron2 contributors Revision 64e84c5b.

detectron2.readthedocs.io

Detectron2 공식 문서를 공부하며 정리한 글입니다!
오역한 부분이나 자연스러운 표현을 위해 의역한 부분이 있을 수 있습니다.
잘못된 내용에 대한 댓글로 부탁드립니다. :)



Detectron2이란?

Detectron2는 Facebook AI Research(FAIR)에서 개발한 Pytorch 기반의 Object Detection, Segmentation 라이브러리이다. MMDetection과 마찬가지로 모듈식으로 작동한다.

로봇 귀여워...


Run a pre-trained detectron2 model

본격적으로 공식문서를 살펴보기에 앞서 기본적인 사용법을 알 수 있는 Colab 노트북을 살펴보았다.

1) COCO 형식의 이미지 준비

2) Config와 DefaultPredictor 생성, Inference 하기

cfg = get_cfg()

# add project-specific config
cfg.merge_from_file(model_zoo.get_config_file("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml"))
cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5

# find a model
cfg.MODEL.WEIGHTS = model.zoo.get_checkpoint_url("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml")
predictor = DefaultPredictor(cfg)

outputs = predictor(img)

3) 결과 시각화하기

print(outputs["instances"].pred_classes)
print(outputs["instances"].pred_boxes)

v = Visualizer(im[:, :, ::-1], MetadataCatalog.get(cfg.DATASETS.TRAIN[0]), scale=1.2)
out = v.draw_instance_predictions(outputs["instances"].to("cpu"))
cv2_imshow(out.get_image()[:, :, ::-1])

 

Use Builtin Datasets

데이터셋들은 DETECTRON2_DATASETS 환경 변수에 명시된 디렉토리()에 존재하는 것으로 가정한다. Detectron2는 기본적으로 COCO, LVIS, Cityscapes, VOC20 데이터셋(=builtin datasets)을 지원한다.

+ Custom dataset의 경우 DatasetCatalog, MetadataCatalog라는 클래스를 이용해 사용하는 것 같다. 이건 뒤에서 더 알아보도록 하자~

 

Extend Detectron2's Defaults

Detectron2는 두 종류의 인터페이스를 제공한다.

1. yaml 파일로부터 생성된 config를 이용하는 함수와 클래스

model = build_model(cfg)

2. 명시적으로 아규먼트가 잘 정의된 함수와 클래스

model = GeneralizedRCNN(
  cfg,
  roi_heads=StandardROIHeads(cfg, batch_size_per_image=666),
  pixel_std=[57.0, 57.0, 57.0])

3. @configurable 데코레이터와 함께 실행되는 몇몇 함수와 클래스 

 

Use Custom Datasets

이번 단계에선 위에서 언급한 데이터셋 API들 (DatasetCatalog, MetadataCatalog)가 어떻게 작동하고, 커스텀 데이터셋을 추가하고자 할 때 이들을 어떻게 이용할 수 있는지 알아본다.

Detectron2의 dataloader를 재사용하면서 새로운 커스텀 데이터셋을 사용하고자 할 때는 다음과 같이 해야 한다.

1. 데이터셋 등록 (Register)
2. (옵션) 데이터셋을 위한 metadata 등록

Register a Dataset

Detectron2가 데이터셋을 어떻게 획득하는지 알게 하기 위해, 유저는 dataset의 아이템을 리턴하는 함수를 만들고 이 함수를 Detectron2에게 알려야 한다.

def my_dataset_function():
  ...
  return list[dict] in the following format

from detectron2.data import DatasetCatalog
DatasetCatalog.register("my_dataset", my_dataset_function)
# later, to access the data:
data: List[Dict] = DatasetCatalog.get("my_dataset")

이때, my_dataset_function은 호출될 때마다 같은 순서의 같은 데이터를 list [dict] 형태로 리턴해야 한다. 그리고 dict는 아래의 형식을 따라야 한다.

1. Detectron2의 standard dataset dict를 따를 것.

2. 임의의 포맷을 따르는 dict. 

결국 Standard dict, 임의의 dict 모두 상관없지만..! Standard dict를 따를 경우에는 Detectron2의 많은 builtin 피쳐들을 이용할 수 있다고 한다. 

 

# Standard Dataset Dicts

Dict는 한 이미지에 대한 정보를 담고 있고, Object detection의 다음과 같은 필드를 필요로 한다. (태스크마다 필요로 하는 필드가 다르다.)

file_name / height / width / image_id / annotations

annotations은 다음과 같은 key를 갖는다.

bbox list[float], required bounding box 좌표값 4개(숫자)
bbox_mode int, required bbox 포맷
category_id int, required [0, num_categories-1] 사이의 숫자
segmentation list[list[float]] or dict list[list[float]]-폴리곤을, dict - RLE 포맷
keypoints list[float] [x1, y1, v1, .... , xn, yn, vn]
이때 v은 키포인트가 보이는지 여부 정보를 담는다
iscrowd 0(default) or 1 COCO 데이터셋의 crowd region과 같은 의미의 라벨이다

 

Metadata for Datasets

각각의 데이터셋은 MetadataCatalog.get(dataset_name).some_metadata로 접근 가능한 metadata와 관련되어 있다. Metadata는 key-value 형식으로, 전체 데이터셋이 공유하는 정보를 담고 있다. 그리고 이것은 데이터셋에 어떤 데이터가 들어있을지 해석하기 위해 쓰인다. (ex. class 명, class 색, 파일 루트 디렉토리) 이러한 정보는 평가, 로깅, 시각화, augmentation 등에 유용하게 쓰인다.DatasetCatalog.register를 통해 데이터셋을 등록했다면, MetadataCatalog.get(dataset_name).some_key = some_value를 통해 메타 데이터를 등록할 수 있다.

from detectron2.data import MetadataCatalog
MetadataCatalog.get("my_dataset").thing_classes = ["person", "dog"]

 

Register a COCO Format Dataset

이미 COCO 포맷으로 데이터가 준비되어 있다면, 데이터셋과 메타 데이터를 쉽게 등록할 수 있다.

from detectron2.data.datasets import register_coco_instances
register_coco_instances("my_dataset", {}, "json_annotation.json", "path/to/image/dir")

데이터셋이 COCO 포맷이지만 추가적인 처리 혹은 annotation의 커스터마이징이 필요하다면 load_coco_json 함수를 쓰는 것이 더 좋다.

 

Update the Config for New Datasets

데이터셋을 등록한 후에는 데이터셋 이름으로 데이터셋을 이용할 수 있다. (위의 예시 같은 경우 my_dataset이 데이터셋의 이름이다.) 새로운 데이터셋에 대해서는 다음과 같이 config를 변경할 수 있다.

예시

 

Dataloader

Dataloader는 모델에게 데이터를 제공하기 위한 요소이다. Dataloader는 보통 데이터셋으로부터 날 것의 데이터를 가져와 모델이 필요로 하는 형식으로 처리하는 역할을 한다.

How the Existing Dataloader Works

Detectron2는 이미 내재된 데이터 로딩 파이프라인을 가지고 있다. build_detection_(train, test)_loader는 다음과 같이 동작한다.1. 등록된 데이터셋의 이름을 가지고 list [dict] 형태의 데이터셋 아이템을 경량 형식으로 로드한다. 이 데이터셋의 아이템들은 곧바로 모델에서 쓰일 수 없다. (ex. 메모리에 이미지가 로드되지 않음, random augmentation이 적용되지 않음) 2. list 내 각각의 dict는 "mapper" 함수에 의해 매핑된다. 유저들은 이 매핑 함수를 build_detection_(train, test)_loader의 mapper 아규먼트를 통해 커스터마이징 할 수 있다. 디폴트는 Datasetmapper이다. 이때 mapper의 역할은 경량 형식의 데이터셋 아이템을 모델이 사용할 수 있는 포맷으로 바꾸는 것이다. (이미지를 불러와서, random augmentation을 적용하고 torch Tensor로 변환하는 모든 과정 포함) 만약 데이터에 custom transformation을 가하고 싶다면 custom mapper 사용하면 된다.

 

Write a Custom Dataloader

custom data loading을 위해서는 build_detection_(train, test)_loader(mapper =) 코드를 통해 다른 mapper를 사용해야 한다. 예를 들어 만약 학습 시 모든 이미지를 고정된 사이즈로 리사이즈하고 싶다면 다음과 같은 코드를 사용하면 된다.

import detectron2.data.transforms as T
from detectron2.data import DatasetMapper   # the default mapper
dataloader = build_detection_train_loader(cfg,
   mapper=DatasetMapper(cfg, is_train=True, augmentations=[
      T.Resize((800, 800))
   ]))
# use this dataloader instead of the default

 

Use a Custom Dataloader

DefaultTrainer를 사용한다면 build_detection_(train, test)_loader 메서드를 오버라이드, 우리만의 dataloader를 만들 수 있다. 

 

Data Augmentation

이 튜토리얼은 새로운 data loader를 작성할 때 어떻게 augmentation을 이용할 수 있을지에 포커싱 되어 있다. 만약 Detectron2의 디폴트 data loader를 사용한다면, 그것은 이미 사용자가 지정한 custom augmentation으로의 확장을 지원한다. (바로 위에서 서술한 내용!)

Basic Usage

from detectron2.data import transforms as T
# Define a sequence of augmentations:
augs = T.AugmentationList([
    T.RandomBrightness(0.9, 1.1),
    T.RandomFlip(prob=0.5),
    T.RandomCrop("absolute", (640, 640))
])  # type: T.Augmentation

# Define the augmentation input ("image" required, others optional):
input = T.AugInput(image, boxes=boxes, sem_seg=sem_seg)
# Apply the augmentation:
transform = augs(input)  # type: T.Transform
image_transformed = input.image  # new image
sem_seg_transformed = input.sem_seg  # new semantic segmentation

# For any extra data that needs to be augmented together, use transform, e.g.:
image2_transformed = transform.apply_image(image2)
polygons_transformed = transform.apply_polygons(polygons)

여기에 쓰인 3가지 기본 개념은 다음과 같다.

# T.AugInput

T.Augmentation에서 필요한에서 필요한 input을 저장한다. 

 

# T.Augmentation

input을 어떻게 수정할지를 정하는 정책(policy)을 정의한다.

 

# T.Transform

데이터를 변형하는 실제 오퍼레이션을 수행한다. apply_image, apply_coords와 같이 데이터 타입에 따라 어떻게 transform 할지 정의한다.

 

이어지는 글

공부하며 정리해보는 Detectron2 튜토리얼 🌠 (2) - Model, Training, Evaluation, Yacs configs, Lazy configs

 

 

 

반응형