[Coding] COCO Dataset ์ฝ๊ธฐ

Dokyeong Kwonยท2020๋…„ 10์›” 4์ผ

Pytorch

๋ชฉ๋ก ๋ณด๊ธฐ
1/2
post-thumbnail

๐Ÿ™‹โ€โ™€๏ธ์˜ค๋Š˜์€ Object Detection, Segmentation, Keypoint Detection ๋“ฑ์„ ์œ„ํ•œ ๋ฐ์ดํ„ฐ์…‹์ธ COCO Dataset ์„ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”์ง€ Pytorch๋ฅผ ์ด์šฉํ•ด์„œ ๊ณต๋ถ€ํ•œ ๋‚ด์šฉ์„ ์ •๋ฆฌํ•ด๋ณด๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.

1. Download COCO

https://cocodataset.org/#home ๐Ÿ‘ˆ ์ด ์‚ฌ์ดํŠธ์—์„œ ๋ฐ์ดํ„ฐ์…‹ ๋‹ค์šด๋กœ๋“œ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์ €๋Š” 2017 Train images์™€ 2017 Train/Val annotations๋ฅผ ๋‹ค์šด๋ฐ›์•„์„œ ์ง„ํ–‰ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋‹ค์šด ๋ฐ›์€ zip ํŒŒ์ผ๋“ค์„ ํ’€์–ด๋ณด๋ฉด, train2014 val2014 ํด๋”์—๋Š” jpg์‚ฌ์ง„๋“ค์ด ๋“ค์–ด์žˆ์„๊ฒƒ์ด๊ณ , annotation ํด๋”์—๋Š” jsonํŒŒ์ผ๋“ค์ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Annotation์—๋Š” ์šฉ๋„ ๋ณ„๋กœ captions instances person_keypoints ํŒŒ์ผ์ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • captions : ๊ทธ๋ฆผ์— ๋Œ€ํ•œ ์„ค๋ช… (text)
  • instances : ๊ทธ๋ฆผ์— ์žˆ๋Š” ์‚ฌ๋žŒ/์‚ฌ๋ฌผ category์™€ ์˜์—ญ mask
  • person_keypoints : ์‚ฌ๋žŒ์˜ ์ž์„ธ ๋ฐ์ดํ„ฐ

๐Ÿ‘‰ ์ €๋Š” instances ์ •๋ณด๋งŒ ํ•„์š”ํ•˜๋ฏ€๋กœ, ์ด ์ •๋ณด๋งŒ ์ด์šฉ ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

Data๋“ค์„ ์‚ด์ง ๋ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. object detection์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” image์™€ annotation์ด ํ•„์š”ํ•˜์ฃ ! image๋Š” ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ ์‚ฌ์ง„๋“ค์ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

instances_val2017.json ํŒŒ์ผ์„ ํ•œ๋ฒˆ ์—ด์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๐Ÿ‘€ ๋ฉ”๋ชจ์žฅ์œผ๋กœ ์—ด๋ฉด ๊นœ์ง๋†€๋ž„๋งŒํผ ์•Œ์•„๋ณด๊ธฐ ํž˜๋“  ๋‚ด์šฉ๋“ค์ด ์ž‘์„ฑ๋˜์–ด ์žˆ์ฃ ! json beautifier ๋ฅผ ์ด์šฉํ•ด์„œ ๋ณด์‹œ๋ฉด ํ•œ์ธต ๋” ๊น”๋”ํ•˜๊ฒŒ json ํŒŒ์ผ์„ ์ฝ์–ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์šด์˜์ฒด์ œ์— ๋งž๋Š” ํŒŒ์ผ์„ ๋‹ค์šด๋ฐ›์•„ ์„ค์น˜ํ•ด์„œ ์‚ฌ์šฉํ•ด๋ณด์„ธ์š”! ๐Ÿ‘‰ https://stedolan.github.io/jq/

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

2. Data ์ค€๋น„

๋‹ค์šด ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ๋กœ๋กœ ์ €์žฅํ•ด๋‘ก๋‹ˆ๋‹ค!

root -- images      -- train2017
     |              |- val2017
     |              |- test2017
     | 
     -- anotations  -- instances_train2017.json
                    |- instances_val2017.json  * minival            

3. Project ์ƒ์„ฑ

๋จผ์ €, ํŒŒ์ด์ฐธ์„ ์ด์šฉํ•ด Project๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

data loader๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ library๋“ค์ด import ๋˜์–ด์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค! ์กฐ๋งŒ๊ฐ„ ๊ฐ€์ƒํ™˜๊ฒฝ ๋งŒ๋“œ๋Š” ๋ฒ•๋„ ์˜ฌ๋ ค๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!

  • Pytorch
  • PIL
  • numpy
  • pycocotools
  • matplotlib

๐Ÿ‘‰ ํ˜น์‹œ, 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"

4. Data Loader

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 ์ฝ”๋“œ๋“ค์ด ๋งŽ์ด ์žˆ์œผ๋‹ˆ ์ฐธ๊ณ ํ•ด๋ณด์„ธ์š”~!

profile
Go with the flow

3๊ฐœ์˜ ๋Œ“๊ธ€

comment-user-thumbnail
2020๋…„ 10์›” 7์ผ

์ŠคํŽ€์ง€๋ฐฅ ์ž˜๋ดค์Šต๋‹ˆ๋‹ค~

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ
comment-user-thumbnail
2021๋…„ 2์›” 26์ผ

2017 ํ…Œ์ŠคํŠธ์…‹์€ ๋ผ๋ฒจ๋ง ํŒŒ์ผ์ด ์—†๋Š”๊ฑฐ์ฃ ~??

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ
comment-user-thumbnail
2022๋…„ 3์›” 25์ผ

์•ˆ๋…•ํ•˜์„ธ์š”. ์—…๋กœ๋“œํ•˜์‹ ์ง€ ์ข€ ์‹œ๊ฐ„์ด ์ง€๋‚˜๊ธด ํ–ˆ์ง€๋งŒ ๊ถ๊ธˆํ•œ ์‚ฌํ•ญ์ด ์žˆ์–ด์„œ ์งˆ๋ฌธ ๋‚จ๊น๋‹ˆ๋‹ค. from transform import transform_COCO ๋Š” public package๊ฐ€ ์•„๋‹Œ ๊ฒƒ ๊ฐ™์€๋ฐ ํ˜น์‹œ ์–ด๋””์„œ ์ฐพ์•„๋ณผ ์ˆ˜ ์žˆ์„๊นŒ์š”?

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ