【Vision】 Detection과 Segmentation 다시 정리 2 - Datasets

당연하다고 생각하지만, 아직은 공부할게 많은 Detection과 Segmentation에 대한 개념을 다시 상기하고 정리해보면서 공부해볼 계획이다.

Detection과 Segmentation 다시 정리 2

Dataset에 대한 진지한 고찰

1. Pascal VOC 기본개념

  1. 기본 개념

    • XML Format (20개 Class)
    • 하나의 이미지에 대해서 Annotation이 하나의 XML 파일에 저장되어 있다.
    • 데이터셋 홈페이지 바로가기
    • 대회 종류
      • Classification/Detection
      • Segmentation
      • Action Classification
      • Person Layout
    • Annotation : Pascal VOC 같은 경우에 아래와 같은 형식의 Annotation 파일로써 Ground True 정보를 파악할 수 있다.

    • Data Set을 다운받으면 다음과 같은 구조를 확인할 수 있다. segmented : segmentation 정보를 가지고 있느냐?를 의미한다.
      drawing
      drawing

2. PASCAL VOC 2012 데이터 탐색해보기

  • 코드 안에 주석도 매우 중요하니 꼭 확인하고 공부하기
  • DLCV/Detection/preliminary/PASCAL_VOC_Dataset_탐색하기.ipynb 파일을 통해 공부한 내용
  !ls ~/DLCV/data/voc/VOCdevkit/VOC2012
  Annotations  ImageSets	JPEGImages  SegmentationClass  SegmentationObject
  !ls ~/DLCV/data/voc/VOCdevkit/VOC2012/JPEGImages | head -n 5
  2007_000027.jpg
  2007_000032.jpg
  2007_000033.jpg
  2007_000039.jpg
  2007_000042.jpg
  ls: write error: Broken pipe
  • JPEGImages 디렉토리에 있는 임의의 이미지 보기
  import cv2
  import matplotlib.pyplot as plt
  %matplotlib inline

  img = cv2.imread('../../data/voc/VOCdevkit/VOC2012/JPEGImages/2007_000032.jpg')
  img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  print('img shape:', img.shape)

  plt.figure(figsize=(8, 8))
  plt.imshow(img_rgb)
  plt.show()

  img shape: (281, 500, 3)
  • Annotations 디렉토리에 있는 임의의 annotation 파일 보기
  !cat ~/DLCV/data/voc/VOCdevkit/VOC2012/Annotations/2007_000032.xml
  <annotation>
    <folder>VOC2012</folder>
    <filename>2007_000032.jpg</filename>
    <source>
      <database>The VOC2007 Database</database>
      <annotation>PASCAL VOC2007</annotation>
      <image>flickr</image>
    </source>
    <size>
      <width>500</width>
      <height>281</height>
      <depth>3</depth>
    </size>
    <segmented>1</segmented>
    <object>
      <name>aeroplane</name>
      <pose>Frontal</pose>
      <truncated>0</truncated>
      <difficult>0</difficult>
      <bndbox>
        <xmin>104</xmin>
        <ymin>78</ymin>
        <xmax>375</xmax>
        <ymax>183</ymax>
      </bndbox>
    </object>
    <object>
      <name>aeroplane</name>
      <pose>Left</pose>
      <truncated>0</truncated>
      <difficult>0</difficult>
      <bndbox>
        <xmin>133</xmin>
        <ymin>88</ymin>
        <xmax>197</xmax>
        <ymax>123</ymax>
      </bndbox>
    </object>
    <object>
      <name>person</name>
      <pose>Rear</pose>
      <truncated>0</truncated>
      <difficult>0</difficult>
      <bndbox>
        <xmin>195</xmin>
        <ymin>180</ymin>
        <xmax>213</xmax>
        <ymax>229</ymax>
      </bndbox>
    </object>
    <object>
      <name>person</name>
      <pose>Rear</pose>
      <truncated>0</truncated>
      <difficult>0</difficult>
      <bndbox>
        <xmin>26</xmin>
        <ymin>189</ymin>
        <xmax>44</xmax>
        <ymax>238</ymax>
      </bndbox>
    </object>
  </annotation>
  • SegmentationObject 디렉토리에 있는 있는 임의의 maksing 이미지 보기
  img = cv2.imread('../../data/voc/VOCdevkit/VOC2012/SegmentationObject/2007_000032.png')
  img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
  print('img shape:', img.shape)

  plt.figure(figsize=(8, 8))
  plt.imshow(img_rgb)
  plt.show()
  img shape: (281, 500, 3)
  • Annotation xml 파일에 있는 요소들을 파싱하여 접근하기
  • 파일 이름만 뽑아아서 xml_files 라는 변수에 저장해 두기
  # 파일 이름만 뽑아아서 xml_files 라는 변수에 저장해 두기
  import os
  import random

  VOC_ROOT_DIR ="../../data/voc/VOCdevkit/VOC2012/"
  ANNO_DIR = os.path.join(VOC_ROOT_DIR, "Annotations")
  IMAGE_DIR = os.path.join(VOC_ROOT_DIR, "JPEGImages")

  xml_files = os.listdir(ANNO_DIR)                       
  print(xml_files[:5]); print(len(xml_files))
  ['2012_001360.xml', '2008_003384.xml', '2008_007317.xml', '2009_000990.xml', '2009_003539.xml']
  17125
  • xml 파일을 다루기 위한 모듈은 다음과 같다.
  # !pip install lxml
  # 틔
  import os
  import xml.etree.ElementTree as ET

  xml_file = os.path.join(ANNO_DIR, '2007_000032.xml')

  # XML 파일을 Parsing 하여 Element 생성
  # 이렇게 2번의 과정을 거쳐서 Parsing을 완료하면 root라는 변수에 원하는 정보들이 저장되어 있다. 
  tree = ET.parse(xml_file)
  root = tree.getroot()

  # root가 dictionary 변수이면 root.keys()이렇게 출력하면 될덴데...
  print("root.keys = ", end='')
  for child in root:
      print(child.tag, end = ', ')
          

  # image 관련 정보는 root의 자식으로 존재
  # root를 이용해서 dictionary형식의 anotation 정보를 뽑아내는 방법은 다음과 같다.
  image_name = root.find('filename').text
  full_image_name = os.path.join(IMAGE_DIR, image_name)
  image_size = root.find('size')
  image_width = int(image_size.find('width').text)
  image_height = int(image_size.find('height').text)

  # 파일내에 있는 모든 object Element를 찾음.
  objects_list = []
  for obj in root.findall('object'):
      # object element의 자식 element에서 bndbox를 찾음. 
      xmlbox = obj.find('bndbox')
      # bndbox element의 자식 element에서 xmin,ymin,xmax,ymax를 찾고 이의 값(text)를 추출 
      x1 = int(xmlbox.find('xmin').text)
      y1 = int(xmlbox.find('ymin').text)
      x2 = int(xmlbox.find('xmax').text)
      y2 = int(xmlbox.find('ymax').text)
      
      bndbox_pos = (x1, y1, x2, y2)
      class_name=obj.find('name').text
      object_dict={'class_name': class_name, 'bndbox_pos':bndbox_pos}
      objects_list.append(object_dict)

  print('\nfull_image_name:', full_image_name,'\n', 'image_size:', (image_width, image_height))

  for object in objects_list:
      print(object)

      
  root.keys = folder, filename, source, size, segmented, object, object, object, object, 
  full_image_name: ../../data/voc/VOCdevkit/VOC2012/JPEGImages/2007_000032.jpg 
  image_size: (500, 281)
  {'class_name': 'aeroplane', 'bndbox_pos': (104, 78, 375, 183)}
  {'class_name': 'aeroplane', 'bndbox_pos': (133, 88, 197, 123)}
  {'class_name': 'person', 'bndbox_pos': (195, 180, 213, 229)}
  {'class_name': 'person', 'bndbox_pos': (26, 189, 44, 238)}
  • Annotation내의 Object들의 bounding box 정보를 이용하여 Bounding box 시각화
  import cv2
  import os
  import xml.etree.ElementTree as ET

  xml_file = os.path.join(ANNO_DIR, '2007_000032.xml')

  tree = ET.parse(xml_file)
  root = tree.getroot()

  image_name = root.find('filename').text
  full_image_name = os.path.join(IMAGE_DIR, image_name)

  img = cv2.imread(full_image_name)
  # opencv의 rectangle()는 인자로 들어온 이미지 배열에 그대로 사각형을 그려주므로 별도의 이미지 배열에 그림 작업 수행. 
  draw_img = img.copy()
  # OpenCV는 RGB가 아니라 BGR이므로 빨간색은 (0, 0, 255)
  green_color=(0, 255, 0)
  red_color=(0, 0, 255)

  # 파일내에 있는 모든 object Element를 찾음.
  objects_list = []
  for obj in root.findall('object'):
      xmlbox = obj.find('bndbox')
      
      left = int(xmlbox.find('xmin').text)
      top = int(xmlbox.find('ymin').text)
      right = int(xmlbox.find('xmax').text)
      bottom = int(xmlbox.find('ymax').text)
      
      class_name=obj.find('name').text
      
      # draw_img 배열의 좌상단 우하단 좌표에 녹색으로 box 표시 
      cv2.rectangle(draw_img, (left, top), (right, bottom), color=green_color, thickness=1)
      # draw_img 배열의 좌상단 좌표에 빨간색으로 클래스명 표시
      cv2.putText(draw_img, class_name, (left, top - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.4, red_color, thickness=1)

  img_rgb = cv2.cvtColor(draw_img, cv2.COLOR_BGR2RGB)
  plt.figure(figsize=(10, 10))
  plt.imshow(img_rgb)

drawing

3. MS COCO

  • json Format (80개 Class : paper에서는 80개라고 했지만, 이미지에서는 굳이 분류 안한 class가 있으니 주의할 것.)
  • 300K 이미지들 1.5M개 Object들 (하나의 이미지당 5개의 객체)
  • 모든 이미지에 대해서 하나의 json 파일이 존재한다.
  • Pretrained Weight로 활용하기에 좋다.
  • 데이터셋 홈페이지 바로가기
    • 보통 2017데이터 셋 가장 최신의 데이터셋을 사용한다.
  • 데이터셋 Explore를 쉽게 할 수 있다.
  • 데이터셋 구성
    drawing
  • 하나의 이미지 안에 여러 Class들 여러 Object들이 존재하고, 타 데이터 세트에 비해 난이도가 높은 데이터이다.
  • 실제 우리의 환경에서 잘 동작할 수 있는 모델을 만들기 위해 만들어진 데이터셋이다.

4. Google Open Image

  • csv Format (600개 Class)
  • Size도 매우 크기 때문에 학습에도 오랜 시간이 걸릴 수 있다.

© All rights reserved By Junha Song.