
๐โโ๏ธ์ค๋์ Object Detection, Segmentation, Keypoint Detection ๋ฑ์ ์ํ ๋ฐ์ดํฐ์
์ธ COCO Dataset ์ ์ด๋ป๊ฒ ์ฌ์ฉํด์ผ ํ๋์ง Pytorch๋ฅผ ์ด์ฉํด์ ๊ณต๋ถํ ๋ด์ฉ์ ์ ๋ฆฌํด๋ณด๊ณ ์ ํฉ๋๋ค.
https://cocodataset.org/#home ๐ ์ด ์ฌ์ดํธ์์ ๋ฐ์ดํฐ์
๋ค์ด๋ก๋๊ฐ ๊ฐ๋ฅํฉ๋๋ค.

์ ๋ 2017 Train images์ 2017 Train/Val annotations๋ฅผ ๋ค์ด๋ฐ์์ ์งํํด๋ณด๊ฒ ์ต๋๋ค.
.png)
๋ค์ด ๋ฐ์ zip ํ์ผ๋ค์ ํ์ด๋ณด๋ฉด, train2014 val2014 ํด๋์๋ jpg์ฌ์ง๋ค์ด ๋ค์ด์์๊ฒ์ด๊ณ , annotation ํด๋์๋ jsonํ์ผ๋ค์ด ์๋ ๊ฒ์ ํ์ธํ์ค ์ ์์ต๋๋ค.
Annotation์๋ ์ฉ๋ ๋ณ๋ก captions instances person_keypoints ํ์ผ์ด ์๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
๐ ์ ๋ instances ์ ๋ณด๋ง ํ์ํ๋ฏ๋ก, ์ด ์ ๋ณด๋ง ์ด์ฉ ํ ์์ ์ ๋๋ค.
Data๋ค์ ์ด์ง ๋ด๋ณด๊ฒ ์ต๋๋ค. object detection์ ํ๊ธฐ ์ํด์๋ image์ annotation์ด ํ์ํ์ฃ ! image๋ ์ฌ๋ฌ ์ข ๋ฅ์ ์ฌ์ง๋ค์ด ์๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
instances_val2017.json ํ์ผ์ ํ๋ฒ ์ด์ด๋ณด๊ฒ ์ต๋๋ค. ๐ ๋ฉ๋ชจ์ฅ์ผ๋ก ์ด๋ฉด ๊น์ง๋๋๋งํผ ์์๋ณด๊ธฐ ํ๋ ๋ด์ฉ๋ค์ด ์์ฑ๋์ด ์์ฃ ! json beautifier ๋ฅผ ์ด์ฉํด์ ๋ณด์๋ฉด ํ์ธต ๋ ๊น๋ํ๊ฒ json ํ์ผ์ ์ฝ์ด๋ณผ ์ ์์ต๋๋ค.
์ด์์ฒด์ ์ ๋ง๋ ํ์ผ์ ๋ค์ด๋ฐ์ ์ค์นํด์ ์ฌ์ฉํด๋ณด์ธ์! ๐ https://stedolan.github.io/jq/
.png)
jsonํ์ผ์ด ์๋ ๊ฒฝ๋ก๋ก ๊ฐ์ jq . instances_val2017.json > instances_val2017_jq.json
๋ช ๋ น์ด๋ฅผ ์ ๋ ฅํ์๋ฉด ๊น๋ํด์ง json ํ์ผ์ด ์์ฑ๋ฉ๋๋ค!
"info": {
"description": "COCO 2017 Dataset",
"url": "http://cocodataset.org",
"version": "1.0",
"year": 2017,
"contributor": "COCO Consortium",
"date_created": "2017/09/01"
}
...
"area": 1037.7818999999995,
"iscrowd": 0,
"image_id": 397133,
"bbox": [
0,
262.81,
62.16,
36.77
],
"category_id": 1,
"id": 1218137
}
"segmentation": [
[
292.37,
425.1,
340.6,
373.86,
347.63,
256.31,
198.93,
240.24,
4.02,
311.57,
1,
427,
291.36,
427
]
]
์ด๋ ๊ฒ image์ ๋ํ bbox์ segmentation ์ ๋ณด๊ฐ ๋์์๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
์ด์ data loader๋ฅผ ์ค๋นํด๋ณด๊ฒ ์ต๋๋ค. ์๋์ github๋ฅผ ์ฐธ์กฐํ์ฌ ์์ฑํ์์ต๋๋ค ๐
https://github.com/csm-kr/yolo_v2_vgg16_pytorch/blob/master/dataset/coco_dataset.py
๋ค์ด ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ค์๊ณผ ๊ฐ์ ๊ฒฝ๋ก๋ก ์ ์ฅํด๋ก๋๋ค!
root -- images -- train2017
| |- val2017
| |- test2017
|
-- anotations -- instances_train2017.json
|- instances_val2017.json * minival
๋จผ์ , ํ์ด์ฐธ์ ์ด์ฉํด Project๋ฅผ ๋ง๋ค์ด ์ค๋๋ค.
.png)
data loader๋ฅผ ๋ง๋ค๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ library๋ค์ด import ๋์ด์์ด์ผ ํฉ๋๋ค! ์กฐ๋ง๊ฐ ๊ฐ์ํ๊ฒฝ ๋ง๋๋ ๋ฒ๋ ์ฌ๋ ค๋ณด๊ฒ ์ต๋๋ค!
๐ ํน์, windows์์ pycocotools์ ์ค์นํ์๋ค๊ฐ error๊ฐ ๋ฐ์ํ์๋ ๋ถ๋ค์ Anaconda Prompt ์์ ์๋์ ๊ฐ์ ์ ์ฐจ๋๋ก ์ค์นํด๋ณด์ธ์!
1.ย pipย installย cython
2.ย condaย installย git
3.ย pipย installย "git+https://github.com/philferriere/cocoapi.git#egg=pycocotools&subdirectory=PythonAPI"
import os
import torch
import numpy as np
import matplotlib.pyplot as plt
from torch.utils.data import Dataset, DataLoader
from pycocotools.coco import COCO
from transform import transform_COCO
from PIL import Image
import matplotlib
from matplotlib.patches import Rectangle
์์ ๊ฐ์ ํ์ผ๋ค์ importํด์ฃผ์๊ณ , data loader class๋ฅผ ๋ง๋ค์ด์ค๋๋ค.
๊ฒฝ๋ก ์ค๋ฅ๊ฐ ๋์ง ์๊ฒ init์ argument์ root_dir๋ฅผ ์ ์์ฑํด์ฃผ์ธ์! validation file๋ค๋ก ์ดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค!
class COCO_Dataset(Dataset):
def __init__(self, root_dir='D:\Data\coco', set_name='val2017', split='TRAIN'):
super().__init__()
self.root_dir = root_dir
self.set_name = set_name
self.coco = COCO(os.path.join(self.root_dir, 'annotations', 'instances_' + self.set_name + '.json'))
๊ทธ๋ฆฌ๊ณ , ๋ผ๋ฒจ์ด ์๋ ์ด๋ฏธ์ง๋ค์ ์ ๊ฑฐํ๊ณ ํ์ต ํน์ ํ ์คํธ์ ์ด์ฉํ๋๋ก list์ ๋ด์์ฃผ๋ฉด ๋ฉ๋๋ค!
whole_image_ids = self.coco.getImgIds() # original length of train2017 is 118287
self.image_ids = []
# to remove not annotated image idx
self.no_anno_list = []
for idx in whole_image_ids:
annotations_ids = self.coco.getAnnIds(imgIds=idx, iscrowd=False)
if len(annotations_ids) == 0:
self.no_anno_list.append(idx)
else:
self.image_ids.append(idx)
self.load_classes() # read class information
self.split = split
COCO๋ person, bicycle, car ๋ฑ๋ฑ 80๊ฐ์ classes๊ฐ ์์ต๋๋ค.
์ด์ ํ๋์ ์ด๋ฏธ์ง๋ฅผ ์ด์ด bbox๋ฅผ ํ์ํด๋ณด๋๋ก ํฉ์๋ค! DataLoader์ getitem() function์์ ๋ณดํต ํ๋์ image๋ฅผ ์ด๊ณ , bounding box๋ฅผ ์ฝ์ต๋๋ค. ํ๋ฒ ์ด๋ฏธ์ง์ ๊ทธ ์ด๋ฏธ์ง์ ์๋ bounding box ์ ๋ณด์ segmentation ์ ๋ณด๋ฅผ ์ด์ฉํด๋ด
์๋ค!
def __getitem__(self, idx):
visualize = True
image, (w, h) = self.load_image(idx)
annotation = self.load_annotations(idx)
boxes = torch.FloatTensor(annotation[:, :4])
labels = torch.LongTensor(annotation[:, 4])
if labels.nelement() == 0: # no labeled img exists.
visualize = True
# data augmentation
image, boxes, labels, segmentations = transform_COCO(image, boxes, labels, self.split)
return image, boxes, labels
๐โโ๏ธ ์ด๋ฏธ์ง๋ฅผ ์ฝ์ด๋ด ์๋ค! coco ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ด์ฉํด์ ์ด๋ฏธ์ง ์ ๋ณด๋ฅผ ์ฝ์ด์ค๊ณ , PIL๋ก ์ด ์ ์์ต๋๋ค.
def load_image(self, image_index):
image_info = self.coco.loadImgs(self.image_ids[image_index])[0]
path = os.path.join(self.root_dir, 'images', self.set_name, image_info['file_name'])
image = Image.open(path).convert('RGB')
return image, (image_info['width'], image_info['height'])
๐โโ๏ธ Annotation๋ ์ฝ์ด๋ด ์๋ค!
def load_annotations(self, image_index):
# get ground truth annotations
annotations_ids = self.coco.getAnnIds(imgIds=self.image_ids[image_index], iscrowd=False)
annotations = np.zeros((0, 5))
# some images appear to miss annotations (like image with id 257034)
if len(annotations_ids) == 0:
return annotations
# parse annotations
coco_annotations = self.coco.loadAnns(annotations_ids)
for idx, a in enumerate(coco_annotations):
# some annotations have basically no width / height, skip them
if a['bbox'][2] < 1 or a['bbox'][3] < 1:
continue
annotation = np.zeros((1, 5))
annotation[0, :4] = a['bbox']
annotation[0, 4] = self.coco_label_to_label(a['category_id'])
annotations = np.append(annotations, annotation, axis=0)
# transform from [x, y, w, h] to [x1, y1, x2, y2]
annotations[:, 2] = annotations[:, 0] + annotations[:, 2]
annotations[:, 3] = annotations[:, 1] + annotations[:, 3]
return annotations
๊ทธ๋ ๋ค๋ฉด, ํ์ต์ ์ด์ฉํ๊ธฐ ์ํด์๋ ์ด๋ป๊ฒ ํด์ผ ํ ์ง ์์๋ณด๊ฒ ์ต๋๋ค. trainํจ์์์ train loader๋ฅผ ๋ถ๋ฌ์์ train data๋ค์ ์ด์ฉํด์ผ ํ๊ฒ ์ฃ ? ์๋์ ์ฝ๋๊ฐ ๋ฐ๋ก Loader๋ฅผ ๋ถ๋ฌ์ค๋ ๋ถ๋ถ์ ๋๋ค.
train_set = COCO_Dataset()
train_loader = DataLoader(train_set,
batch_size=1,
collate_fn=train_set.collate_fn,
shuffle=False,
num_workers=0,
pin_memory=True)
์ด๋ ๊ฒ data๋ค์ ๋ถ๋ฌ์ค๋ฉด train_loader๋ผ๋ ๊ณณ์ ์ ์ฅ์ด ๋๊ณ ,
for i, (images, boxes, labels) in enumerate(train_loader):
images = images.cuda()
boxes = [b.cuda() for b in boxes]
labels = [l.cuda() for l in labels]
์ค์ ๋ก for๋ฌธ์ ์ด์ฉํด์ data๋ฅผ ์ฝ์ด์ค๋ฉด get_item function์์ ์ํํ๋ ๊ฒ๋ค์ด ๋ถ๋ฌ์์ง๋๋ค. ๐ ์ฌ๊ธฐ๊น์ง๊ฐ coco dataset์ ํ์ต์ ์ด์ฉํ๊ธฐ ์ํด ์ด๋ป๊ฒ ์ฝ์ด์ผ ํ๋๊ฐ๋ฅผ ๋ค๋ฃฌ ๋ด์ฉ์
๋๋ค.
https://github.com/csm-kr ๐ ์ด github์ detection ์ฝ๋๋ค์ด ๋ง์ด ์์ผ๋ ์ฐธ๊ณ ํด๋ณด์ธ์~!
์คํ์ง๋ฐฅ ์๋ดค์ต๋๋ค~