728x90
반응형
!pip install mmcv-full
!git clone https://github.com/open-mmlab/mmdetection.git
!cd mmdetection; python setup.py install

Oxford Pet Dataset 다운로드

image와 annotations을 압축파일로 각각 download 수행.

!wget https://www.robots.ox.ac.uk/~vgg/data/pets/data/images.tar.gz
!wget https://www.robots.ox.ac.uk/~vgg/data/pets/data/annotations.tar.gz

# /content/data 디렉토리를 만들고 해당 디렉토리에 다운로드 받은 압축 파일 풀기.
!mkdir /content/data
!tar -xvf images.tar.gz -C /content/data
!tar -xvf annotations.tar.gz -C /content/data

- 하나의 image에 하나의 annotation

- kaggle kenel은 t100 gpu가 돌아감 1epoch에 13분 // t4로 돌리면 좀더 걸림

- 품종 고르기

디렉토리 안에서 .jpg file만 꺼내야함. 그걸 xmls 폴더의 annotation을 매칭시켜야함.

annotation file에 경로지정이 안되어있음.

image당 object가 하나밖에 없고,

cat, dog 수준으로 나뉨

이미지 디렉토리와 annotation 파일 살펴 보기

!ls -lia ./data/images/Abyss*.jpg
# 4460071 -rwxr-xr-x 1 1001 1001 126923 Jun 18  2012 ./data/images/Abyssinian_100.jpg
# ...
# 4458962 -rwxr-xr-x 1 1001 1001  21004 Jun 18  2012 ./data/images/Abyssinian_9.jpg
!ls -lia ./data/images

# Streaming output truncated to the last 5000 lines.
# 4459898 -rwxr-xr-x 1 1001 1001   27987 Jun 18  2012 Egyptian_Mau_91.jpg
# ...
# 4476065 -rwxr-xr-x 1 1001 1001  126596 Jun 18  2012 yorkshire_terrier_9.jpg
!cat ./data/annotations/xmls/Abyssinian_1.xml
# <annotation><folder>OXIIIT</folder><filename>Abyssinian_1.jpg</filename><source><database>OXFORD-IIIT Pet Dataset</database><annotation>OXIIIT</annotation><image>flickr</image></source><size><width>600</width><height>400</height><depth>3</depth></size><segmented>0</segmented><object><name>cat</name><pose>Frontal</pose><truncated>0</truncated><occluded>0</occluded><bndbox><xmin>333</xmin><ymin>72</ymin><xmax>425</xmax><ymax>158</ymax></bndbox><difficult>0</difficult></object></annotation>
import glob
import xml.etree.ElementTree as ET

# annotation xml 파일 파싱해서 bbox정보 추출
def get_bboxes_from_xml_test(xml_file):
  tree = ET.parse(xml_file)
  root = tree.getroot()
  bbox_names = []
  bboxes = []
  # 파일내에 있는 모든 object Element를 찾음. 
  for obj in root.findall('object'):

    bbox_name = obj.find('name').text
    xmlbox = obj.find('bndbox')
    x1 = int(xmlbox.find('xmin').text)
    y1 = int(xmlbox.find('ymin').text)
    x2 = int(xmlbox.find('xmax').text)
    y2 = int(xmlbox.find('ymax').text)

    bbox_names.append(bbox_name)
    bboxes.append([x1, y1, x2, y2])

  return bbox_names, bboxes

get_bboxes_from_xml_test('./data/annotations/xmls/Abyssinian_1.xml')
!ls -lia ./data/annotations/xmls/Abys*.xml

train, val image/annotation 메타 파일 보기

  • train과 valid 데이터로 나뉠 image와 annotation의 파일명을 가지는 메타 파일
  • train과 valid용 meta 파일을 별도로 만듬.
!cd ./data/annotations; cat trainval.txt
import pandas as pd

pet_df = pd.read_csv('./data/annotations/trainval.txt', sep=' ', header=None, names=['img_name', 'class_id', 'etc1', 'etc2'])
pet_df.head()
	img_name	class_id	etc1	etc2
0	Abyssinian_100	1	1	1
1	Abyssinian_101	1	1	1
2	Abyssinian_102	1	1	1
3	Abyssinian_103	1	1	1
4	Abyssinian_104	1	1	1
pet_df['class_id'].value_counts()
37    100
22    100
34    100
32    100
30    100
28    100
26    100
24    100
20    100
35    100
18    100
16    100
14    100
10    100
6     100
4     100
36    100
1     100
3     100
19    100
31    100
29    100
27    100
25    100
5     100
21    100
17    100
15    100
11    100
9     100
7     100
2     100
33     99
23     96
13     96
8      96
12     93
Name: class_id, dtype: int64
pet_df['class_name'] = pet_df['img_name'].apply(lambda x:x[:x.rfind('_')])
pet_df.head()

	img_name	class_id	etc1	etc2	class_name
0	Abyssinian_100	1	1	1	Abyssinian
1	Abyssinian_101	1	1	1	Abyssinian
2	Abyssinian_102	1	1	1	Abyssinian
3	Abyssinian_103	1	1	1	Abyssinian
4	Abyssinian_104	1	1	1	Abyssinian
print(train_df['class_id'].value_counts(), val_df['class_id'].value_counts())
37    90
22    90
34    90
32    90
30    90
28    90
26    90
24    90
20    90
35    90
18    90
16    90
14    90
10    90
6     90
4     90
36    90
1     90
3     90
19    90
31    90
29    90
27    90
25    90
5     90
21    90
17    90
15    90
11    90
9     90
7     90
2     90
33    89
23    87
13    86
8     86
12    84
Name: class_id, dtype: int64 37    10
36    10
17    10
16    10
15    10
14    10
13    10
11    10
10    10
9     10
8     10
7     10
6     10
5     10
4     10
3     10
2     10
18    10
19    10
20    10
21    10
35    10
34    10
33    10
32    10
31    10
30    10
29    10
28    10
27    10
26    10
25    10
24    10
22    10
1     10
12     9
23     9
Name: class_id, dtype: int64
train_df = train_df.sort_values(by='img_name')
val_df = val_df.sort_values(by='img_name')

# ann_file로 주어지는 메타파일은 가급적이면 소스데이터의 가장 상단 디렉토리에 저장하는 것이 바람직. 
train_df['img_name'].to_csv('./data/train.txt', sep=' ', header=False, index=False)
val_df['img_name'].to_csv('./data/val.txt', sep=' ', header=False, index=False)

pet_classes_list = pet_df['class_name'].unique().tolist()
print(pet_classes_list)
['Abyssinian', 'american_bulldog', 'american_pit_bull_terrier', 'basset_hound', 'beagle', 'Bengal', 'Birman', 'Bombay', 'boxer', 'British_Shorthair', 'chihuahua', 'Egyptian_Mau', 'english_cocker_spaniel', 'english_setter', 'german_shorthaired', 'great_pyrenees', 'havanese', 'japanese_chin', 'keeshond', 'leonberger', 'Maine_Coon', 'miniature_pinscher', 'newfoundland', 'Persian', 'pomeranian', 'pug', 'Ragdoll', 'Russian_Blue', 'saint_bernard', 'samoyed', 'scottish_terrier', 'shiba_inu', 'Siamese', 'Sphynx', 'staffordshire_bull_terrier', 'wheaten_terrier', 'yorkshire_terrier']

 

!echo 'train list #####'; cat ./data/train.txt
train list #####
Abyssinian_1
Abyssinian_10
Abyssinian_101
Abyssinian_102
...
yorkshire_terrier_187
yorkshire_terrier_188
yorkshire_terrier_189

!echo ' valid list ###'; cat ./data/val.txt
 valid list ###
Abyssinian_100
Abyssinian_11
...
yorkshire_terrier_185
yorkshire_terrier_190

mmdetection의 중립 annotation 포맷 변환

  • CLASSES 는 pet_df의 'class_name' 컬럼에 unique 데이터로 지정. class id는 tuple(list)형의 CLASSES의 index값에 따라 설정.
  • ann_file로 입력되는 메타 파일을 읽어서 개별 image정보와 ann 정보를 dict로 생성하여 data_infos list에 입력
  • 개별 XML 읽어서 ann 정보를 만드는 것은 get_bboxes_from_xml() 함수 이용.
  • 디버깅용으로 CustomDataset을 만들어서 미리 테스트 하는 방법도 고려.

import xml.etree.ElementTree as ET

# 1개의 annotation 파일에서 bbox 정보 추출. 여러개의 object가 있을 경우 이들 object의 name과 bbox 좌표들을 list로 반환.
def get_bboxes_from_xml(anno_dir, xml_file):
  anno_xml_file = osp.join(anno_dir, xml_file)
  tree = ET.parse(anno_xml_file)
  root = tree.getroot()
  bbox_names = []
  bboxes = []

  # 파일내에 있는 모든 object Element를 찾음. 
  for obj in root.findall('object'):
    #obj.find('name').text는 cat 이나 dog을 반환     
    #bbox_name = obj.find('name').text
    # object의 클래스명은 파일명에서 추출. 
    bbox_name = xml_file[:xml_file.rfind('_')]

    xmlbox = obj.find('bndbox')
    x1 = int(xmlbox.find('xmin').text)
    y1 = int(xmlbox.find('ymin').text)
    x2 = int(xmlbox.find('xmax').text)
    y2 = int(xmlbox.find('ymax').text)

    bboxes.append([x1, y1, x2, y2])
    bbox_names.append(bbox_name)

  return bbox_names, bboxes
import copy
import os.path as osp

import mmcv
import numpy as np
import cv2

from mmdet.datasets.builder import DATASETS
from mmdet.datasets.custom import CustomDataset

import xml.etree.ElementTree as ET

PET_CLASSES = pet_df['class_name'].unique().tolist()

@DATASETS.register_module(force=True)
class PetDataset(CustomDataset):
  CLASSES = PET_CLASSES

  # annotation에 대한 모든 파일명을 가지고 있는 텍스트 파일을 __init__(self, ann_file)로 입력 받고, 
  # 이 self.ann_file이 load_annotations()의 인자로 입력
  def load_annotations(self, ann_file):
    cat2label = {k:i for i, k in enumerate(self.CLASSES)}
    image_list = mmcv.list_from_file(self.ann_file)
    # 포맷 중립 데이터를 담을 list 객체
    data_infos = []

    for image_id in image_list:
      # self.img_prefix는 images 가 입력될 것임. 
      filename = '{0:}/{1:}.jpg'.format(self.img_prefix, image_id)
      # 원본 이미지의 너비, 높이를 image를 직접 로드하여 구함. 
      image = cv2.imread(filename)
      height, width = image.shape[:2]
      # 개별 image의 annotation 정보 저장용 Dict 생성. key값 filename에는 image의 파일명만 들어감(디렉토리는 제외)
      data_info = {'filename': filename,
                  'width': width, 'height': height}
      # 개별 annotation XML 파일이 있는 서브 디렉토리의 prefix 변환. 
      label_prefix = self.img_prefix.replace('images', 'annotations')
      
      # 개별 annotation XML 파일을 1개 line 씩 읽어서 list 로드. annotation XML파일이 xmls 밑에 있음에 유의
      anno_xml_file = osp.join(label_prefix, 'xmls/'+str(image_id)+'.xml')
      # 메타 파일에는 이름이 있으나 실제로는 존재하지 않는 XML이 있으므로 이는 제외. 
      if not osp.exists(anno_xml_file):
          continue
      
      # get_bboxes_from_xml() 를 이용하여 개별 XML 파일에 있는 이미지의 모든 bbox 정보를 list 객체로 생성. 
      anno_dir = osp.join(label_prefix, 'xmls')
      bbox_names, bboxes = get_bboxes_from_xml(anno_dir, str(image_id)+'.xml')
      #print('#########:', bbox_names)
                  
      gt_bboxes = []
      gt_labels = []
      gt_bboxes_ignore = []
      gt_labels_ignore = []
        
      # bbox별 Object들의 class name을 class id로 매핑. class id는 tuple(list)형의 CLASSES의 index값에 따라 설정
      for bbox_name, bbox in zip(bbox_names, bboxes):
        # 만약 bbox_name이 클래스명에 해당 되면, gt_bboxes와 gt_labels에 추가, 그렇지 않으면 gt_bboxes_ignore, gt_labels_ignore에 추가
        # bbox_name이 CLASSES중에 반드시 하나 있어야 함. 안 그러면 FILTERING 되므로 주의 할것. 
        if bbox_name in cat2label:
            gt_bboxes.append(bbox)
            # gt_labels에는 class id를 입력
            gt_labels.append(cat2label[bbox_name])
        else:
            gt_bboxes_ignore.append(bbox)
            gt_labels_ignore.append(-1)
      
      # 개별 image별 annotation 정보를 가지는 Dict 생성. 해당 Dict의 value값을 np.array형태로 bbox의 좌표와 label값으로 생성. 
      data_anno = {
        'bboxes': np.array(gt_bboxes, dtype=np.float32).reshape(-1, 4),
        'labels': np.array(gt_labels, dtype=np.long),
        'bboxes_ignore': np.array(gt_bboxes_ignore, dtype=np.float32).reshape(-1, 4),
        'labels_ignore': np.array(gt_labels_ignore, dtype=np.long)
      }
      
      # image에 대한 메타 정보를 가지는 data_info Dict에 'ann' key값으로 data_anno를 value로 저장. 
      data_info.update(ann=data_anno)
      # 전체 annotation 파일들에 대한 정보를 가지는 data_infos에 data_info Dict를 추가
      data_infos.append(data_info)
      #print(data_info)

    return data_infos
''' 디버깅 용도로 CustomDataset을 흉내낸 클래스를 생성하여 다양한 테스트를 수행 가능 '''

import os.path as osp

PET_CLASSES = pet_df['class_name'].unique().tolist()

# 디버깅 용도로 CustomDataset을 흉내낸 클래스 생성. 
class PetDataset_imsi():
  CLASSES = PET_CLASSES

  # 생성자 함수 생성. 
  def __init__(self, data_root, ann_file, img_prefix):
      self.data_root = data_root
      self.ann_file = osp.join(data_root, ann_file)
      self.img_prefix = osp.join(data_root, img_prefix)
      
      self.data_infos = self.load_annotations(self.ann_file)

  # annotation에 대한 모든 파일명을 가지고 있는 텍스트 파일을 __init__(self, ann_file)로 입력 받고, 
  # 이 self.ann_file이 load_annotations()의 인자로 입력
  def load_annotations(self, ann_file):
    cat2label = {k:i for i, k in enumerate(self.CLASSES)}
    image_list = mmcv.list_from_file(self.ann_file)
    # 포맷 중립 데이터를 담을 list 객체
    data_infos = []

    for image_id in image_list:
      # self.img_prefix는 images 가 입력될 것임. 
      filename = '{0:}/{1:}.jpg'.format(self.img_prefix, image_id)
      # 원본 이미지의 너비, 높이를 image를 직접 로드하여 구함. 
      image = cv2.imread(filename)
      height, width = image.shape[:2]
      # 개별 image의 annotation 정보 저장용 Dict 생성. key값 filename에는 image의 파일명만 들어감(디렉토리는 제외)
      data_info = {'filename': filename,
                  'width': width, 'height': height}
      # 개별 annotation XML 파일이 있는 서브 디렉토리의 prefix 변환. 
      label_prefix = self.img_prefix.replace('images', 'annotations')
      
      # 개별 annotation XML 파일을 1개 line 씩 읽어서 list 로드. annotation XML파일이 xmls 밑에 있음에 유의
      anno_xml_file = osp.join(label_prefix, 'xmls/'+str(image_id)+'.xml')
      # 메타 파일에는 이름이 있으나 실제로는 존재하지 않는 XML이 있으므로 이는 제외. 
      if not osp.exists(anno_xml_file):
          continue
      
      # get_bboxes_from_xml() 를 이용하여 개별 XML 파일에 있는 이미지의 모든 bbox 정보를 list 객체로 생성. 
      anno_dir = osp.join(label_prefix, 'xmls')
      bbox_names, bboxes = get_bboxes_from_xml(anno_dir, str(image_id)+'.xml')
      #print('#########:', bbox_names)
                  
      gt_bboxes = []
      gt_labels = []
      gt_bboxes_ignore = []
      gt_labels_ignore = []
        
      # bbox별 Object들의 class name을 class id로 매핑. class id는 tuple(list)형의 CLASSES의 index값에 따라 설정
      for bbox_name, bbox in zip(bbox_names, bboxes):
        # 만약 bbox_name이 클래스명에 해당 되면, gt_bboxes와 gt_labels에 추가, 그렇지 않으면 gt_bboxes_ignore, gt_labels_ignore에 추가
        # bbox_name이 CLASSES중에 반드시 하나 있어야 함. 안 그러면 FILTERING 되므로 주의 할것. 
        if bbox_name in cat2label:
            gt_bboxes.append(bbox)
            # gt_labels에는 class id를 입력
            gt_labels.append(cat2label[bbox_name])
        else:
            gt_bboxes_ignore.append(bbox)
            gt_labels_ignore.append(-1)
      
      # 개별 image별 annotation 정보를 가지는 Dict 생성. 해당 Dict의 value값을 np.array형태로 bbox의 좌표와 label값으로 생성. 
      data_anno = {
        'bboxes': np.array(gt_bboxes, dtype=np.float32).reshape(-1, 4),
        'labels': np.array(gt_labels, dtype=np.long),
        'bboxes_ignore': np.array(gt_bboxes_ignore, dtype=np.float32).reshape(-1, 4),
        'labels_ignore': np.array(gt_labels_ignore, dtype=np.long)
      }
      
      # image에 대한 메타 정보를 가지는 data_info Dict에 'ann' key값으로 data_anno를 value로 저장. 
      data_info.update(ann=data_anno)
      # 전체 annotation 파일들에 대한 정보를 가지는 data_infos에 data_info Dict를 추가
      data_infos.append(data_info)
      #print(data_info)

    return data_infos

 

반응형
728x90
반응형
from mmcv import Config

cfg = Config.fromfile(config_file)
print(cfg.pretty_text)

# model = dict(
    type='FasterRCNN',
    pretrained='torchvision://resnet50',
    backbone=dict(
        type='ResNet',
        depth=50,
        num_stages=4,
        out_indices=(0, 1, 2, 3),
        frozen_stages=1,
        norm_cfg=dict(type='BN', requires_grad=True),
        norm_eval=True,
        style='pytorch'),
    neck=dict(
        type='FPN',
        in_channels=[256, 512, 1024, 2048],
        out_channels=256,
        num_outs=5),
    rpn_head=dict(
        type='RPNHead',
        in_channels=256,
        feat_channels=256,
        anchor_generator=dict(
            type='AnchorGenerator',
            scales=[8],
            ratios=[0.5, 1.0, 2.0],
            strides=[4, 8, 16, 32, 64]),
        bbox_coder=dict(
            type='DeltaXYWHBBoxCoder',
            target_means=[0.0, 0.0, 0.0, 0.0],
            target_stds=[1.0, 1.0, 1.0, 1.0]),
        loss_cls=dict(
            type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),
        loss_bbox=dict(type='L1Loss', loss_weight=1.0)),
    roi_head=dict(
        type='StandardRoIHead',
        bbox_roi_extractor=dict(
            type='SingleRoIExtractor',
            roi_layer=dict(type='RoIAlign', output_size=7, sampling_ratio=0),
            out_channels=256,
            featmap_strides=[4, 8, 16, 32]),
        bbox_head=dict(
            type='Shared2FCBBoxHead',
            in_channels=256,
            fc_out_channels=1024,
            roi_feat_size=7,
            num_classes=80,
            bbox_coder=dict(
                type='DeltaXYWHBBoxCoder',
                target_means=[0.0, 0.0, 0.0, 0.0],
                target_stds=[0.1, 0.1, 0.2, 0.2]),
            reg_class_agnostic=False,
            loss_cls=dict(
                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),
            loss_bbox=dict(type='L1Loss', loss_weight=1.0))),
    train_cfg=dict(
        rpn=dict(
            assigner=dict(
                type='MaxIoUAssigner',
                pos_iou_thr=0.7,
                neg_iou_thr=0.3,
                min_pos_iou=0.3,
                match_low_quality=True,
                ignore_iof_thr=-1),
            sampler=dict(
                type='RandomSampler',
                num=256,
                pos_fraction=0.5,
                neg_pos_ub=-1,
                add_gt_as_proposals=False),
            allowed_border=-1,
            pos_weight=-1,
            debug=False),
        rpn_proposal=dict(
            nms_pre=2000,
            max_per_img=1000,
            nms=dict(type='nms', iou_threshold=0.7),
            min_bbox_size=0),
        rcnn=dict(
            assigner=dict(
                type='MaxIoUAssigner',
                pos_iou_thr=0.5,
                neg_iou_thr=0.5,
                min_pos_iou=0.5,
                match_low_quality=False,
                ignore_iof_thr=-1),
            sampler=dict(
                type='RandomSampler',
                num=512,
                pos_fraction=0.25,
                neg_pos_ub=-1,
                add_gt_as_proposals=True),
            pos_weight=-1,
            debug=False)),
    test_cfg=dict(
        rpn=dict(
            nms_pre=1000,
            max_per_img=1000,
            nms=dict(type='nms', iou_threshold=0.7),
            min_bbox_size=0),
        rcnn=dict(
            score_thr=0.05,
            nms=dict(type='nms', iou_threshold=0.5),
            max_per_img=100)))
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',
        mean=[123.675, 116.28, 103.53],
        std=[58.395, 57.12, 57.375],
        to_rgb=True),
    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',
                mean=[123.675, 116.28, 103.53],
                std=[58.395, 57.12, 57.375],
                to_rgb=True),
            dict(type='Pad', size_divisor=32),
            dict(type='ImageToTensor', keys=['img']),
            dict(type='Collect', keys=['img'])
        ])
]
data = dict(
    samples_per_gpu=2,
    workers_per_gpu=2,
    train=dict(
        type='CocoDataset',
        ann_file='data/coco/annotations/instances_train2017.json',
        img_prefix='data/coco/train2017/',
        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',
                mean=[123.675, 116.28, 103.53],
                std=[58.395, 57.12, 57.375],
                to_rgb=True),
            dict(type='Pad', size_divisor=32),
            dict(type='DefaultFormatBundle'),
            dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
        ]),
    val=dict(
        type='CocoDataset',
        ann_file='data/coco/annotations/instances_val2017.json',
        img_prefix='data/coco/val2017/',
        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',
                        mean=[123.675, 116.28, 103.53],
                        std=[58.395, 57.12, 57.375],
                        to_rgb=True),
                    dict(type='Pad', size_divisor=32),
                    dict(type='ImageToTensor', keys=['img']),
                    dict(type='Collect', keys=['img'])
                ])
        ]),
    test=dict(
        type='CocoDataset',
        ann_file='data/coco/annotations/instances_val2017.json',
        img_prefix='data/coco/val2017/',
        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',
                        mean=[123.675, 116.28, 103.53],
                        std=[58.395, 57.12, 57.375],
                        to_rgb=True),
                    dict(type='Pad', size_divisor=32),
                    dict(type='ImageToTensor', keys=['img']),
                    dict(type='Collect', keys=['img'])
                ])
        ]))
evaluation = dict(interval=1, metric='bbox')
optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)
optimizer_config = dict(grad_clip=None)
lr_config = dict(
    policy='step',
    warmup='linear',
    warmup_iters=500,
    warmup_ratio=0.001,
    step=[8, 11])
runner = dict(type='EpochBasedRunner', max_epochs=12)
checkpoint_config = dict(interval=1)
log_config = dict(interval=50, hooks=[dict(type='TextLoggerHook')])
custom_hooks = [dict(type='NumClassCheckHook')]
dist_params = dict(backend='nccl')
log_level = 'INFO'
load_from = None
resume_from = None
workflow = [('train', 1)]

 

data_pipeline의 구성

순차적으로 파이프라인이 진행될때마다 개별작업은 새로운 key값을 추가하거나(녹색), 기존key값 update적용(주황)

annotation 내용을 어떻게 바꿔야하는가에 관한 내용들

formatting은 모델에 최종적으로 전달할 내용들

 

img_norm_cfg = dict(
    # rgb 적용후, meanstandard 적용
    mean = [123.675, 116.28, 103.53], std=[58.395, 57.12, 57.375], to_rgb=True)
train_pipeline = [ # train 방식
    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']),
        ])
]​

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형
728x90
반응형

 config를 이해하는게 mmdetection을 이해하는데 매우 중요함

 

faster

# faster_rcnn_r50_fpn_1x_coco.py의 내용
_base_ = [
	'../_base_/models/faster_rcnn_r50_fpn.py', # model
	'../_base_/dataset/coco_detection.py',     # dataset
 	'../_base_/schedules/schedule_1x.py',      # schedule
	'../_base_/default_runtime.py',            # runtime
]


# 위 내용이 합쳐짐
from mmcv import Config
cfg = Config.fromfile(config_file)
print(cfg.pretty_text)

from mmcv import Config

cfg = Config.fromfile(config_file)
print(cfg.pretty_text)

# model
model = dict(
    type='FasterRCNN', # type
    pretrained='torchvision://resnet50',
    backbone=dict( # backbone, resnet
        type='ResNet',
        depth=50,
        num_stages=4,
        out_indices=(0, 1, 2, 3),
        frozen_stages=1,
        norm_cfg=dict(type='BN', requires_grad=True),
        norm_eval=True,
        style='pytorch'),
    neck=dict(  # neck, fpn
        type='FPN',
        in_channels=[256, 512, 1024, 2048],
        out_channels=256,
        num_outs=5),
    rpn_head=dict(
        type='RPNHead',
        in_channels=256,
        feat_channels=256,
        anchor_generator=dict(
            type='AnchorGenerator',
            scales=[8],
            ratios=[0.5, 1.0, 2.0],
            strides=[4, 8, 16, 32, 64]),
        bbox_coder=dict(
            type='DeltaXYWHBBoxCoder',
            target_means=[0.0, 0.0, 0.0, 0.0],
            target_stds=[1.0, 1.0, 1.0, 1.0]),
        loss_cls=dict(
            type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),
        loss_bbox=dict(type='L1Loss', loss_weight=1.0)),
    roi_head=dict( # roihead
        type='StandardRoIHead',
        bbox_roi_extractor=dict(
            type='SingleRoIExtractor',
            roi_layer=dict(type='RoIAlign', output_size=7, sampling_ratio=0),
            out_channels=256,
            featmap_strides=[4, 8, 16, 32]),
        bbox_head=dict( # bbox head : num_classes
            type='Shared2FCBBoxHead',
            in_channels=256,
            fc_out_channels=1024,
            roi_feat_size=7,
            num_classes=80,
            bbox_coder=dict(
                type='DeltaXYWHBBoxCoder',
                target_means=[0.0, 0.0, 0.0, 0.0],
                target_stds=[0.1, 0.1, 0.2, 0.2]),
            reg_class_agnostic=False,
            loss_cls=dict(
                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),
            loss_bbox=dict(type='L1Loss', loss_weight=1.0))),
    train_cfg=dict(
        rpn=dict(
            assigner=dict(
                type='MaxIoUAssigner',
                pos_iou_thr=0.7,
                neg_iou_thr=0.3,
                min_pos_iou=0.3,
                match_low_quality=True,
                ignore_iof_thr=-1),
            sampler=dict(
                type='RandomSampler',
                num=256,
                pos_fraction=0.5,
                neg_pos_ub=-1,
                add_gt_as_proposals=False),
            allowed_border=-1,
            pos_weight=-1,
            debug=False),
        rpn_proposal=dict(
            nms_pre=2000,
            max_per_img=1000,
            nms=dict(type='nms', iou_threshold=0.7),
            min_bbox_size=0),
        rcnn=dict(
            assigner=dict(
                type='MaxIoUAssigner',
                pos_iou_thr=0.5,
                neg_iou_thr=0.5,
                min_pos_iou=0.5,
                match_low_quality=False,
                ignore_iof_thr=-1),
            sampler=dict(
                type='RandomSampler',
                num=512,
                pos_fraction=0.25,
                neg_pos_ub=-1,
                add_gt_as_proposals=True),
            pos_weight=-1,
            debug=False)),
    test_cfg=dict(
        rpn=dict(
            nms_pre=1000,
            max_per_img=1000,
            nms=dict(type='nms', iou_threshold=0.7),
            min_bbox_size=0),
        rcnn=dict(
            score_thr=0.05,
            nms=dict(type='nms', iou_threshold=0.5),
            max_per_img=100)))
# dataset            
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',
        mean=[123.675, 116.28, 103.53],
        std=[58.395, 57.12, 57.375],
        to_rgb=True),
    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',
                mean=[123.675, 116.28, 103.53],
                std=[58.395, 57.12, 57.375],
                to_rgb=True),
            dict(type='Pad', size_divisor=32),
            dict(type='ImageToTensor', keys=['img']),
            dict(type='Collect', keys=['img'])
        ])
]
data = dict(
    samples_per_gpu=2,
    workers_per_gpu=2,
    train=dict(
        type='CocoDataset',
        ann_file='data/coco/annotations/instances_train2017.json',
        img_prefix='data/coco/train2017/',
        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',
                mean=[123.675, 116.28, 103.53],
                std=[58.395, 57.12, 57.375],
                to_rgb=True),
            dict(type='Pad', size_divisor=32),
            dict(type='DefaultFormatBundle'),
            dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
        ]),
    val=dict(
        type='CocoDataset',
        ann_file='data/coco/annotations/instances_val2017.json',
        img_prefix='data/coco/val2017/',
        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',
                        mean=[123.675, 116.28, 103.53],
                        std=[58.395, 57.12, 57.375],
                        to_rgb=True),
                    dict(type='Pad', size_divisor=32),
                    dict(type='ImageToTensor', keys=['img']),
                    dict(type='Collect', keys=['img'])
                ])
        ]),
    test=dict(
        type='CocoDataset',
        ann_file='data/coco/annotations/instances_val2017.json',
        img_prefix='data/coco/val2017/',
        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',
                        mean=[123.675, 116.28, 103.53],
                        std=[58.395, 57.12, 57.375],
                        to_rgb=True),
                    dict(type='Pad', size_divisor=32),
                    dict(type='ImageToTensor', keys=['img']),
                    dict(type='Collect', keys=['img'])
                ])
        ]))
evaluation = dict(interval=1, metric='bbox')
# optimizer sgd
optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)
optimizer_config = dict(grad_clip=None)
lr_config = dict(
    policy='step',
    warmup='linear',
    warmup_iters=500,
    warmup_ratio=0.001,
    step=[8, 11])
# runner : epoch
runner = dict(type='EpochBasedRunner', max_epochs=12)
checkpoint_config = dict(interval=1)
log_config = dict(interval=50, hooks=[dict(type='TextLoggerHook')])
custom_hooks = [dict(type='NumClassCheckHook')]
dist_params = dict(backend='nccl')
log_level = 'INFO'
load_from = None
resume_from = None
workflow = [('train', 1)]

config 대분류 및 주요설정내역

config 대분류 설명
dataset dataset의 type(customdataset, cocodataset 등), train/val/test dataset 유형, data_root, train/val/test dataset의 주요 파라미터 설정(type, ann_file, img_prefix, pipeline 등)
model object detection model의 backbone, neck, dense head, roi extractor, roi head(num_classes=4) 주요 영역별로 세부 설정
schedule optimizer 유형 설정 (sgd, adam, rmsprop 등), 최초 learning 설정
학습중 동적 learning rate 적용 정책 설정(step, cyclic, cosine annealing 등)
train 시 epochs 횟수 : learning rate scheduler
runtime 주로 hook(callback)관련 설정
학습 중 checkpoint 파일, log 파일 생성을 위한 interval epochs 수

 

 

 

 

 

 

 

반응형
728x90
반응형

학습된 모델을 이용하여 Video Detection 수행하기

classes 만 바뀜

%cd /content
!mkdir /content/data
!wget -O /content/data/the_rock_chase.mp4 https://github.com/chulminkw/DLCV/blob/master/data/video/the_rock_chase.mp4?raw=true

 

CLASSES = ('Car', 'Truck', 'Pedestrian', 'Cyclist')
labels_to_names_seq = {i:k for i, k in enumerate(CLASSES)}
labels_to_names_seq
# {0: 'Car', 1: 'Truck', 2: 'Pedestrian', 3: 'Cyclist'}

 

CLASSES = ('Car', 'Truck', 'Pedestrian', 'Cyclist')
cat2label = {k:i for i, k in enumerate(CLASSES)}

def get_detected_img(model, img_array,  score_threshold=0.3, is_print=True):
  # 인자로 들어온 image_array를 복사. 
  draw_img = img_array.copy()
  bbox_color=(0, 255, 0)
  text_color=(0, 0, 255)

  # model과 image array를 입력 인자로 inference detection 수행하고 결과를 results로 받음. 
  # results는 80개의 2차원 array(shape=(오브젝트갯수, 5))를 가지는 list. 
  results = inference_detector(model, img_array)

  # 80개의 array원소를 가지는 results 리스트를 loop를 돌면서 개별 2차원 array들을 추출하고 이를 기반으로 이미지 시각화 
  # results 리스트의 위치 index가 바로 COCO 매핑된 Class id. 여기서는 result_ind가 class id
  # 개별 2차원 array에 오브젝트별 좌표와 class confidence score 값을 가짐. 
  for result_ind, result in enumerate(results):
    # 개별 2차원 array의 row size가 0 이면 해당 Class id로 값이 없으므로 다음 loop로 진행. 
    if len(result) == 0:
      continue
    
    # 2차원 array에서 5번째 컬럼에 해당하는 값이 score threshold이며 이 값이 함수 인자로 들어온 score_threshold 보다 낮은 경우는 제외. 
    result_filtered = result[np.where(result[:, 4] > score_threshold)]
    
    # 해당 클래스 별로 Detect된 여러개의 오브젝트 정보가 2차원 array에 담겨 있으며, 이 2차원 array를 row수만큼 iteration해서 개별 오브젝트의 좌표값 추출. 
    for i in range(len(result_filtered)):
      # 좌상단, 우하단 좌표 추출. 
      left = int(result_filtered[i, 0])
      top = int(result_filtered[i, 1])
      right = int(result_filtered[i, 2])
      bottom = int(result_filtered[i, 3])
      caption = "{}: {:.4f}".format(labels_to_names_seq[result_ind], result_filtered[i, 4])
      cv2.rectangle(draw_img, (left, top), (right, bottom), color=bbox_color, thickness=2)
      cv2.putText(draw_img, caption, (int(left), int(top - 7)), cv2.FONT_HERSHEY_SIMPLEX, 0.37, text_color, 1)
      if is_print:
        print(caption)

  return draw_img
import time

def do_detected_video(model, input_path, output_path, score_threshold, do_print=True):
    
    cap = cv2.VideoCapture(input_path)

    codec = cv2.VideoWriter_fourcc(*'XVID')

    vid_size = (round(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),round(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
    vid_fps = cap.get(cv2.CAP_PROP_FPS)

    vid_writer = cv2.VideoWriter(output_path, codec, vid_fps, vid_size) 

    frame_cnt = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    print('총 Frame 갯수:', frame_cnt)
    btime = time.time()
    while True:
        hasFrame, img_frame = cap.read()
        if not hasFrame:
            print('더 이상 처리할 frame이 없습니다.')
            break
        stime = time.time()
        img_frame = get_detected_img(model, img_frame,  score_threshold=score_threshold, is_print=False)
        if do_print:
          print('frame별 detection 수행 시간:', round(time.time() - stime, 4))
        vid_writer.write(img_frame)
    # end of while loop

    vid_writer.release()
    cap.release()

    print('최종 detection 완료 수행 시간:', round(time.time() - btime, 4))
do_detected_video(model, '/content/data/the_rock_chase.mp4', '/content/data/the_rock_chase_out1.mp4', score_threshold=0.4, do_print=True)

# 총 Frame 갯수: 503
frame별 detection 수행 시간: 0.1158
frame별 detection 수행 시간: 0.0974
frame별 detection 수행 시간: 0.0929
frame별 detection 수행 시간: 0.102
frame별 detection 수행 시간: 0.1017
frame별 detection 수행 시간: 0.1063
frame별 detection 수행 시간: 0.0948
frame별 detection 수행 시간: 0.1055
frame별 detection 수행 시간: 0.0973
frame별 detection 수행 시간: 0.1025
frame별 detection 수행 시간: 0.096
frame별 detection 수행 시간: 0.0997
frame별 detection 수행 시간: 0.0982
frame별 detection 수행 시간: 0.1127
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0982
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0966
frame별 detection 수행 시간: 0.0955
frame별 detection 수행 시간: 0.0945
frame별 detection 수행 시간: 0.0959
frame별 detection 수행 시간: 0.1024
frame별 detection 수행 시간: 0.0985
frame별 detection 수행 시간: 0.095
frame별 detection 수행 시간: 0.1022
frame별 detection 수행 시간: 0.0937
frame별 detection 수행 시간: 0.096
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0958
frame별 detection 수행 시간: 0.1023
frame별 detection 수행 시간: 0.0971
frame별 detection 수행 시간: 0.0946
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0938
frame별 detection 수행 시간: 0.0946
frame별 detection 수행 시간: 0.0938
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0955
frame별 detection 수행 시간: 0.0991
frame별 detection 수행 시간: 0.0997
frame별 detection 수행 시간: 0.0964
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0968
frame별 detection 수행 시간: 0.0928
frame별 detection 수행 시간: 0.0995
frame별 detection 수행 시간: 0.0998
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.0931
frame별 detection 수행 시간: 0.095
frame별 detection 수행 시간: 0.103
frame별 detection 수행 시간: 0.1082
frame별 detection 수행 시간: 0.091
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.0929
frame별 detection 수행 시간: 0.092
frame별 detection 수행 시간: 0.094
frame별 detection 수행 시간: 0.0917
frame별 detection 수행 시간: 0.0964
frame별 detection 수행 시간: 0.092
frame별 detection 수행 시간: 0.0937
frame별 detection 수행 시간: 0.0936
frame별 detection 수행 시간: 0.1009
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0985
frame별 detection 수행 시간: 0.0968
frame별 detection 수행 시간: 0.092
frame별 detection 수행 시간: 0.0959
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0946
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.0987
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0927
frame별 detection 수행 시간: 0.0974
frame별 detection 수행 시간: 0.0932
frame별 detection 수행 시간: 0.1043
frame별 detection 수행 시간: 0.0947
frame별 detection 수행 시간: 0.1006
frame별 detection 수행 시간: 0.0955
frame별 detection 수행 시간: 0.1049
frame별 detection 수행 시간: 0.0924
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0959
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.094
frame별 detection 수행 시간: 0.0949
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0952
frame별 detection 수행 시간: 0.0974
frame별 detection 수행 시간: 0.1047
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0977
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.0927
frame별 detection 수행 시간: 0.0957
frame별 detection 수행 시간: 0.0938
frame별 detection 수행 시간: 0.0997
frame별 detection 수행 시간: 0.0979
frame별 detection 수행 시간: 0.0972
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0992
frame별 detection 수행 시간: 0.1034
frame별 detection 수행 시간: 0.1029
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0946
frame별 detection 수행 시간: 0.0934
frame별 detection 수행 시간: 0.0966
frame별 detection 수행 시간: 0.0917
frame별 detection 수행 시간: 0.1
frame별 detection 수행 시간: 0.0979
frame별 detection 수행 시간: 0.0953
frame별 detection 수행 시간: 0.0932
frame별 detection 수행 시간: 0.0946
frame별 detection 수행 시간: 0.0906
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.094
frame별 detection 수행 시간: 0.0969
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.0967
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0934
frame별 detection 수행 시간: 0.0924
frame별 detection 수행 시간: 0.0924
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.1
frame별 detection 수행 시간: 0.092
frame별 detection 수행 시간: 0.0928
frame별 detection 수행 시간: 0.0921
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.092
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0937
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0961
frame별 detection 수행 시간: 0.0928
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0905
frame별 detection 수행 시간: 0.0912
frame별 detection 수행 시간: 0.0927
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0958
frame별 detection 수행 시간: 0.0936
frame별 detection 수행 시간: 0.0922
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.0928
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0924
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0972
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.0948
frame별 detection 수행 시간: 0.0924
frame별 detection 수행 시간: 0.0932
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.09
frame별 detection 수행 시간: 0.097
frame별 detection 수행 시간: 0.0927
frame별 detection 수행 시간: 0.0955
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.0947
frame별 detection 수행 시간: 0.0917
frame별 detection 수행 시간: 0.1029
frame별 detection 수행 시간: 0.0912
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0921
frame별 detection 수행 시간: 0.0967
frame별 detection 수행 시간: 0.0906
frame별 detection 수행 시간: 0.0945
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0952
frame별 detection 수행 시간: 0.0904
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0905
frame별 detection 수행 시간: 0.092
frame별 detection 수행 시간: 0.0902
frame별 detection 수행 시간: 0.0927
frame별 detection 수행 시간: 0.0963
frame별 detection 수행 시간: 0.0989
frame별 detection 수행 시간: 0.0917
frame별 detection 수행 시간: 0.0952
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.0905
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.0906
frame별 detection 수행 시간: 0.0981
frame별 detection 수행 시간: 0.0928
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0904
frame별 detection 수행 시간: 0.094
frame별 detection 수행 시간: 0.0909
frame별 detection 수행 시간: 0.0961
frame별 detection 수행 시간: 0.0936
frame별 detection 수행 시간: 0.0978
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0961
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0955
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0906
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0898
frame별 detection 수행 시간: 0.0893
frame별 detection 수행 시간: 0.0923
frame별 detection 수행 시간: 0.0999
frame별 detection 수행 시간: 0.0909
frame별 detection 수행 시간: 0.1059
frame별 detection 수행 시간: 0.0957
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0931
frame별 detection 수행 시간: 0.1005
frame별 detection 수행 시간: 0.0927
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0967
frame별 detection 수행 시간: 0.0912
frame별 detection 수행 시간: 0.097
frame별 detection 수행 시간: 0.0902
frame별 detection 수행 시간: 0.0934
frame별 detection 수행 시간: 0.0907
frame별 detection 수행 시간: 0.0956
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.0953
frame별 detection 수행 시간: 0.0946
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.0934
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0994
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0974
frame별 detection 수행 시간: 0.097
frame별 detection 수행 시간: 0.0927
frame별 detection 수행 시간: 0.0999
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.0974
frame별 detection 수행 시간: 0.0938
frame별 detection 수행 시간: 0.1012
frame별 detection 수행 시간: 0.0964
frame별 detection 수행 시간: 0.0978
frame별 detection 수행 시간: 0.0947
frame별 detection 수행 시간: 0.0949
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0955
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0963
frame별 detection 수행 시간: 0.0936
frame별 detection 수행 시간: 0.096
frame별 detection 수행 시간: 0.1008
frame별 detection 수행 시간: 0.0964
frame별 detection 수행 시간: 0.0937
frame별 detection 수행 시간: 0.0947
frame별 detection 수행 시간: 0.094
frame별 detection 수행 시간: 0.095
frame별 detection 수행 시간: 0.0929
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.1009
frame별 detection 수행 시간: 0.0948
frame별 detection 수행 시간: 0.0917
frame별 detection 수행 시간: 0.0931
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0934
frame별 detection 수행 시간: 0.0932
frame별 detection 수행 시간: 0.0961
frame별 detection 수행 시간: 0.0972
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.1005
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0967
frame별 detection 수행 시간: 0.0998
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0947
frame별 detection 수행 시간: 0.0921
frame별 detection 수행 시간: 0.0945
frame별 detection 수행 시간: 0.0932
frame별 detection 수행 시간: 0.0934
frame별 detection 수행 시간: 0.0913
frame별 detection 수행 시간: 0.0918
frame별 detection 수행 시간: 0.0949
frame별 detection 수행 시간: 0.0956
frame별 detection 수행 시간: 0.0991
frame별 detection 수행 시간: 0.096
frame별 detection 수행 시간: 0.1012
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.095
frame별 detection 수행 시간: 0.0947
frame별 detection 수행 시간: 0.0949
frame별 detection 수행 시간: 0.0959
frame별 detection 수행 시간: 0.0977
frame별 detection 수행 시간: 0.0962
frame별 detection 수행 시간: 0.1024
frame별 detection 수행 시간: 0.0923
frame별 detection 수행 시간: 0.0971
frame별 detection 수행 시간: 0.0973
frame별 detection 수행 시간: 0.0992
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0991
frame별 detection 수행 시간: 0.0937
frame별 detection 수행 시간: 0.0988
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0993
frame별 detection 수행 시간: 0.0968
frame별 detection 수행 시간: 0.1021
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0995
frame별 detection 수행 시간: 0.0964
frame별 detection 수행 시간: 0.1024
frame별 detection 수행 시간: 0.0987
frame별 detection 수행 시간: 0.1017
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.1026
frame별 detection 수행 시간: 0.096
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.09
frame별 detection 수행 시간: 0.0969
frame별 detection 수행 시간: 0.0927
frame별 detection 수행 시간: 0.1002
frame별 detection 수행 시간: 0.0901
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0915
frame별 detection 수행 시간: 0.0916
frame별 detection 수행 시간: 0.0924
frame별 detection 수행 시간: 0.0936
frame별 detection 수행 시간: 0.0928
frame별 detection 수행 시간: 0.0996
frame별 detection 수행 시간: 0.0977
frame별 detection 수행 시간: 0.095
frame별 detection 수행 시간: 0.0898
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0987
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0945
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0923
frame별 detection 수행 시간: 0.0902
frame별 detection 수행 시간: 0.0915
frame별 detection 수행 시간: 0.0931
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0948
frame별 detection 수행 시간: 0.0928
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0945
frame별 detection 수행 시간: 0.091
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0919
frame별 detection 수행 시간: 0.0974
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0985
frame별 detection 수행 시간: 0.0918
frame별 detection 수행 시간: 0.0916
frame별 detection 수행 시간: 0.0901
frame별 detection 수행 시간: 0.0938
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0909
frame별 detection 수행 시간: 0.0931
frame별 detection 수행 시간: 0.1007
frame별 detection 수행 시간: 0.0966
frame별 detection 수행 시간: 0.0917
frame별 detection 수행 시간: 0.0912
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.092
frame별 detection 수행 시간: 0.0937
frame별 detection 수행 시간: 0.0898
frame별 detection 수행 시간: 0.0884
frame별 detection 수행 시간: 0.0916
frame별 detection 수행 시간: 0.0936
frame별 detection 수행 시간: 0.0885
frame별 detection 수행 시간: 0.0902
frame별 detection 수행 시간: 0.089
frame별 detection 수행 시간: 0.0985
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0959
frame별 detection 수행 시간: 0.0947
frame별 detection 수행 시간: 0.0982
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0959
frame별 detection 수행 시간: 0.0922
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.0932
frame별 detection 수행 시간: 0.0955
frame별 detection 수행 시간: 0.0912
frame별 detection 수행 시간: 0.096
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.1
frame별 detection 수행 시간: 0.0987
frame별 detection 수행 시간: 0.1007
frame별 detection 수행 시간: 0.097
frame별 detection 수행 시간: 0.098
frame별 detection 수행 시간: 0.0934
frame별 detection 수행 시간: 0.0985
frame별 detection 수행 시간: 0.0926
frame별 detection 수행 시간: 0.0973
frame별 detection 수행 시간: 0.0918
frame별 detection 수행 시간: 0.0914
frame별 detection 수행 시간: 0.0931
frame별 detection 수행 시간: 0.0991
frame별 detection 수행 시간: 0.0922
frame별 detection 수행 시간: 0.095
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0954
frame별 detection 수행 시간: 0.0908
frame별 detection 수행 시간: 0.0938
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0921
frame별 detection 수행 시간: 0.0967
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.0896
frame별 detection 수행 시간: 0.0989
frame별 detection 수행 시간: 0.092
frame별 detection 수행 시간: 0.097
frame별 detection 수행 시간: 0.0936
frame별 detection 수행 시간: 0.0992
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0937
frame별 detection 수행 시간: 0.0952
frame별 detection 수행 시간: 0.0937
frame별 detection 수행 시간: 0.0906
frame별 detection 수행 시간: 0.1034
frame별 detection 수행 시간: 0.0936
frame별 detection 수행 시간: 0.0929
frame별 detection 수행 시간: 0.09
frame별 detection 수행 시간: 0.0968
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0939
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0921
frame별 detection 수행 시간: 0.0952
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.095
frame별 detection 수행 시간: 0.0945
frame별 detection 수행 시간: 0.0929
frame별 detection 수행 시간: 0.0965
frame별 detection 수행 시간: 0.0962
frame별 detection 수행 시간: 0.0951
frame별 detection 수행 시간: 0.0935
frame별 detection 수행 시간: 0.0958
frame별 detection 수행 시간: 0.0943
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0979
frame별 detection 수행 시간: 0.093
frame별 detection 수행 시간: 0.0941
frame별 detection 수행 시간: 0.0983
frame별 detection 수행 시간: 0.0967
frame별 detection 수행 시간: 0.0925
frame별 detection 수행 시간: 0.0944
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.0942
frame별 detection 수행 시간: 0.0961
frame별 detection 수행 시간: 0.1017
frame별 detection 수행 시간: 0.096
frame별 detection 수행 시간: 0.0971
frame별 detection 수행 시간: 0.0948
frame별 detection 수행 시간: 0.095
frame별 detection 수행 시간: 0.0933
frame별 detection 수행 시간: 0.0952
frame별 detection 수행 시간: 0.0907
더 이상 처리할 frame이 없습니다.
최종 detection 완료 수행 시간: 53.1923

 

 

 

 

 

반응형
728x90
반응형

kitti Dataset을 중립 데이터형태로 변환하여 메모리 로드

# 원본 kitti Dataset는 10개의 Class로 되어 있음. 'Car Van Truck Pedestrian Person_sitting Cyclist Tram Misc DontCare'
CLASSES = ('Car', 'Truck', 'Pedestrian', 'Cyclist')
cat2label = {k:i for i, k in enumerate(CLASSES)}
print(cat2label)
cat2label['Car']

# {'Car': 0, 'Truck': 1, 'Pedestrian': 2, 'Cyclist': 3}
# 0
# data_anno {label}에 넣기 위한것
image_list = mmcv.list_from_file('/content/kitti_tiny/train.txt')

lines = mmcv.list_from_file('/content/kitti_tiny/training/label_2/000064.txt')
#print(lines)
content = [line.strip().split(' ') for line in lines]
bbox_names = [x[0] for x in content]
#print(bbox_names)
# bounding box 읽기
bboxes = [ [float(info) for info in x[4:8]] for x in content]
print(bboxes)

# [[657.65, 179.93, 709.86, 219.92], [731.51, 180.39, 882.28, 275.8], [715.18, 175.63, 762.77, 203.9], [816.58, 59.74, 1112.51, 266.07], [626.78, 174.27, 647.77, 192.18], [546.19, 168.97, 554.01, 177.09]]
import copy
import os.path as osp
import cv2

import mmcv
import numpy as np

from mmdet.datasets.builder import DATASETS
from mmdet.datasets.custom import CustomDataset

# 반드시 아래 Decorator 설정 할것.@DATASETS.register_module() 설정 시 force=True를 입력하지 않으면 Dataset 재등록 불가. 
@DATASETS.register_module(force=True)
class KittyTinyDataset(CustomDataset):
  CLASSES = ('Car', 'Truck', 'Pedestrian', 'Cyclist')
  # __init__ 가 없는것은 customdataset것을 이용
  ##### self.data_root: /content/kitti_tiny/ self.ann_file: /content/kitti_tiny/train.txt self.img_prefix: /content/kitti_tiny/training/image_2
  #### ann_file: /content/kitti_tiny/train.txt
  # annotation에 대한 모든 파일명을 가지고 있는 텍스트 파일을 __init__(self, ann_file)로 입력 받고, 이 self.ann_file이 load_annotations()의 인자로 입력
  def load_annotations(self, ann_file):
    print('##### self.data_root:', self.data_root, 'self.ann_file:', self.ann_file, 'self.img_prefix:', self.img_prefix)
    print('#### ann_file:', ann_file)
    cat2label = {k:i for i, k in enumerate(self.CLASSES)}
    image_list = mmcv.list_from_file(self.ann_file)
    # 포맷 중립 데이터를 담을 list 객체
    data_infos = []
    
    for image_id in image_list: # 000000
      filename = '{0:}/{1:}.jpeg'.format(self.img_prefix, image_id)
      # 원본 이미지의 너비, 높이를 image를 직접 로드하여 구함. 
      image = cv2.imread(filename)
      height, width = image.shape[:2]
      # 개별 image의 annotation 정보 저장용 Dict 생성. key값 filename 에는 image의 파일명만 들어감(디렉토리는 제외)
      data_info = {'filename': str(image_id) + '.jpeg',
                   'width': width, 'height': height}
      # 개별 annotation이 있는 서브 디렉토리의 prefix 변환. 
      label_prefix = self.img_prefix.replace('image_2', 'label_2')
      # 개별 annotation 파일을 1개 line 씩 읽어서 list 로드 
      lines = mmcv.list_from_file(osp.join(label_prefix, str(image_id)+'.txt'))

      # 전체 lines를 개별 line별 공백 레벨로 parsing 하여 다시 list로 저장. content는 list의 list형태임.
      # ann 정보는 numpy array로 저장되나 텍스트 처리나 데이터 가공이 list 가 편하므로 일차적으로 list로 변환 수행.   
      content = [line.strip().split(' ') for line in lines]
      # 오브젝트의 클래스명은 bbox_names로 저장. 
      bbox_names = [x[0] for x in content]
      # bbox 좌표를 저장
      bboxes = [ [float(info) for info in x[4:8]] for x in content]

      # 클래스명이 해당 사항이 없는 대상 Filtering out, 'DontCare'sms ignore로 별도 저장.
      gt_bboxes = []
      gt_labels = []
      gt_bboxes_ignore = []
      gt_labels_ignore = []
	  
      # 파일 내용을 읽는 loop
      for bbox_name, bbox in zip(bbox_names, bboxes):
        # 만약 bbox_name이 클래스명에 해당 되면, gt_bboxes와 gt_labels에 추가, 그렇지 않으면 gt_bboxes_ignore, gt_labels_ignore에 추가
        if bbox_name in cat2label:
          gt_bboxes.append(bbox)
          # gt_labels에는 class id를 입력
          gt_labels.append(cat2label[bbox_name])
        else:
          gt_bboxes_ignore.append(bbox)
          gt_labels_ignore.append(-1)
      # 개별 image별 annotation 정보를 가지는 Dict 생성. 해당 Dict의 value값은 모두 np.array임. 
      data_anno = {
          'bboxes': np.array(gt_bboxes, dtype=np.float32).reshape(-1, 4),
          'labels': np.array(gt_labels, dtype=np.long),
          'bboxes_ignore': np.array(gt_bboxes_ignore, dtype=np.float32).reshape(-1, 4),
          'labels_ignore': np.array(gt_labels_ignore, dtype=np.long)
      }
      # image에 대한 메타 정보를 가지는 data_info Dict에 'ann' key값으로 data_anno를 value로 저장. 
      data_info.update(ann=data_anno)
      # 전체 annotation 파일들에 대한 정보를 가지는 data_infos에 data_info Dict를 추가
      data_infos.append(data_info)

    return data_infos

 

### Config 설정하고 Pretrained 모델 다운로드
config_file = '/content/mmdetection/configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py'
checkpoint_file = '/content/mmdetection/checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth'
!cd mmdetection; mkdir checkpoints
!wget -O /content/mmdetection/checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth http://download.openmmlab.com/mmdetection/v2.0/faster_rcnn/faster_rcnn_r50_fpn_1x_coco/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth

 

from mmcv import Config

cfg = Config.fromfile(config_file)
print(cfg.pretty_text)

# model = dict(
    type='FasterRCNN',
    pretrained='torchvision://resnet50',
    backbone=dict(
        type='ResNet',
        depth=50,
        num_stages=4,
        out_indices=(0, 1, 2, 3),
        frozen_stages=1,
        norm_cfg=dict(type='BN', requires_grad=True),
        norm_eval=True,
        style='pytorch'),
    neck=dict(
        type='FPN',
        in_channels=[256, 512, 1024, 2048],
        out_channels=256,
        num_outs=5),
    rpn_head=dict(
        type='RPNHead',
        in_channels=256,
        feat_channels=256,
        anchor_generator=dict(
            type='AnchorGenerator',
            scales=[8],
            ratios=[0.5, 1.0, 2.0],
            strides=[4, 8, 16, 32, 64]),
        bbox_coder=dict(
            type='DeltaXYWHBBoxCoder',
            target_means=[0.0, 0.0, 0.0, 0.0],
            target_stds=[1.0, 1.0, 1.0, 1.0]),
        loss_cls=dict(
            type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),
        loss_bbox=dict(type='L1Loss', loss_weight=1.0)),
    roi_head=dict(
        type='StandardRoIHead',
        bbox_roi_extractor=dict(
            type='SingleRoIExtractor',
            roi_layer=dict(type='RoIAlign', output_size=7, sampling_ratio=0),
            out_channels=256,
            featmap_strides=[4, 8, 16, 32]),
        bbox_head=dict(
            type='Shared2FCBBoxHead',
            in_channels=256,
            fc_out_channels=1024,
            roi_feat_size=7,
            num_classes=80,
            bbox_coder=dict(
                type='DeltaXYWHBBoxCoder',
                target_means=[0.0, 0.0, 0.0, 0.0],
                target_stds=[0.1, 0.1, 0.2, 0.2]),
            reg_class_agnostic=False,
            loss_cls=dict(
                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),
            loss_bbox=dict(type='L1Loss', loss_weight=1.0))),
    train_cfg=dict(
        rpn=dict(
            assigner=dict(
                type='MaxIoUAssigner',
                pos_iou_thr=0.7,
                neg_iou_thr=0.3,
                min_pos_iou=0.3,
                match_low_quality=True,
                ignore_iof_thr=-1),
            sampler=dict(
                type='RandomSampler',
                num=256,
                pos_fraction=0.5,
                neg_pos_ub=-1,
                add_gt_as_proposals=False),
            allowed_border=-1,
            pos_weight=-1,
            debug=False),
        rpn_proposal=dict(
            nms_pre=2000,
            max_per_img=1000,
            nms=dict(type='nms', iou_threshold=0.7),
            min_bbox_size=0),
        rcnn=dict(
            assigner=dict(
                type='MaxIoUAssigner',
                pos_iou_thr=0.5,
                neg_iou_thr=0.5,
                min_pos_iou=0.5,
                match_low_quality=False,
                ignore_iof_thr=-1),
            sampler=dict(
                type='RandomSampler',
                num=512,
                pos_fraction=0.25,
                neg_pos_ub=-1,
                add_gt_as_proposals=True),
            pos_weight=-1,
            debug=False)),
    test_cfg=dict(
        rpn=dict(
            nms_pre=1000,
            max_per_img=1000,
            nms=dict(type='nms', iou_threshold=0.7),
            min_bbox_size=0),
        rcnn=dict(
            score_thr=0.05,
            nms=dict(type='nms', iou_threshold=0.5),
            max_per_img=100)))
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',
        mean=[123.675, 116.28, 103.53],
        std=[58.395, 57.12, 57.375],
        to_rgb=True),
    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',
                mean=[123.675, 116.28, 103.53],
                std=[58.395, 57.12, 57.375],
                to_rgb=True),
            dict(type='Pad', size_divisor=32),
            dict(type='ImageToTensor', keys=['img']),
            dict(type='Collect', keys=['img'])
        ])
]
data = dict(
    samples_per_gpu=2,
    workers_per_gpu=2,
    train=dict(
        type='CocoDataset',
        ann_file='data/coco/annotations/instances_train2017.json',
        img_prefix='data/coco/train2017/',
        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',
                mean=[123.675, 116.28, 103.53],
                std=[58.395, 57.12, 57.375],
                to_rgb=True),
            dict(type='Pad', size_divisor=32),
            dict(type='DefaultFormatBundle'),
            dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
        ]),
    val=dict(
        type='CocoDataset',
        ann_file='data/coco/annotations/instances_val2017.json',
        img_prefix='data/coco/val2017/',
        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',
                        mean=[123.675, 116.28, 103.53],
                        std=[58.395, 57.12, 57.375],
                        to_rgb=True),
                    dict(type='Pad', size_divisor=32),
                    dict(type='ImageToTensor', keys=['img']),
                    dict(type='Collect', keys=['img'])
                ])
        ]),
    test=dict(
        type='CocoDataset',
        ann_file='data/coco/annotations/instances_val2017.json',
        img_prefix='data/coco/val2017/',
        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',
                        mean=[123.675, 116.28, 103.53],
                        std=[58.395, 57.12, 57.375],
                        to_rgb=True),
                    dict(type='Pad', size_divisor=32),
                    dict(type='ImageToTensor', keys=['img']),
                    dict(type='Collect', keys=['img'])
                ])
        ]))
evaluation = dict(interval=1, metric='bbox')
optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)
optimizer_config = dict(grad_clip=None)
lr_config = dict(
    policy='step',
    warmup='linear',
    warmup_iters=500,
    warmup_ratio=0.001,
    step=[8, 11])
runner = dict(type='EpochBasedRunner', max_epochs=12)
checkpoint_config = dict(interval=1)
log_config = dict(interval=50, hooks=[dict(type='TextLoggerHook')])
custom_hooks = [dict(type='NumClassCheckHook')]
dist_params = dict(backend='nccl')
log_level = 'INFO'
load_from = None
resume_from = None
workflow = [('train', 1)]

 

from mmdet.apis import set_random_seed

# dataset에 대한 환경 파라미터 수정. 
cfg.dataset_type = 'KittyTinyDataset'
cfg.data_root = '/content/kitti_tiny/'

# train, val, test dataset에 대한 type, data_root, ann_file, img_prefix 환경 파라미터 수정. 
cfg.data.train.type = 'KittyTinyDataset'
cfg.data.train.data_root = '/content/kitti_tiny/'
cfg.data.train.ann_file = 'train.txt'
cfg.data.train.img_prefix = 'training/image_2'

cfg.data.val.type = 'KittyTinyDataset'
cfg.data.val.data_root = '/content/kitti_tiny/'
cfg.data.val.ann_file = 'val.txt'
cfg.data.val.img_prefix = 'training/image_2'

cfg.data.test.type = 'KittyTinyDataset'
cfg.data.test.data_root = '/content/kitti_tiny/'
cfg.data.test.ann_file = 'val.txt'
cfg.data.test.img_prefix = 'training/image_2'

# class의 갯수 수정. 
cfg.model.roi_head.bbox_head.num_classes = 4
# pretrained 모델
cfg.load_from = 'checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth'

# 학습 weight 파일로 로그를 저장하기 위한 디렉토리 설정. 
cfg.work_dir = './tutorial_exps'

# 학습율 변경 환경 파라미터 설정. 
cfg.optimizer.lr = 0.02 / 8

cfg.lr_config.warmup = None
cfg.log_config.interval = 10

# config 수행 시마다 policy값이 없어지는 bug로 인하여 설정. 
cfg.lr_config.policy = 'step'

# Change the evaluation metric since we use customized dataset.
cfg.evaluation.metric = 'mAP'
# We can set the evaluation interval to reduce the evaluation times
cfg.evaluation.interval = 12
# We can set the checkpoint saving interval to reduce the storage cost
cfg.checkpoint_config.interval = 12

# Set seed thus the results are more reproducible
cfg.seed = 0
set_random_seed(0, deterministic=False)
cfg.gpu_ids = range(1)


# We can initialize the logger for training and have a look
# at the final config used for training
print(f'Config:\n{cfg.pretty_text}')



# Config:
model = dict(
    type='FasterRCNN',
    pretrained='torchvision://resnet50',
    backbone=dict(
        type='ResNet',
        depth=50,
        num_stages=4,
        out_indices=(0, 1, 2, 3),
        frozen_stages=1,
        norm_cfg=dict(type='BN', requires_grad=True),
        norm_eval=True,
        style='pytorch',
        pretrained='torchvision://resnet50'),
    neck=dict(
        type='FPN',
        in_channels=[256, 512, 1024, 2048],
        out_channels=256,
        num_outs=5),
    rpn_head=dict(
        type='RPNHead',
        in_channels=256,
        feat_channels=256,
        anchor_generator=dict(
            type='AnchorGenerator',
            scales=[8],
            ratios=[0.5, 1.0, 2.0],
            strides=[4, 8, 16, 32, 64]),
        bbox_coder=dict(
            type='DeltaXYWHBBoxCoder',
            target_means=[0.0, 0.0, 0.0, 0.0],
            target_stds=[1.0, 1.0, 1.0, 1.0]),
        loss_cls=dict(
            type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),
        loss_bbox=dict(type='L1Loss', loss_weight=1.0)),
    roi_head=dict(
        type='StandardRoIHead',
        bbox_roi_extractor=dict(
            type='SingleRoIExtractor',
            roi_layer=dict(type='RoIAlign', output_size=7, sampling_ratio=0),
            out_channels=256,
            featmap_strides=[4, 8, 16, 32]),
        bbox_head=dict(
            type='Shared2FCBBoxHead',
            in_channels=256,
            fc_out_channels=1024,
            roi_feat_size=7,
            num_classes=4,
            bbox_coder=dict(
                type='DeltaXYWHBBoxCoder',
                target_means=[0.0, 0.0, 0.0, 0.0],
                target_stds=[0.1, 0.1, 0.2, 0.2]),
            reg_class_agnostic=False,
            loss_cls=dict(
                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),
            loss_bbox=dict(type='L1Loss', loss_weight=1.0)),
        train_cfg=dict(
            assigner=dict(
                type='MaxIoUAssigner',
                pos_iou_thr=0.5,
                neg_iou_thr=0.5,
                min_pos_iou=0.5,
                match_low_quality=False,
                ignore_iof_thr=-1),
            sampler=dict(
                type='RandomSampler',
                num=512,
                pos_fraction=0.25,
                neg_pos_ub=-1,
                add_gt_as_proposals=True),
            pos_weight=-1,
            debug=False),
        test_cfg=dict(
            score_thr=0.05,
            nms=dict(type='nms', iou_threshold=0.5),
            max_per_img=100),
        pretrained='torchvision://resnet50'),
    train_cfg=dict(
        rpn=dict(
            assigner=dict(
                type='MaxIoUAssigner',
                pos_iou_thr=0.7,
                neg_iou_thr=0.3,
                min_pos_iou=0.3,
                match_low_quality=True,
                ignore_iof_thr=-1),
            sampler=dict(
                type='RandomSampler',
                num=256,
                pos_fraction=0.5,
                neg_pos_ub=-1,
                add_gt_as_proposals=False),
            allowed_border=-1,
            pos_weight=-1,
            debug=False),
        rpn_proposal=dict(
            nms_pre=2000,
            max_per_img=1000,
            nms=dict(type='nms', iou_threshold=0.7),
            min_bbox_size=0),
        rcnn=dict(
            assigner=dict(
                type='MaxIoUAssigner',
                pos_iou_thr=0.5,
                neg_iou_thr=0.5,
                min_pos_iou=0.5,
                match_low_quality=False,
                ignore_iof_thr=-1),
            sampler=dict(
                type='RandomSampler',
                num=512,
                pos_fraction=0.25,
                neg_pos_ub=-1,
                add_gt_as_proposals=True),
            pos_weight=-1,
            debug=False)),
    test_cfg=dict(
        rpn=dict(
            nms_pre=1000,
            max_per_img=1000,
            nms=dict(type='nms', iou_threshold=0.7),
            min_bbox_size=0),
        rcnn=dict(
            score_thr=0.05,
            nms=dict(type='nms', iou_threshold=0.5),
            max_per_img=100)))
dataset_type = 'KittyTinyDataset'
data_root = '/content/kitti_tiny/'
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',
        mean=[123.675, 116.28, 103.53],
        std=[58.395, 57.12, 57.375],
        to_rgb=True),
    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',
                mean=[123.675, 116.28, 103.53],
                std=[58.395, 57.12, 57.375],
                to_rgb=True),
            dict(type='Pad', size_divisor=32),
            dict(type='ImageToTensor', keys=['img']),
            dict(type='Collect', keys=['img'])
        ])
]
data = dict(
    samples_per_gpu=2,
    workers_per_gpu=2,
    train=dict(
        type='KittyTinyDataset',
        ann_file='train.txt',
        img_prefix='training/image_2',
        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',
                mean=[123.675, 116.28, 103.53],
                std=[58.395, 57.12, 57.375],
                to_rgb=True),
            dict(type='Pad', size_divisor=32),
            dict(type='DefaultFormatBundle'),
            dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
        ],
        data_root='/content/kitti_tiny/'),
    val=dict(
        type='KittyTinyDataset',
        ann_file='val.txt',
        img_prefix='training/image_2',
        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',
                        mean=[123.675, 116.28, 103.53],
                        std=[58.395, 57.12, 57.375],
                        to_rgb=True),
                    dict(type='Pad', size_divisor=32),
                    dict(type='ImageToTensor', keys=['img']),
                    dict(type='Collect', keys=['img'])
                ])
        ],
        data_root='/content/kitti_tiny/'),
    test=dict(
        type='KittyTinyDataset',
        ann_file='val.txt',
        img_prefix='training/image_2',
        pipeline=[
            dict(type='LoadImageFromWebcam'),
            dict(
                type='MultiScaleFlipAug',
                img_scale=(1333, 800),
                flip=False,
                transforms=[
                    dict(type='Resize', keep_ratio=True),
                    dict(type='RandomFlip'),
                    dict(
                        type='Normalize',
                        mean=[123.675, 116.28, 103.53],
                        std=[58.395, 57.12, 57.375],
                        to_rgb=True),
                    dict(type='Pad', size_divisor=32),
                    dict(type='DefaultFormatBundle'),
                    dict(type='Collect', keys=['img'])
                ])
        ],
        data_root='/content/kitti_tiny/'))
evaluation = dict(interval=12, metric='mAP', by_epoch=True)
optimizer = dict(type='SGD', lr=0.0025, momentum=0.9, weight_decay=0.0001)
optimizer_config = dict(grad_clip=None, type='OptimizerHook')
lr_config = dict(
    warmup=None,
    warmup_iters=500,
    warmup_ratio=0.001,
    step=[8, 11],
    type='StepLrUpdaterHook',
    policy='step')
runner = dict(type='EpochBasedRunner', max_epochs=12)
checkpoint_config = dict(interval=12, type='CheckpointHook')
log_config = dict(interval=10, hooks=[dict(type='TextLoggerHook')])
custom_hooks = [dict(type='NumClassCheckHook')]
dist_params = dict(backend='nccl')
log_level = 'INFO'
load_from = 'checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth'
resume_from = None
workflow = [('train', 1)]
work_dir = './tutorial_exps'
seed = 0
gpu_ids = range(0, 1)

Config에서 설정한 Dataset과 Model, 동적 학습율, Pipeline 설정에 따라 모델 학습 수행.

  • train용 Dataset을 생성하고 이를 이용하여 학습 수행.
from mmdet.datasets import build_dataset
from mmdet.models import build_detector
from mmdet.apis import train_detector

# train용 Dataset 생성. 
datasets = [build_dataset(cfg.data.train)]
datasets

# [
#  KittyTinyDataset Train dataset with number of images 50, and instance counts: 
#  +----------+-------+-----------+-------+----------------+-------+-------------+-------+---------------+-------+
#  | category | count | category  | count | category       | count | category    | count | category      | count |
#  +----------+-------+-----------+-------+----------------+-------+-------------+-------+---------------+-------+
#  | 0 [Car]  | 147   | 1 [Truck] | 7     | 2 [Pedestrian] | 23    | 3 [Cyclist] | 7     | -1 background | 0     |
#  +----------+-------+-----------+-------+----------------+-------+-------------+-------+---------------+-------+]
datasets[0].CLASSES
# ('Car', 'Truck', 'Pedestrian', 'Cyclist')
model = build_detector(cfg.model, train_cfg=cfg.get('train_cfg'), test_cfg=cfg.get('test_cfg'))
model.CLASSES = datasets[0].CLASSES

# /usr/local/lib/python3.7/dist-packages/mmdet-2.12.0-py3.7.egg/mmdet/models/backbones/resnet.py:400: UserWarning: DeprecationWarning: pretrained is a deprecated, please use "init_cfg" instead
#  warnings.warn('DeprecationWarning: pretrained is a deprecated, '
# 주의, config에 pretrained 모델 지정이 상대 경로로 설정됨 cfg.load_from = 'checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth'
# 아래와 같이 %cd mmdetection 지정 필요. 
 
%cd mmdetection 

mmcv.mkdir_or_exist(osp.abspath(cfg.work_dir))
# epochs는 config의 runner 파라미터로 지정됨. 기본 12회 
train_detector(model, datasets, cfg, distributed=False, validate=True)



/content/mmdetection
2021-05-27 02:01:03,488 - mmdet - INFO - load checkpoint from checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth
2021-05-27 02:01:03,489 - mmdet - INFO - Use load_from_local loader
##### self.data_root: /content/kitti_tiny/ self.ann_file: /content/kitti_tiny/val.txt self.img_prefix: /content/kitti_tiny/training/image_2
#### ann_file: /content/kitti_tiny/val.txt
2021-05-27 02:01:03,630 - mmdet - WARNING - The model and loaded state dict do not match exactly

size mismatch for roi_head.bbox_head.fc_cls.weight: copying a param with shape torch.Size([81, 1024]) from checkpoint, the shape in current model is torch.Size([5, 1024]).
size mismatch for roi_head.bbox_head.fc_cls.bias: copying a param with shape torch.Size([81]) from checkpoint, the shape in current model is torch.Size([5]).
size mismatch for roi_head.bbox_head.fc_reg.weight: copying a param with shape torch.Size([320, 1024]) from checkpoint, the shape in current model is torch.Size([16, 1024]).
size mismatch for roi_head.bbox_head.fc_reg.bias: copying a param with shape torch.Size([320]) from checkpoint, the shape in current model is torch.Size([16]).
2021-05-27 02:01:03,639 - mmdet - INFO - Start running, host: root@d7fd648a5af0, work_dir: /content/mmdetection/tutorial_exps
2021-05-27 02:01:03,640 - mmdet - INFO - workflow: [('train', 1)], max: 12 epochs
2021-05-27 02:01:08,457 - mmdet - INFO - Epoch [1][10/25]	lr: 2.500e-03, eta: 0:02:18, time: 0.476, data_time: 0.229, memory: 2226, loss_rpn_cls: 0.0275, loss_rpn_bbox: 0.0179, loss_cls: 0.7554, acc: 73.3594, loss_bbox: 0.4131, loss: 1.2139
2021-05-27 02:01:10,877 - mmdet - INFO - Epoch [1][20/25]	lr: 2.500e-03, eta: 0:01:40, time: 0.242, data_time: 0.012, memory: 2226, loss_rpn_cls: 0.0178, loss_rpn_bbox: 0.0128, loss_cls: 0.2395, acc: 92.2559, loss_bbox: 0.3446, loss: 0.6147
2021-05-27 02:01:16,800 - mmdet - INFO - Epoch [2][10/25]	lr: 2.500e-03, eta: 0:01:29, time: 0.464, data_time: 0.228, memory: 2226, loss_rpn_cls: 0.0151, loss_rpn_bbox: 0.0156, loss_cls: 0.2097, acc: 93.5547, loss_bbox: 0.3205, loss: 0.5609
2021-05-27 02:01:19,231 - mmdet - INFO - Epoch [2][20/25]	lr: 2.500e-03, eta: 0:01:20, time: 0.243, data_time: 0.012, memory: 2226, loss_rpn_cls: 0.0133, loss_rpn_bbox: 0.0131, loss_cls: 0.1617, acc: 94.0332, loss_bbox: 0.2242, loss: 0.4123
2021-05-27 02:01:25,113 - mmdet - INFO - Epoch [3][10/25]	lr: 2.500e-03, eta: 0:01:15, time: 0.462, data_time: 0.227, memory: 2226, loss_rpn_cls: 0.0048, loss_rpn_bbox: 0.0117, loss_cls: 0.1387, acc: 95.1465, loss_bbox: 0.1990, loss: 0.3543
2021-05-27 02:01:27,568 - mmdet - INFO - Epoch [3][20/25]	lr: 2.500e-03, eta: 0:01:10, time: 0.246, data_time: 0.012, memory: 2226, loss_rpn_cls: 0.0069, loss_rpn_bbox: 0.0125, loss_cls: 0.1741, acc: 93.4863, loss_bbox: 0.2716, loss: 0.4651
2021-05-27 02:01:33,510 - mmdet - INFO - Epoch [4][10/25]	lr: 2.500e-03, eta: 0:01:05, time: 0.466, data_time: 0.225, memory: 2226, loss_rpn_cls: 0.0071, loss_rpn_bbox: 0.0151, loss_cls: 0.1503, acc: 94.2578, loss_bbox: 0.2479, loss: 0.4204
2021-05-27 02:01:35,960 - mmdet - INFO - Epoch [4][20/25]	lr: 2.500e-03, eta: 0:01:01, time: 0.245, data_time: 0.013, memory: 2226, loss_rpn_cls: 0.0028, loss_rpn_bbox: 0.0123, loss_cls: 0.1339, acc: 95.1172, loss_bbox: 0.2092, loss: 0.3582
2021-05-27 02:01:41,874 - mmdet - INFO - Epoch [5][10/25]	lr: 2.500e-03, eta: 0:00:57, time: 0.466, data_time: 0.226, memory: 2226, loss_rpn_cls: 0.0038, loss_rpn_bbox: 0.0100, loss_cls: 0.1278, acc: 94.9512, loss_bbox: 0.2143, loss: 0.3559
2021-05-27 02:01:44,334 - mmdet - INFO - Epoch [5][20/25]	lr: 2.500e-03, eta: 0:00:53, time: 0.246, data_time: 0.012, memory: 2226, loss_rpn_cls: 0.0071, loss_rpn_bbox: 0.0119, loss_cls: 0.1317, acc: 94.7852, loss_bbox: 0.2035, loss: 0.3542
2021-05-27 02:01:50,296 - mmdet - INFO - Epoch [6][10/25]	lr: 2.500e-03, eta: 0:00:49, time: 0.467, data_time: 0.228, memory: 2226, loss_rpn_cls: 0.0014, loss_rpn_bbox: 0.0094, loss_cls: 0.1039, acc: 96.0059, loss_bbox: 0.1820, loss: 0.2968
2021-05-27 02:01:52,762 - mmdet - INFO - Epoch [6][20/25]	lr: 2.500e-03, eta: 0:00:45, time: 0.247, data_time: 0.012, memory: 2226, loss_rpn_cls: 0.0039, loss_rpn_bbox: 0.0104, loss_cls: 0.1045, acc: 96.0840, loss_bbox: 0.1877, loss: 0.3065
2021-05-27 02:01:58,690 - mmdet - INFO - Epoch [7][10/25]	lr: 2.500e-03, eta: 0:00:41, time: 0.465, data_time: 0.225, memory: 2226, loss_rpn_cls: 0.0019, loss_rpn_bbox: 0.0106, loss_cls: 0.1018, acc: 96.2402, loss_bbox: 0.1835, loss: 0.2978
2021-05-27 02:02:01,159 - mmdet - INFO - Epoch [7][20/25]	lr: 2.500e-03, eta: 0:00:38, time: 0.247, data_time: 0.011, memory: 2226, loss_rpn_cls: 0.0039, loss_rpn_bbox: 0.0125, loss_cls: 0.0970, acc: 96.2500, loss_bbox: 0.1859, loss: 0.2993
2021-05-27 02:02:07,094 - mmdet - INFO - Epoch [8][10/25]	lr: 2.500e-03, eta: 0:00:33, time: 0.464, data_time: 0.225, memory: 2226, loss_rpn_cls: 0.0029, loss_rpn_bbox: 0.0088, loss_cls: 0.0875, acc: 96.6309, loss_bbox: 0.1584, loss: 0.2575
2021-05-27 02:02:09,550 - mmdet - INFO - Epoch [8][20/25]	lr: 2.500e-03, eta: 0:00:30, time: 0.246, data_time: 0.012, memory: 2226, loss_rpn_cls: 0.0020, loss_rpn_bbox: 0.0089, loss_cls: 0.0976, acc: 96.4160, loss_bbox: 0.1765, loss: 0.2850
2021-05-27 02:02:15,504 - mmdet - INFO - Epoch [9][10/25]	lr: 2.500e-04, eta: 0:00:26, time: 0.466, data_time: 0.225, memory: 2226, loss_rpn_cls: 0.0029, loss_rpn_bbox: 0.0093, loss_cls: 0.0829, acc: 96.8457, loss_bbox: 0.1472, loss: 0.2423
2021-05-27 02:02:17,968 - mmdet - INFO - Epoch [9][20/25]	lr: 2.500e-04, eta: 0:00:23, time: 0.246, data_time: 0.013, memory: 2226, loss_rpn_cls: 0.0012, loss_rpn_bbox: 0.0071, loss_cls: 0.0760, acc: 97.2168, loss_bbox: 0.1358, loss: 0.2201
2021-05-27 02:02:23,924 - mmdet - INFO - Epoch [10][10/25]	lr: 2.500e-04, eta: 0:00:19, time: 0.466, data_time: 0.226, memory: 2226, loss_rpn_cls: 0.0027, loss_rpn_bbox: 0.0095, loss_cls: 0.0899, acc: 96.4160, loss_bbox: 0.1554, loss: 0.2575
2021-05-27 02:02:26,391 - mmdet - INFO - Epoch [10][20/25]	lr: 2.500e-04, eta: 0:00:15, time: 0.247, data_time: 0.012, memory: 2226, loss_rpn_cls: 0.0013, loss_rpn_bbox: 0.0064, loss_cls: 0.0731, acc: 97.2168, loss_bbox: 0.1324, loss: 0.2132
2021-05-27 02:02:32,334 - mmdet - INFO - Epoch [11][10/25]	lr: 2.500e-04, eta: 0:00:11, time: 0.465, data_time: 0.225, memory: 2226, loss_rpn_cls: 0.0037, loss_rpn_bbox: 0.0084, loss_cls: 0.0911, acc: 96.3965, loss_bbox: 0.1458, loss: 0.2490
2021-05-27 02:02:34,811 - mmdet - INFO - Epoch [11][20/25]	lr: 2.500e-04, eta: 0:00:08, time: 0.248, data_time: 0.012, memory: 2226, loss_rpn_cls: 0.0012, loss_rpn_bbox: 0.0087, loss_cls: 0.0703, acc: 97.3047, loss_bbox: 0.1367, loss: 0.2168
2021-05-27 02:02:40,779 - mmdet - INFO - Epoch [12][10/25]	lr: 2.500e-05, eta: 0:00:04, time: 0.469, data_time: 0.226, memory: 2226, loss_rpn_cls: 0.0016, loss_rpn_bbox: 0.0065, loss_cls: 0.0630, acc: 97.5586, loss_bbox: 0.1168, loss: 0.1879
2021-05-27 02:02:43,234 - mmdet - INFO - Epoch [12][20/25]	lr: 2.500e-05, eta: 0:00:01, time: 0.245, data_time: 0.013, memory: 2226, loss_rpn_cls: 0.0016, loss_rpn_bbox: 0.0070, loss_cls: 0.0700, acc: 97.2949, loss_bbox: 0.1068, loss: 0.1853
[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>] 25/25, 13.7 task/s, elapsed: 2s, ETA:     0s
---------------iou_thr: 0.5---------------
2021-05-27 02:02:46,577 - mmdet - INFO - 
+------------+-----+------+--------+-------+
| class      | gts | dets | recall | ap    |
+------------+-----+------+--------+-------+
| Car        | 62  | 145  | 0.935  | 0.829 |
| Truck      | 3   | 16   | 1.000  | 0.600 |
| Pedestrian | 13  | 49   | 0.923  | 0.781 |
| Cyclist    | 7   | 51   | 0.714  | 0.180 |
+------------+-----+------+--------+-------+
| mAP        |     |      |        | 0.598 |
+------------+-----+------+--------+-------+
2021-05-27 02:02:46,581 - mmdet - INFO - Saving checkpoint at 12 epochs
2021-05-27 02:02:47,549 - mmdet - INFO - Epoch(val) [12][25]	AP50: 0.5980, mAP: 0.5975

학습된 model을 이용하여 inference 수행.

from mmdet.apis import inference_detector, init_detector, show_result_pyplot

# BGR Image 사용 
img = cv2.imread('/content/kitti_tiny/training/image_2/000068.jpeg')

model.cfg = cfg

result = inference_detector(model, img)
show_result_pyplot(model, img, result)

 

 

반응형
728x90
반응형
# https://github.com/open-mmlab/mmdetection/blob/master/demo/MMDet_Tutorial.ipynb 에서 발췌
# mmcv를 위해서 mmcv-full을 먼저 설치해야 함. 
!pip install mmcv-full
# mmdetection 설치 
!git clone https://github.com/open-mmlab/mmdetection.git
!cd mmdetection; python setup.py install
# 아래를 수행하기 전에 kernel을 restart 해야 함. 
from mmdet.apis import init_detector, inference_detector
import mmcv

KITTI Dataset 다운로드

  • 작은 용량의 KITTI Dataset을 다운로드하고 /content 밑에 압축 해제
# 튜토리얼용 dataset
!wget https://download.openmmlab.com/mmdetection/data/kitti_tiny.zip
!unzip kitti_tiny.zip > /dev/null
import matplotlib.pyplot as plt
import cv2

img = cv2.cvtColor(cv2.imread('/content/kitti_tiny/training/image_2/000068.jpeg'), cv2.COLOR_BGR2RGB)
plt.figure(figsize=(15, 10))
plt.imshow(img)

KITTI DATA FORMAT 확인

  • 첫번째 컬럼은 해당 오브젝트의 클래스 명.
  • 5번째~8번째가 BOUNDING BOX 정보임. 좌상단(xmin, ymin), 우하단(xmax, ymax) 좌표 임.
!cat /content/kitti_tiny/training/label_2/000068.txt

# Car 0.25 0 1.94 69.26 200.28 435.08 374.00 1.46 1.62 4.04 -3.00 1.79 6.98 1.55
# Car 0.80 1 2.26 0.00 209.20 198.59 374.00 1.46 1.58 3.72 -5.44 1.85 6.22 1.56
# Cyclist 0.97 0 2.34 1210.28 199.77 1241.00 374.00 1.55 0.57 1.73 4.04 1.69 3.57 -3.14
# Car 0.00 2 1.68 478.18 187.68 549.54 249.43 1.57 1.60 3.99 -2.73 2.03 20.96 1.55
# Car 0.00 1 1.66 530.03 187.79 573.10 226.09 1.52 1.54 3.68 -2.53 2.20 31.50 1.58
# Van 0.00 1 1.63 547.61 171.12 584.05 212.41 2.47 1.98 5.81 -2.79 2.41 46.44 1.57
# Car 0.00 1 -0.16 667.74 182.35 790.82 230.38 1.62 1.65 4.14 4.19 1.99 25.95 0.00
# Car 0.00 2 -0.11 657.37 184.48 763.34 221.64 1.55 1.66 4.47 4.35 2.10 32.00 0.02
# Car 0.00 1 -0.01 637.45 180.34 714.44 212.34 1.69 1.76 4.12 3.59 2.12 39.79 0.08
# Van 0.00 1 1.61 572.52 175.02 596.26 199.95 2.13 1.91 6.40 -2.28 2.36 65.43 1.57
# Van 0.00 1 1.77 380.78 167.69 523.29 288.56 1.95 1.75 4.63 -2.89 1.90 14.05 1.57
# Cyclist 0.00 1 1.09 958.95 167.55 1036.88 254.43 1.68 0.53 1.96 7.95 1.59 14.95 1.57

KITTI annotation 파일들의 리스트들을 가지는 파일 확인.

!cat /content/kitti_tiny/train.txt
000000
000001
000002
000003
000004
000005
000006
000007
000008
000009
000010
000011
000012
000013
000014
000015
000016
000017
000018
000019
000020
000021
000022
000023
000024
000025
000026
000027
000028
000029
000030
000031
000032
000033
000034
000035
000036
000037
000038
000039
000040
000041
000042
000043
000044
000045
000046
000047
000048
000049

mmdetection의 중립 annotation 포맷 변환. 해당 포맷은 텍스트로 변환하지 않음. 바로 메모리 상의 list로 생성됨.

filename, width, height, ann을 Key로 가지는 Dictionary를 이미지 개수대로 가지는 list 생성.

  • filename: 이미지 파일명(디렉토리는 포함하지 않음)
  • width: 이미지 너비
  • height: 이미지 높이
  • ann: bbounding box와 label에 대한 정보를 가지는 Dictionary
    • bboxes: 하나의 이미지에 있는 여러 Object 들의 numpy array. 4개의 좌표값(좌상단, 우하단)을 가지고, 해당 이미지에 n개의 Object들이 있을 경우 array의 shape는 (n, 4)
    • labels: 하나의 이미지에 있는 여러 Object들의 numpy array. shape는 (n, )
    • bboxes_ignore: 학습에 사용되지 않고 무시하는 bboxes. 무시하는 bboxes의 개수가 k개이면 shape는 (k, 4)
    • labels_ignore: 학습에 사용되지 않고 무시하는 labels. 무시하는 bboxes의 개수가 k개이면 shape는 (k,)

kitti Dataset을 중립 데이터형태로 변환하여 메모리 로드

 

# 원본 kitti Dataset는 10개의 Class로 되어 있음. 'Car Van Truck Pedestrian Person_sitting Cyclist Tram Misc DontCare'
CLASSES = ('Car', 'Truck', 'Pedestrian', 'Cyclist')
cat2label = {k:i for i, k in enumerate(CLASSES)}
print(cat2label)
cat2label['Car']

# {'Car': 0, 'Truck': 1, 'Pedestrian': 2, 'Cyclist': 3}
# 0
image_list = mmcv.list_from_file('/content/kitti_tiny/train.txt')

lines = mmcv.list_from_file('/content/kitti_tiny/training/label_2/000064.txt')
#print(lines)
content = [line.strip().split(' ') for line in lines]
bbox_names = [x[0] for x in content]
#print(bbox_names)
bboxes = [ [float(info) for info in x[4:8]] for x in content]
print(bboxes)

# [[657.65, 179.93, 709.86, 219.92], [731.51, 180.39, 882.28, 275.8], [715.18, 175.63, 762.77, 203.9], [816.58, 59.74, 1112.51, 266.07], [626.78, 174.27, 647.77, 192.18], [546.19, 168.97, 554.01, 177.09]]

dataset, config의 관계를 이해하는 것이 가장 중요하다.

custom dataset 생성 주요 로직

0. dataset을 위한 config 설정(data_root, ann_file, img_prefix)

- build_dataset()으로 아래 작업해줌

1. customdataset객체를 mmdetection framework에 등록

- @DATASETS.register_module(force=True) customdataset을 상속한 클래스 생성

- load_annotations()을 재정의 하여 middle format으로 원본 소스 변환

2. config에 설정된 주요값으로 customdataset 객체 생성

import copy
import os.path as osp
import cv2

import mmcv
import numpy as np

from mmdet.datasets.builder import DATASETS
from mmdet.datasets.custom import CustomDataset

# 반드시 아래 Decorator 설정 할것.@DATASETS.register_module() 설정 시 force=True를 입력하지 않으면 Dataset 재등록 불가. 
@DATASETS.register_module(force=True)
class KittyTinyDataset(CustomDataset):
  CLASSES = ('Car', 'Truck', 'Pedestrian', 'Cyclist')
  
  ##### self.data_root: /content/kitti_tiny/ self.ann_file: /content/kitti_tiny/train.txt self.img_prefix: /content/kitti_tiny/training/image_2
  #### ann_file: /content/kitti_tiny/train.txt
  # annotation에 대한 모든 파일명을 가지고 있는 텍스트 파일을 __init__(self, ann_file)로 입력 받고, 이 self.ann_file이 load_annotations()의 인자로 입력
  def load_annotations(self, ann_file):
    print('##### self.data_root:', self.data_root, 'self.ann_file:', self.ann_file, 'self.img_prefix:', self.img_prefix)
    print('#### ann_file:', ann_file)
    cat2label = {k:i for i, k in enumerate(self.CLASSES)}
    image_list = mmcv.list_from_file(self.ann_file)
    # 포맷 중립 데이터를 담을 list 객체
    data_infos = []
    
    for image_id in image_list:
      filename = '{0:}/{1:}.jpeg'.format(self.img_prefix, image_id)
      # 원본 이미지의 너비, 높이를 image를 직접 로드하여 구함. 
      image = cv2.imread(filename)
      height, width = image.shape[:2]
      # 개별 image의 annotation 정보 저장용 Dict 생성. key값 filename 에는 image의 파일명만 들어감(디렉토리는 제외)
      data_info = {'filename': str(image_id) + '.jpeg',
                   'width': width, 'height': height}
      # 개별 annotation이 있는 서브 디렉토리의 prefix 변환. 
      label_prefix = self.img_prefix.replace('image_2', 'label_2')
      # 개별 annotation 파일을 1개 line 씩 읽어서 list 로드 
      lines = mmcv.list_from_file(osp.join(label_prefix, str(image_id)+'.txt'))

      # 전체 lines를 개별 line별 공백 레벨로 parsing 하여 다시 list로 저장. content는 list의 list형태임.
      # ann 정보는 numpy array로 저장되나 텍스트 처리나 데이터 가공이 list 가 편하므로 일차적으로 list로 변환 수행.   
      content = [line.strip().split(' ') for line in lines]
      # 오브젝트의 클래스명은 bbox_names로 저장. 
      bbox_names = [x[0] for x in content]
      # bbox 좌표를 저장
      bboxes = [ [float(info) for info in x[4:8]] for x in content]

      # 클래스명이 해당 사항이 없는 대상 Filtering out, 'DontCare'sms ignore로 별도 저장.
      gt_bboxes = []
      gt_labels = []
      gt_bboxes_ignore = []
      gt_labels_ignore = []

      for bbox_name, bbox in zip(bbox_names, bboxes):
        # 만약 bbox_name이 클래스명에 해당 되면, gt_bboxes와 gt_labels에 추가, 그렇지 않으면 gt_bboxes_ignore, gt_labels_ignore에 추가
        if bbox_name in cat2label:
          gt_bboxes.append(bbox)
          # gt_labels에는 class id를 입력
          gt_labels.append(cat2label[bbox_name])
        else:
          gt_bboxes_ignore.append(bbox)
          gt_labels_ignore.append(-1)
      # 개별 image별 annotation 정보를 가지는 Dict 생성. 해당 Dict의 value값은 모두 np.array임. 
      data_anno = {
          'bboxes': np.array(gt_bboxes, dtype=np.float32).reshape(-1, 4),
          'labels': np.array(gt_labels, dtype=np.long),
          'bboxes_ignore': np.array(gt_bboxes_ignore, dtype=np.float32).reshape(-1, 4),
          'labels_ignore': np.array(gt_labels_ignore, dtype=np.long)
      }
      # image에 대한 메타 정보를 가지는 data_info Dict에 'ann' key값으로 data_anno를 value로 저장. 
      data_info.update(ann=data_anno)
      # 전체 annotation 파일들에 대한 정보를 가지는 data_infos에 data_info Dict를 추가
      data_infos.append(data_info)

    return data_infos

data_root, ann_file, img_prefix의 활용

- 학습용, 검증용, 테스트용으로 dataset이 만들어져야한다.

소스 데이터들의 학습용, 검증용, 테스트용 분리유형

- image 들과 annotation파일이 학습용, 검증용, 테스트용 디렉토리에 별도로 분리

- 별도의 메타 파일에서 각 image, annotation 지정

- image들 각 용도에 맞게 디렉토리별 분리, annotation은 각 용도별 하나만 가짐(3개 json)

* img_prefix는 여러개의 image들을 포함할 수 있는 디렉토리 형태로 지정되지만, ann_file은 단하나만 지정할 수 있음

# 학습 data config 셋팅
train.data_root=/content/kitti_tiny
train.ann_file='train.txt'
train.img_prefix='training/image_2'

# 학습 kitti data config 셋팅

train_dataset = kittiYinydataset(ann_file = train.data_root,
				data_root = train.ann_file,
				img_prefix = train.img_prefix )

 

 

 

 

 

 

 

반응형
728x90
반응형

mmdetection의 주요구성요소

dataset을 model에 입력시켜야 함.

model을 weight값을 갱신하면서 고도화시켜야함

dataset에는 image, detection을 위한 annotation이 있고, dataset config file에 저장이 되어있음.

 전체적으로 config 파일에 의해서 통제가 됨.

 

dataset의 변환도 중요함

pv, coco 등 많은 dataset이 있는데 이것을 mmdetection이 받아들이기 쉽게 transformation해야 함.

 

mmdetection dataset 지원

=> mmdetection은 다양한 유형의 dataset을 변환 클래스를 통해서 지원함

custom dataset, cocodataset, vocdataset, widerfaceDataset, XMLdataset 중

customdataset, cocodataset이 쉽게 적용될 수 있는 dataset임

 

pascal voc 데이터 세트 특징

ds_name = 'voc07'으로 pascal 형식을 그대로 따름

VOCdevkit - voc2012 - annotations, imageset, jpegimage, segmentationclass, segmentationobject

=> 디렉토리 의 구조를 맞춰줘야함. 차라리 custom dataset 을 parsing 하는게 나음

 

ms-coco 데이터 세트 특징

모든 이미지들에 대해 단 1개의 annotation 파일을 가짐

train, val, test전부 json 포맷인 한개의 파일, 한 라인으로 구성됨

json { info, license,

images {id, file_name, width, height},

annotations {image, object id, segmentation, bounding box, pixel area},

categories (80개 object categories 에 대한 id, names, group)

}

 

custom dataset에 사용되는 포멧

- 모든 이미지에 대한 annotation정보들을 list객체로 가짐

- list 내 개별 원소는 dict로 구성되면 개별 dict는 1개 이미지에 대한 annotation 정보를 가짐

- 1개 이미지는 여러개의 object bbox와 labels annotation 정보들을 개별 dict로 가짐

- 1개 이미지의 object bbox와 2차원 array로 , label은 1차원 array로 구성됨.

 

반응형
728x90
반응형

Video Inference 수행

  • mmdetection의 video_demo.py 대로 Video inference 수행시 image 처리 시간이 상대적으로 오래 걸림.
  • 이미지 처리 로직을 변경하여 적용
!wget -O /content/data/John_Wick_small.mp4 https://github.com/chulminkw/DLCV/blob/master/data/video/John_Wick_small.mp4?raw=true
from mmdet.apis import init_detector, inference_detector
import mmcv

config_file = '/content/mmdetection/configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py'
checkpoint_file = '/content/mmdetection/checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth'
model = init_detector(config_file, checkpoint_file, device='cuda:0')
# https://github.com/open-mmlab/mmdetection/blob/master/demo/video_demo.py 대로 video detection 수행. 

import cv2

video_reader = mmcv.VideoReader('/content/data/John_Wick_small.mp4')
video_writer = None
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
video_writer = cv2.VideoWriter('/content/data/John_Wick_small_out1.mp4', fourcc, video_reader.fps,(video_reader.width, video_reader.height))

for frame in mmcv.track_iter_progress(video_reader):
  result = inference_detector(model, frame)
  frame = model.show_result(frame, result, score_thr=0.4)

  video_writer.write(frame)

if video_writer:
        video_writer.release()

Custom된 frame처리 로직을 적용하여 Video Inference 수행.

  • 기존에 사용한 get_detected_img()를 그대로 사용함.
# model과 원본 이미지 array, filtering할 기준 class confidence score를 인자로 가지는 inference 시각화용 함수 생성. 
import numpy as np

# 0부터 순차적으로 클래스 매핑된 label 적용. 
labels_to_names_seq = {0:'person',1:'bicycle',2:'car',3:'motorbike',4:'aeroplane',5:'bus',6:'train',7:'truck',8:'boat',9:'traffic light',10:'fire hydrant',
                        11:'stop sign',12:'parking meter',13:'bench',14:'bird',15:'cat',16:'dog',17:'horse',18:'sheep',19:'cow',20:'elephant',
                        21:'bear',22:'zebra',23:'giraffe',24:'backpack',25:'umbrella',26:'handbag',27:'tie',28:'suitcase',29:'frisbee',30:'skis',
                        31:'snowboard',32:'sports ball',33:'kite',34:'baseball bat',35:'baseball glove',36:'skateboard',37:'surfboard',38:'tennis racket',39:'bottle',40:'wine glass',
                        41:'cup',42:'fork',43:'knife',44:'spoon',45:'bowl',46:'banana',47:'apple',48:'sandwich',49:'orange',50:'broccoli',
                        51:'carrot',52:'hot dog',53:'pizza',54:'donut',55:'cake',56:'chair',57:'sofa',58:'pottedplant',59:'bed',60:'diningtable',
                        61:'toilet',62:'tvmonitor',63:'laptop',64:'mouse',65:'remote',66:'keyboard',67:'cell phone',68:'microwave',69:'oven',70:'toaster',
                        71:'sink',72:'refrigerator',73:'book',74:'clock',75:'vase',76:'scissors',77:'teddy bear',78:'hair drier',79:'toothbrush' }

def get_detected_img(model, img_array,  score_threshold=0.3, is_print=True):
  # 인자로 들어온 image_array를 복사. 
  draw_img = img_array.copy()
  bbox_color=(0, 255, 0)
  text_color=(0, 0, 255)

  # model과 image array를 입력 인자로 inference detection 수행하고 결과를 results로 받음. 
  # results는 80개의 2차원 array(shape=(오브젝트갯수, 5))를 가지는 list. 
  results = inference_detector(model, img_array)

  # 80개의 array원소를 가지는 results 리스트를 loop를 돌면서 개별 2차원 array들을 추출하고 이를 기반으로 이미지 시각화 
  # results 리스트의 위치 index가 바로 COCO 매핑된 Class id. 여기서는 result_ind가 class id
  # 개별 2차원 array에 오브젝트별 좌표와 class confidence score 값을 가짐. 
  for result_ind, result in enumerate(results):
    # 개별 2차원 array의 row size가 0 이면 해당 Class id로 값이 없으므로 다음 loop로 진행. 
    if len(result) == 0:
      continue
    
    # 2차원 array에서 5번째 컬럼에 해당하는 값이 score threshold이며 이 값이 함수 인자로 들어온 score_threshold 보다 낮은 경우는 제외. 
    result_filtered = result[np.where(result[:, 4] > score_threshold)]
    
    # 해당 클래스 별로 Detect된 여러개의 오브젝트 정보가 2차원 array에 담겨 있으며, 이 2차원 array를 row수만큼 iteration해서 개별 오브젝트의 좌표값 추출. 
    for i in range(len(result_filtered)):
      # 좌상단, 우하단 좌표 추출. 
      left = int(result_filtered[i, 0])
      top = int(result_filtered[i, 1])
      right = int(result_filtered[i, 2])
      bottom = int(result_filtered[i, 3])
      caption = "{}: {:.4f}".format(labels_to_names_seq[result_ind], result_filtered[i, 4])
      cv2.rectangle(draw_img, (left, top), (right, bottom), color=bbox_color, thickness=2)
      cv2.putText(draw_img, caption, (int(left), int(top - 7)), cv2.FONT_HERSHEY_SIMPLEX, 0.37, text_color, 1)
      if is_print:
        print(caption)

  return draw_img
import time

def do_detected_video(model, input_path, output_path, score_threshold, do_print=True):
    
    cap = cv2.VideoCapture(input_path)

    codec = cv2.VideoWriter_fourcc(*'XVID')

    vid_size = (round(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),round(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
    vid_fps = cap.get(cv2.CAP_PROP_FPS)

    vid_writer = cv2.VideoWriter(output_path, codec, vid_fps, vid_size) 

    frame_cnt = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    print('총 Frame 갯수:', frame_cnt)
    btime = time.time()
    while True:
        hasFrame, img_frame = cap.read()
        if not hasFrame:
            print('더 이상 처리할 frame이 없습니다.')
            break
        stime = time.time()
        img_frame = get_detected_img(model, img_frame,  score_threshold=score_threshold, is_print=False)
        if do_print:
          print('frame별 detection 수행 시간:', round(time.time() - stime, 4))
        vid_writer.write(img_frame)
    # end of while loop

    vid_writer.release()
    cap.release()

    print('최종 detection 완료 수행 시간:', round(time.time() - btime, 4))
do_detected_video(model, '/content/data/John_Wick_small.mp4', '/content/data/John_Wick_small_out2.mp4', score_threshold=0.4, do_print=True)

frame별 detection 수행 시간: 0.304
frame별 detection 수행 시간: 0.3139
frame별 detection 수행 시간: 0.2853
frame별 detection 수행 시간: 0.2918
frame별 detection 수행 시간: 0.2905
frame별 detection 수행 시간: 0.299
frame별 detection 수행 시간: 0.3006
frame별 detection 수행 시간: 0.2887
frame별 detection 수행 시간: 0.295
frame별 detection 수행 시간: 0.2932
frame별 detection 수행 시간: 0.2991
frame별 detection 수행 시간: 0.303
frame별 detection 수행 시간: 0.2913
frame별 detection 수행 시간: 0.2953
frame별 detection 수행 시간: 0.3003
frame별 detection 수행 시간: 0.3022
frame별 detection 수행 시간: 0.3018
frame별 detection 수행 시간: 0.2954
frame별 detection 수행 시간: 0.2975
frame별 detection 수행 시간: 0.3034
frame별 detection 수행 시간: 0.292
frame별 detection 수행 시간: 0.288
frame별 detection 수행 시간: 0.2939
frame별 detection 수행 시간: 0.2911
frame별 detection 수행 시간: 0.2969
frame별 detection 수행 시간: 0.2903
frame별 detection 수행 시간: 0.2912
frame별 detection 수행 시간: 0.2906
frame별 detection 수행 시간: 0.2947
frame별 detection 수행 시간: 0.2956
frame별 detection 수행 시간: 0.2936
frame별 detection 수행 시간: 0.2939
frame별 detection 수행 시간: 0.2925
frame별 detection 수행 시간: 0.2939
frame별 detection 수행 시간: 0.3
frame별 detection 수행 시간: 0.2862
frame별 detection 수행 시간: 0.2961
frame별 detection 수행 시간: 0.2958
frame별 detection 수행 시간: 0.2943
frame별 detection 수행 시간: 0.2931
frame별 detection 수행 시간: 0.2856
frame별 detection 수행 시간: 0.2911
frame별 detection 수행 시간: 0.2967
frame별 detection 수행 시간: 0.2944
frame별 detection 수행 시간: 0.2933
frame별 detection 수행 시간: 0.2886
frame별 detection 수행 시간: 0.2926
frame별 detection 수행 시간: 0.2991
frame별 detection 수행 시간: 0.2963
frame별 detection 수행 시간: 0.2885
frame별 detection 수행 시간: 0.2917
frame별 detection 수행 시간: 0.292
frame별 detection 수행 시간: 0.3013
frame별 detection 수행 시간: 0.2963
frame별 detection 수행 시간: 0.2903
더 이상 처리할 frame이 없습니다.
최종 detection 완료 수행 시간: 17.738

 

 

 

 

반응형
728x90
반응형
# 버전 확인
import torch
print(torch.__version__)
# mmcv를 위해서 mmcv-full을 설치해야 함. 
!pip install mmcv-full
from google.colab import drive
drive.mount('/content/drive')
!git clone https://github.com/open-mmlab/mmdetection.git
!cd mmdetection; python setup.py install
# 아래를 수행하기 전에 kernel을 restart 해야 함. 
# 런타임 초기화하면 설치한 파일 날라감
from mmdet.apis import init_detector, inference_detector
import mmcv

MS-COCO 데이터 기반으로 Faster RCNN Pretrained 모델을 활용하여 Inference 수행

  • Faster RCNN Pretrained 모델 다운로드
  • Faster RCNN용 Config 파일 설정.
  • Inference 용 모델을 생성하고, Inference 적용
# pretrained weight 모델을 다운로드 받기 위해서 mmdetection/checkpoints 디렉토리를 만듬. 
!cd mmdetection; mkdir checkpoints
# pretrained model faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth 설치
!wget -O /content/mmdetection/checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth http://download.openmmlab.com/mmdetection/v2.0/faster_rcnn/faster_rcnn_r50_fpn_1x_coco/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth
# pretrained model 경로 확인
!ls -lia /content/mmdetection/checkpoints
# total 163376
# 3951436 drwxr-xr-x  2 root root      4096 Oct 10 13:13 .
# 3932841 drwxr-xr-x 19 root root      4096 Oct 10 13:13 ..
# 3951438 -rw-r--r--  1 root root 167287506 Aug 28  2020 faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth

 

 

# config 파일을 설정하고, 다운로드 받은 pretrained 모델을 checkpoint로 설정. 
config_file = '/content/mmdetection/configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py'
checkpoint_file = '/content/mmdetection/checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth'
# config 파일과 pretrained 모델을 기반으로 Detector 모델을 생성. 
from mmdet.apis import init_detector, inference_detector

model = init_detector(config_file, checkpoint_file, device='cuda:0') # gpu 지정
# /usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/core/anchor/builder.py:17: UserWarning: ``build_anchor_generator`` would be deprecated soon, please use ``build_prior_generator`` 
#   '``build_anchor_generator`` would be deprecated soon, please use '
# Use load_from_local loader
# mmdetection은 상대 경로를 인자로 주면 무조건 mmdetection 디렉토리를 기준으로 함. 
%cd mmdetection

from mmdet.apis import init_detector, inference_detector

# init_detector() 인자로 config와 checkpoint를 입력함. 
model = init_detector(config='configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py', checkpoint='checkpoints/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth')

# /content/mmdetection
# /usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/core/anchor/builder.py:17: UserWarning: ``build_anchor_generator`` would be deprecated soon, please use ``build_prior_generator`` 
#   '``build_anchor_generator`` would be deprecated soon, please use '
# Use load_from_local loader

# mmdetection/configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py - _base_

=> 모델 별로 각각 다른 config를 가지는게 아니라 공통의 config를 지님

mmdetection/configs/_base_/models/fast_rcnn_r50_fpn.py에 neck=dict에 type=fpn으로 되어있음

참고로 나중에 커스컴 할 때 num_classes = n을 바꿔야함, coco dataset이 n개라서

%cd /content
# /content
import cv2
import matplotlib.pyplot as plt
img = '/content/mmdetection/demo/demo.jpg'

img_arr  = cv2.cvtColor(cv2.imread(img), cv2.COLOR_BGR2RGB)
plt.figure(figsize=(12, 12))
plt.imshow(img_arr)

 

img = '/content/mmdetection/demo/demo.jpg'
# inference_detector의 인자로 string(file경로), ndarray가 단일 또는 list형태로 입력 될 수 있음. 
results = inference_detector(model, img)

# /usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/datasets/utils.py:69: UserWarning: "ImageToTensor" pipeline is replaced by "DefaultFormatBundle" for batch inference. It is recommended to manually replace it in the test data pipeline in your config file.
#   'data pipeline in your config file.', UserWarning)
# /usr/local/lib/python3.7/dist-packages/torch/nn/functional.py:718: UserWarning: Named tensors and all their associated APIs are an experimental feature and subject to change. Please do not use them for anything important until they are released as stable. (Triggered internally at  /pytorch/c10/core/TensorImpl.h:1156.)
#   return torch.max_pool2d(input, kernel_size, stride, padding, dilation, ceil_mode)
# /usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/core/anchor/anchor_generator.py:324: UserWarning: ``grid_anchors`` would be deprecated soon. Please use ``grid_priors`` 
#   warnings.warn('``grid_anchors`` would be deprecated soon. '
# /usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/core/anchor/anchor_generator.py:361: UserWarning: ``single_level_grid_anchors`` would be deprecated soon. Please use ``single_level_grid_priors`` 
#   '``single_level_grid_anchors`` would be deprecated soon. '
type(results), len(results)
# (list, 80)
# len이 80개인데, detected 가 80개가 아니라 cocodataset이 80개임

MS-COCO pretrained model의 inference 반환 결과

# results는 list형으로 coco class의  0부터 79까지 class_id별로 80개의 array를 가짐. 
# 개별 array들은 각 클래스별로 5개의 값(좌표값과 class별로 confidence)을 가짐. 개별 class별로 여러개의 좌표를 가지면 여러개의 array가 생성됨. 
# 좌표는 좌상단(xmin, ymin), 우하단(xmax, ymax) 기준. 
# 개별 array의 shape는 (Detection된 object들의 수, 5(좌표와 confidence)) 임

results

class)id 0:'person', 1:'bicycle, 2:'car'
[array([[3.75348572e+02, 1.19171005e+02, 3.81950867e+02, 1.34460617e+02,
         1.35454327e-01], # 좌표값 좌상단(xmin, ymin), 우하단(xmax, ymax), class confidence
        [5.32362000e+02, 1.09554726e+02, 5.40526550e+02, 1.25222633e+02,
         8.88783410e-02], # 좌표값 좌상단(xmin, ymin), 우하단(xmax, ymax), class confidence
        [3.61124298e+02, 1.09049202e+02, 3.68625610e+02, 1.22483063e+02,
         7.20723420e-02]], dtype=float32), # 좌표값 좌상단(xmin, ymin), 우하단(xmax, ymax), class confidence
# class id는 별도로 없고, results[0]이 0번임         
# 내부에서 정규화를 해버림 
 array([], shape=(0, 5), dtype=float32), # 0번 class id는 detect가 안됬다.
 array([[6.09650024e+02, 1.13805893e+02, 6.34511658e+02, 1.36951904e+02,
         9.88766134e-01],
        [4.81773712e+02, 1.10480980e+02, 5.22459717e+02, 1.30407104e+02,
         9.87157285e-01],
        [1.01822114e+00, 1.12144730e+02, 6.04374733e+01, 1.44173752e+02,
         9.83206093e-01],
        [2.94623718e+02, 1.17035240e+02, 3.78022705e+02, 1.50550873e+02,
         9.71326768e-01],
        [3.96328979e+02, 1.11203323e+02, 4.32490540e+02, 1.32729263e+02,
         9.67802167e-01],
        [5.90976257e+02, 1.10802658e+02, 6.15401794e+02, 1.26493553e+02,
         9.59414959e-01],
        [2.67582001e+02, 1.05686005e+02, 3.28818756e+02, 1.28226547e+02,
         9.59253132e-01],
        [1.66856735e+02, 1.08006607e+02, 2.19100693e+02, 1.40194809e+02,
         9.56841350e-01],
        [1.89769577e+02, 1.09801109e+02, 3.00310852e+02, 1.53781891e+02,
         9.51012135e-01],
        [4.29822540e+02, 1.05655380e+02, 4.82741516e+02, 1.32376724e+02,
         9.45849955e-01],
        [5.55000916e+02, 1.09785004e+02, 5.92761780e+02, 1.27808495e+02,
         9.43992615e-01],
        [5.96790352e+01, 9.31828003e+01, 8.34545441e+01, 1.06242912e+02,
         9.33143973e-01],
        [9.78446579e+01, 8.96542969e+01, 1.18172356e+02, 1.01011108e+02,
         8.66323531e-01],
        [1.43898987e+02, 9.61869888e+01, 1.64599792e+02, 1.04979256e+02,
         8.26784551e-01],
        [8.55894241e+01, 8.99445801e+01, 9.88920746e+01, 9.85285416e+01,
         7.53480315e-01],
        [9.78282700e+01, 9.07443695e+01, 1.10298050e+02, 9.97373276e+01,
         7.16600597e-01],
        [2.23579224e+02, 9.85184631e+01, 2.49845108e+02, 1.07509857e+02,
         6.00782037e-01],
        [1.68928635e+02, 9.59468994e+01, 1.82843445e+02, 1.05694962e+02,
         5.91998756e-01],
        [1.35021347e+02, 9.08739395e+01, 1.50607025e+02, 1.02798874e+02,
         5.54030240e-01],
        [0.00000000e+00, 1.11521950e+02, 1.45326691e+01, 1.25850288e+02,
         5.43519914e-01],
        [5.53896606e+02, 1.16170540e+02, 5.62602295e+02, 1.26390923e+02,
         4.76758897e-01],
        [3.75809753e+02, 1.19579056e+02, 3.82376495e+02, 1.32113892e+02,
         4.61191744e-01],
        [1.37924118e+02, 9.37975311e+01, 1.54497177e+02, 1.04659683e+02,
         4.00998443e-01],
        [5.55009033e+02, 1.10952698e+02, 5.74925659e+02, 1.26912033e+02,
         3.43850523e-01],
        [5.54043152e+02, 1.00959076e+02, 5.61297913e+02, 1.10927711e+02,
         2.87963450e-01],
        [6.14741028e+02, 1.01987068e+02, 6.35481628e+02, 1.12593704e+02,
         2.61200219e-01],
        [5.70760315e+02, 1.09679398e+02, 5.90286133e+02, 1.27248878e+02,
         2.58404434e-01],
        [4.78544116e-01, 1.11568169e+02, 2.25040989e+01, 1.42623535e+02,
         2.56050110e-01],
        [3.75093140e+02, 1.11696442e+02, 4.20536804e+02, 1.33691055e+02,
         2.55963236e-01],
        [2.62747284e+02, 1.07565620e+02, 3.26765930e+02, 1.43925293e+02,
         2.09969625e-01],
        [7.91312714e+01, 9.03788834e+01, 1.00247879e+02, 1.01080894e+02,
         2.03962341e-01],
        [6.09313477e+02, 1.13308510e+02, 6.25961975e+02, 1.25342514e+02,
         1.97422847e-01],
        [1.35304840e+02, 9.23771439e+01, 1.64080185e+02, 1.04992455e+02,
         1.49973527e-01],
        [6.73540573e+01, 8.85008087e+01, 8.29853592e+01, 9.73942108e+01,
         1.48383990e-01],
        [5.40852417e+02, 1.13848946e+02, 5.61855530e+02, 1.26198776e+02,
         1.47629887e-01],
        [3.51735046e+02, 1.09432655e+02, 4.39310089e+02, 1.34819733e+02,
         1.41735107e-01],
        [9.63179016e+01, 8.98780594e+01, 1.53287781e+02, 1.01776367e+02,
         1.32707968e-01],
        [4.54495049e+01, 1.17444977e+02, 6.18955803e+01, 1.44275055e+02,
         1.25890508e-01],
        [6.06407532e+02, 1.12215973e+02, 6.18935669e+02, 1.24957237e+02,
         1.10722415e-01],
        [1.02152626e+02, 9.36143646e+01, 1.41081863e+02, 1.01598961e+02,
         8.13643038e-02],
        [3.98364838e+02, 1.12081459e+02, 4.09389862e+02, 1.32897766e+02,
         7.64543191e-02],
        [5.39245911e+02, 1.12394836e+02, 5.48756714e+02, 1.21964462e+02,
         7.32642636e-02],
        [6.09156555e+02, 1.04017456e+02, 6.35472107e+02, 1.26777176e+02,
         6.47417754e-02],
        [3.75894284e+00, 9.85745239e+01, 7.45848312e+01, 1.35154999e+02,
         6.32166639e-02],
        [1.68166473e+02, 9.14260483e+01, 2.20303146e+02, 1.07955681e+02,
         5.16179129e-02],
        [7.09724045e+01, 9.02684860e+01, 1.05398132e+02, 1.03825508e+02,
         5.15376776e-02]], dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([[1.8820007e+02, 1.0994706e+02, 3.0047137e+02, 1.5633583e+02,
         9.7509645e-02],
        [4.2774915e+02, 1.0511559e+02, 4.8345541e+02, 1.3294328e+02,
         9.6882291e-02],
        [2.9450479e+02, 1.1764229e+02, 3.7863284e+02, 1.5046356e+02,
         7.4364766e-02]], dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([[2.1920888e+02, 1.7456262e+02, 4.6010886e+02, 3.7704660e+02,
         9.7778010e-01],
        [3.7206638e+02, 1.3631432e+02, 4.3219531e+02, 1.8717290e+02,
         4.1699746e-01]], dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([[9.13259964e+01, 1.07155769e+02, 1.06029366e+02, 1.19777306e+02,
         1.15152948e-01]], dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([[3.72651917e+02, 1.36143082e+02, 4.32053833e+02, 1.88446472e+02,
         7.77875960e-01],
        [2.18404114e+02, 1.75137848e+02, 4.62107605e+02, 3.65541260e+02,
         1.01236075e-01]], dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32),
 array([], shape=(0, 5), dtype=float32)]

요약

# 2차원 배열로 표현됨
# 사람,    자전거,  차,     
results[0].shape, results[1].shape, results[2].shape, results[3].shape
# ((3, 5), (0, 5), (46, 5), (0, 5))
# 3건,      0건,    46건,    0건

결과 직접 확인

from mmdet.apis import show_result_pyplot
# inference 된 결과를 원본 이미지에 적용하여 새로운 image로 생성(bbox 처리된 image)
# Default로 score threshold가 0.3 이상인 Object들만 시각화 적용. show_result_pyplot은 model.show_result()를 호출. 
show_result_pyplot(model, img, results)

 

Model의 Config 설정 확인하기

# configs 파일로 모델을 만들었는데 모델 객체안의 변수 확인
model.__dict__

# 80개 class
{'CLASSES': ('person',
  'bicycle',
  'car',
  'motorcycle',
  'airplane',
  'bus',
  'train',
  'truck',
  'boat',
  'traffic_light',
  'fire_hydrant',
  'stop_sign',
  'parking_meter',
  'bench',
  'bird',
  'cat',
  'dog',
  'horse',
  'sheep',
  'cow',
  'elephant',
  'bear',
  'zebra',
  'giraffe',
  'backpack',
  'umbrella',
  'handbag',
  'tie',
  'suitcase',
  'frisbee',
  'skis',
  'snowboard',
  'sports_ball',
  'kite',
  'baseball_bat',
  'baseball_glove',
  'skateboard',
  'surfboard',
  'tennis_racket',
  'bottle',
  'wine_glass',
  'cup',
  'fork',
  'knife',
  'spoon',
  'bowl',
  'banana',
  'apple',
  'sandwich',
  'orange',
  'broccoli',
  'carrot',
  'hot_dog',
  'pizza',
  'donut',
  'cake',
  'chair',
  'couch',
  'potted_plant',
  'bed',
  'dining_table',
  'toilet',
  'tv',
  'laptop',
  'mouse',
  'remote',
  'keyboard',
  'cell_phone',
  'microwave',
  'oven',
  'toaster',
  'sink',
  'refrigerator',
  'book',
  'clock',
  'vase',
  'scissors',
  'teddy_bear',
  'hair_drier',
  'toothbrush'),
  '_modules': OrderedDict([('backbone', ResNet(
  # 모듈은 pytorch, backbone : resnet
  'cfg': Config (path: configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py)
#print(model.cfg) # 안이쁘게 나옴
print(model.cfg.pretty_text)

model = dict(
    type='FasterRCNN',
    backbone=dict(
        type='ResNet',
        depth=50,
        num_stages=4,
        out_indices=(0, 1, 2, 3),
        frozen_stages=1,
        norm_cfg=dict(type='BN', requires_grad=True),
        norm_eval=True,
        style='pytorch',
        init_cfg=dict(type='Pretrained', checkpoint='torchvision://resnet50')),
    neck=dict(
        type='FPN',
        in_channels=[256, 512, 1024, 2048],
        out_channels=256,
        num_outs=5),
    rpn_head=dict(
        type='RPNHead',
        in_channels=256,
        feat_channels=256,
        anchor_generator=dict(
            type='AnchorGenerator',
            scales=[8],
            ratios=[0.5, 1.0, 2.0],
            strides=[4, 8, 16, 32, 64]),
        bbox_coder=dict(
            type='DeltaXYWHBBoxCoder',
            target_means=[0.0, 0.0, 0.0, 0.0],
            target_stds=[1.0, 1.0, 1.0, 1.0]),
        loss_cls=dict(
            type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0),
        loss_bbox=dict(type='L1Loss', loss_weight=1.0)),
    roi_head=dict(
        type='StandardRoIHead',
        bbox_roi_extractor=dict(
            type='SingleRoIExtractor',
            roi_layer=dict(type='RoIAlign', output_size=7, sampling_ratio=0),
            out_channels=256,
            featmap_strides=[4, 8, 16, 32]),
        bbox_head=dict(
            type='Shared2FCBBoxHead',
            in_channels=256,
            fc_out_channels=1024,
            roi_feat_size=7,
            num_classes=80,
            bbox_coder=dict(
                type='DeltaXYWHBBoxCoder',
                target_means=[0.0, 0.0, 0.0, 0.0],
                target_stds=[0.1, 0.1, 0.2, 0.2]),
            reg_class_agnostic=False,
            loss_cls=dict(
                type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0),
            loss_bbox=dict(type='L1Loss', loss_weight=1.0)),
        train_cfg=None,
        test_cfg=dict(
            score_thr=0.05,
            nms=dict(type='nms', iou_threshold=0.5),
            max_per_img=100),
        pretrained=None),
    train_cfg=None,
    test_cfg=dict(
        rpn=dict(
            nms_pre=1000,
            max_per_img=1000,
            nms=dict(type='nms', iou_threshold=0.7),
            min_bbox_size=0),
        rcnn=dict(
            score_thr=0.05,
            nms=dict(type='nms', iou_threshold=0.5),
            max_per_img=100)),
    pretrained=None)
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',
        mean=[123.675, 116.28, 103.53],
        std=[58.395, 57.12, 57.375],
        to_rgb=True),
    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',
                mean=[123.675, 116.28, 103.53],
                std=[58.395, 57.12, 57.375],
                to_rgb=True),
            dict(type='Pad', size_divisor=32),
            dict(type='ImageToTensor', keys=['img']),
            dict(type='Collect', keys=['img'])
        ])
]
data = dict(
    samples_per_gpu=2,
    workers_per_gpu=2,
    train=dict(
        type='CocoDataset',
        ann_file='data/coco/annotations/instances_train2017.json',
        img_prefix='data/coco/train2017/',
        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',
                mean=[123.675, 116.28, 103.53],
                std=[58.395, 57.12, 57.375],
                to_rgb=True),
            dict(type='Pad', size_divisor=32),
            dict(type='DefaultFormatBundle'),
            dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels'])
        ]),
    val=dict(
        type='CocoDataset',
        ann_file='data/coco/annotations/instances_val2017.json',
        img_prefix='data/coco/val2017/',
        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',
                        mean=[123.675, 116.28, 103.53],
                        std=[58.395, 57.12, 57.375],
                        to_rgb=True),
                    dict(type='Pad', size_divisor=32),
                    dict(type='ImageToTensor', keys=['img']),
                    dict(type='Collect', keys=['img'])
                ])
        ]),
    test=dict(
        type='CocoDataset',
        ann_file='data/coco/annotations/instances_val2017.json',
        img_prefix='data/coco/val2017/',
        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',
                        mean=[123.675, 116.28, 103.53],
                        std=[58.395, 57.12, 57.375],
                        to_rgb=True),
                    dict(type='Pad', size_divisor=32),
                    dict(type='DefaultFormatBundle'),
                    dict(type='Collect', keys=['img'])
                ])
        ]))
evaluation = dict(interval=1, metric='bbox')
optimizer = dict(type='SGD', lr=0.02, momentum=0.9, weight_decay=0.0001)
optimizer_config = dict(grad_clip=None)
lr_config = dict(
    policy='step',
    warmup='linear',
    warmup_iters=500,
    warmup_ratio=0.001,
    step=[8, 11])
runner = dict(type='EpochBasedRunner', max_epochs=12)
checkpoint_config = dict(interval=1)
log_config = dict(interval=50, hooks=[dict(type='TextLoggerHook')])
custom_hooks = [dict(type='NumClassCheckHook')]
dist_params = dict(backend='nccl')
log_level = 'INFO'
load_from = None
resume_from = None
workflow = [('train', 1)]

커스텀 할때 모델의 class 가 몇개인가, bbox_head의 num_classes 설정, dataset 설정을 지정해야 함. transforming, annotation 등 설정

 

array를 inference_detector()에 입력할 경우에는 원본 array를 BGR 형태로 입력 필요(RGB 변환은 내부에서 수행하므로 BGR로 입력 필요)

import cv2

# RGB가 아닌 BGR로 입력
img_arr = cv2.imread('/content/mmdetection/demo/demo.jpg')
results = inference_detector(model, img_arr)

show_result_pyplot(model, img_arr, results)

show_result_pyplot()을 이용하지 않고, inference 결과를 image로 표현하기

  • model과 image array를 입력하면 해당 image를 detect하고 bbox 처리해주는 get_detected_img() 함수 생성.
  • COCO 클래스 매핑은 0 부터 순차적으로 적용됨.
  • results에 들어있는 array 값이 없는 경우는 해당 list의 index에 해당하는 class id값으로 object가 Detection되지 않은 것임.
  • 개별 class의 score threshold가 낮은 값은 제외.
# 0부터 순차적으로 클래스 매핑된 label 적용. 
labels_to_names_seq = {0:'person',1:'bicycle',2:'car',3:'motorbike',4:'aeroplane',5:'bus',6:'train',7:'truck',8:'boat',9:'traffic light',10:'fire hydrant',
                        11:'stop sign',12:'parking meter',13:'bench',14:'bird',15:'cat',16:'dog',17:'horse',18:'sheep',19:'cow',20:'elephant',
                        21:'bear',22:'zebra',23:'giraffe',24:'backpack',25:'umbrella',26:'handbag',27:'tie',28:'suitcase',29:'frisbee',30:'skis',
                        31:'snowboard',32:'sports ball',33:'kite',34:'baseball bat',35:'baseball glove',36:'skateboard',37:'surfboard',38:'tennis racket',39:'bottle',40:'wine glass',
                        41:'cup',42:'fork',43:'knife',44:'spoon',45:'bowl',46:'banana',47:'apple',48:'sandwich',49:'orange',50:'broccoli',
                        51:'carrot',52:'hot dog',53:'pizza',54:'donut',55:'cake',56:'chair',57:'sofa',58:'pottedplant',59:'bed',60:'diningtable',
                        61:'toilet',62:'tvmonitor',63:'laptop',64:'mouse',65:'remote',66:'keyboard',67:'cell phone',68:'microwave',69:'oven',70:'toaster',
                        71:'sink',72:'refrigerator',73:'book',74:'clock',75:'vase',76:'scissors',77:'teddy bear',78:'hair drier',79:'toothbrush' }

labels_to_names = {1:'person',2:'bicycle',3:'car',4:'motorcycle',5:'airplane',6:'bus',7:'train',8:'truck',9:'boat',10:'traffic light',
                    11:'fire hydrant',12:'street sign',13:'stop sign',14:'parking meter',15:'bench',16:'bird',17:'cat',18:'dog',19:'horse',20:'sheep',
                    21:'cow',22:'elephant',23:'bear',24:'zebra',25:'giraffe',26:'hat',27:'backpack',28:'umbrella',29:'shoe',30:'eye glasses',
                    31:'handbag',32:'tie',33:'suitcase',34:'frisbee',35:'skis',36:'snowboard',37:'sports ball',38:'kite',39:'baseball bat',40:'baseball glove',
                    41:'skateboard',42:'surfboard',43:'tennis racket',44:'bottle',45:'plate',46:'wine glass',47:'cup',48:'fork',49:'knife',50:'spoon',
                    51:'bowl',52:'banana',53:'apple',54:'sandwich',55:'orange',56:'broccoli',57:'carrot',58:'hot dog',59:'pizza',60:'donut',
                    61:'cake',62:'chair',63:'couch',64:'potted plant',65:'bed',66:'mirror',67:'dining table',68:'window',69:'desk',70:'toilet',
                    71:'door',72:'tv',73:'laptop',74:'mouse',75:'remote',76:'keyboard',77:'cell phone',78:'microwave',79:'oven',80:'toaster',
                    81:'sink',82:'refrigerator',83:'blender',84:'book',85:'clock',86:'vase',87:'scissors',88:'teddy bear',89:'hair drier',90:'toothbrush',
                    91:'hair brush'}
import numpy as np

# np.where 사용법 예시.
arr1 = np.array([[3.75348572e+02, 1.19171005e+02, 3.81950867e+02, 1.34460617e+02,
         1.35454759e-01],
        [5.32362000e+02, 1.09554726e+02, 5.40526550e+02, 1.25222633e+02,
         8.88786465e-01],
        [3.61124298e+02, 1.09049202e+02, 3.68625610e+02, 1.22483063e+02,
         7.20717013e-02]], dtype=np.float32)
print(arr1.shape)

arr1_filtered = arr1[np.where(arr1[:, 4] > 0.1)] # 0.1 보다 큰것만 저장
print('### arr1_filtered:', arr1_filtered, arr1_filtered.shape)

(3, 5) # 2차원으로
### arr1_filtered: [[3.75348572e+02 1.19171005e+02 3.81950867e+02 1.34460617e+02
  1.35454759e-01]
 [5.32362000e+02 1.09554726e+02 5.40526550e+02 1.25222633e+02
  8.88786495e-01]] (2, 5)
np.where(arr1[:, 4] > 0.1) # row는 전부, 4:class confidence 가 0.1보다 큰 경우
# (array([0, 1]),)
# row 기준으로
# model과 원본 이미지 array, filtering할 기준 class confidence score를 인자로 가지는 inference 시각화용 함수 생성. 
def get_detected_img(model, img_array,  score_threshold=0.3, is_print=True):
  # 인자로 들어온 image_array를 복사. 
  draw_img = img_array.copy()
  bbox_color=(0, 255, 0)
  text_color=(0, 0, 255)

  # model과 image array를 입력 인자로 inference detection 수행하고 결과를 results로 받음. 
  # results는 80개의 2차원 array(shape=(오브젝트갯수, 5))를 가지는 list. 
  results = inference_detector(model, img_array)

  # 80개의 array원소를 가지는 results 리스트를 loop를 돌면서 개별 2차원 array들을 추출하고 이를 기반으로 이미지 시각화 
  # results 리스트의 위치 index가 바로 COCO 매핑된 Class id. 여기서는 result_ind가 class id
  # 개별 2차원 array에 오브젝트별 좌표와 class confidence score 값을 가짐. 
  for result_ind, result in enumerate(results):
    # 개별 2차원 array의 row size가 0 이면 해당 Class id로 값이 없으므로 다음 loop로 진행. 
    if len(result) == 0:
      continue
    
    # 2차원 array에서 5번째 컬럼에 해당하는 값이 score threshold이며 이 값이 함수 인자로 들어온 score_threshold 보다 낮은 경우는 제외. 
    result_filtered = result[np.where(result[:, 4] > score_threshold)]
    
    # 해당 클래스 별로 Detect된 여러개의 오브젝트 정보가 2차원 array에 담겨 있으며, 이 2차원 array를 row수만큼 iteration해서 개별 오브젝트의 좌표값 추출. 
    for i in range(len(result_filtered)):
      # 좌상단, 우하단 좌표 추출. 
      left = int(result_filtered[i, 0])
      top = int(result_filtered[i, 1])
      right = int(result_filtered[i, 2])
      bottom = int(result_filtered[i, 3])
      
      caption = "{}: {:.4f}".format(labels_to_names_seq[result_ind], result_filtered[i, 4])
      cv2.rectangle(draw_img, (left, top), (right, bottom), color=bbox_color, thickness=2)
      cv2.putText(draw_img, caption, (int(left), int(top - 7)), cv2.FONT_HERSHEY_SIMPLEX, 0.37, text_color, 1)
      if is_print:
        print(caption)

  return draw_img
import matplotlib.pyplot as plt

img_arr = cv2.imread('/content/mmdetection/demo/demo.jpg')
detected_img = get_detected_img(model, img_arr,  score_threshold=0.3, is_print=True)
# detect 입력된 이미지는 bgr임. 이를 최종 출력시 rgb로 변환 
detected_img = cv2.cvtColor(detected_img, cv2.COLOR_BGR2RGB)

plt.figure(figsize=(12, 12))
plt.imshow(detected_img)

/usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/core/anchor/anchor_generator.py:324: UserWarning: ``grid_anchors`` would be deprecated soon. Please use ``grid_priors`` 
  warnings.warn('``grid_anchors`` would be deprecated soon. '
car: 0.9888
car: 0.9872
car: 0.9832
car: 0.9713
car: 0.9678
car: 0.9594
car: 0.9593
car: 0.9568
car: 0.9510
car: 0.9458
car: 0.9440
car: 0.9331
car: 0.8663
car: 0.8268
car: 0.7535
car: 0.7166
car: 0.6008
car: 0.5920
car: 0.5540
car: 0.5435
car: 0.4768
car: 0.4612
car: 0.4010
car: 0.3439
bench: 0.9778
bench: 0.4170
chair: 0.7779
/usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/core/anchor/anchor_generator.py:361: UserWarning: ``single_level_grid_anchors`` would be deprecated soon. Please use ``single_level_grid_priors`` 
  '``single_level_grid_anchors`` would be deprecated soon. '
<matplotlib.image.AxesImage at 0x7f7f78bc4a50>

!mkdir data
!wget -O /content/data/beatles01.jpg https://raw.githubusercontent.com/chulminkw/DLCV/master/data/image/beatles01.jpg
!ls -lia /content/data/beatles01.jpg
img_arr = cv2.imread('/content/data/beatles01.jpg')
detected_img = get_detected_img(model, img_arr,  score_threshold=0.5, is_print=True)
# detect 입력된 이미지는 bgr임. 이를 최종 출력시 rgb로 변환 
detected_img = cv2.cvtColor(detected_img, cv2.COLOR_BGR2RGB)

plt.figure(figsize=(12, 12))
plt.imshow(detected_img)

/usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/core/anchor/anchor_generator.py:324: UserWarning: ``grid_anchors`` would be deprecated soon. Please use ``grid_priors`` 
  warnings.warn('``grid_anchors`` would be deprecated soon. '
person: 0.9988
person: 0.9982
person: 0.9980
person: 0.9971
person: 0.9604
car: 0.9693
car: 0.9686
car: 0.9648
car: 0.9517
car: 0.9254
car: 0.9030
car: 0.8312
car: 0.8008
car: 0.7331
car: 0.6208
tie: 0.5924
/usr/local/lib/python3.7/dist-packages/mmdet-2.17.0-py3.7.egg/mmdet/core/anchor/anchor_generator.py:361: UserWarning: ``single_level_grid_anchors`` would be deprecated soon. Please use ``single_level_grid_priors`` 
  '``single_level_grid_anchors`` would be deprecated soon. '
<matplotlib.image.AxesImage at 0x7f7f78bf2e50>

 

반응형
728x90
반응형

알고리즘을 패키지화 시키는 것이 대세

code기반, 지원 알고리즘이 많지 않음

Config 기반, Facebook Research 주도

detectron1이 있었는데 mmdetection에 밀리고, v2는 1보다 훨씬 빠르다

Config 기반, 중국 칭화대 중심 openMMlab 주도

발전속도도 빠르고, 지원하는 알고리즘도 많다.

매우 수준 높은 패키지, 난이도는 조금 있다.

kaggle에서도 좋은 성적을 냄

 

 

MMDetection

- 2018년 MSCOCO Challenge에서 우승 후 모듈을 확장하여 다수의 알고리즘 수용

- 뛰어난 구현 성능, 효율적인 모듈 설계, config 기반 데이터부터 모델 학습 / 평가 까지 이어지는 간편한 파이프라인 적용

- 코드를 짜는게 아니라 config에 적용함

- pytorch 기반 구현

- backbone이 ResNet이 많음

- SSD에 어울리는 mobileNet이 없다.

 

YOLO v3도 포함

efficientDet은 업데이트 예정

 

MMdetection 모델 아키텍처

- Backbone : Feature Extractor(이미지 => Feature Map) 

- Neck : backbone과 head를 연결, heads가 feature map의 특성을 보다 잘 해석하고 처리하도록 정제 작업 수행

- DenseHead : Feature map에서 object의 위치와 classification을 처리하는 부분

- ROIExtractor : Feature Map에서 ROI정보를 뽑아내는 부분

- ROIHead(BBoxHead/MaskHead) : ROI정보를 기반으로 Object 위치와 Classification을 수행하는 부분 

1) Dataset

model training, model evaluation

annotation, image

 

 

3) Model

faster RCNN, SSD, YOLO, RetinaNet

 

optimasier, epoch 등 선택

=> 알고리즘의 특성을 각각 반영하다보면  config 규모가 커짐 

- config로 하면 여러 알고리즘을 써도 편함

 

# MMdetection Training pipeline

- loop를 iteration을 돌아서 중간에 어떤 조작이 안되고 대신 callback을 건다

- Hook(callback) 통해 학습에 필요한 여러 설정들을 customization 가능

- 대부분 configuration에서 이를 설정함

 

 

 

 

 

 

 

반응형

+ Recent posts