04-26 06:21
Notice
Recent Posts
Recent Comments
관리 메뉴

Scientific Computing & Data Science

[Artificial Intelligence / TensorFlow] TensorFlow Object Detection API를 이용한 다물체 인식하기 Part 1. 본문

Artificial Intelligence/TensorFlow

[Artificial Intelligence / TensorFlow] TensorFlow Object Detection API를 이용한 다물체 인식하기 Part 1.

cinema4dr12 2017. 9. 13. 21:36

Written by Geol Choi | 


지난 6월 Google Research Blog에 "Supercharge your Computer Vision models with the TensorFlow Object Detection API"라는 제목으로 상당히 흥미로운 아티클이 소개되었습니다.



요는, Google이 개발 중이던 In-house Object Detection System이 괄목할만한 결과를 얻었고 COCO Detection Challenge라는 사물인식 경진대회에서 1등을 먹었는데, 이 결과물을 TensorFlow Object Detection API를 제공하여 TensorFlow에서 사용할 수 있도록 하였다는 것입니다.


가장 중요한 것은, 단일 이미지 내에서 다중의 객체의 위치를 파악하고 식별할 수 있는 정확한 ML(Machine Learning) 모델을 만들었다는 것입니다. 이 모델에 사용된 R-FCN, Faster RCNN 알고리즘 등 보다 자세한 내용은 해당 블로그를 참고하시기 바라며, 본 포스팅에서는 이론적 내용보다는 TensorFlow에서 이 모델을 사용할 수 있는 방법에 초점을 맞추도록 하겠습니다.


* 본 튜토리얼을 시리즈로 진행되며, 각 링크는 다음과 같습니다:

개발환경

본 포스팅에서 TensorFlow Object Detection API를 구축한 실행환경은 다음과 같습니다:

  • OS: Windows 7 64bit

  • Anaconda: 4.4.0 (Python 3.6 Version)

  • Spyder: 3.2.1

  • TensorFlow: v1.3 GPU Version

 

실행환경을 Windows 7으로 명시하였지만, 다른 OS에서도 유사한 방법으로 구축이 가능하시리라 생각됩니다. 또한, 굳이 Anaconda가 아니더라도 TensorFlow가 설치되어 있는 기본 Python 3.5+ 환경에서도 가능합니다.

모델 다운로드

TensorFlow/Models GitHub 사이트로부터 모델을 다운로드합니다.

.proto 파일로부터 Python Module 생성

앞서 다운로드 한 모델 파일의 압축을 해제하면 object_detection라는 이름의 폴더 안에 proto라는 이름의 폴더가 있습니다. ProtoProtocol Buffers(protobuf)를 의미하는 것으로 Google에서 개발한 구조화된 데이터의 직렬화 방식이며 통신할 때 데이터를 주고 받을 때 유용합니다.


만약 Protobuf를 사용하는 방법 예제에 대한 정보를 원한다면 저의 이전 포스팅 "Protocol Buffer + ZeroMQ + Python으로 메시징 전달하기"를 참고하시기 바랍니다.


저의 이전 포스팅 내용과 같이 직접 Protocol Buffer의 실행파일인 protoc.exe 파일을 빌드할 수도 있지만, 여간 과정이 번거롭고 귀찮으므로 다음 링크를 클릭하여 미리 빌드되어 있는 파일을 다운로드 합니다: protoc-3.3.0-win32.zip


다운받은 protoc-3.3.0-win32.zip 파일의 압축을 해제하면 bininclude라는 이름의 폴더가 보일 것이며, bin 폴더 내에 protoc.exe 실행파일이 있음을 확인할 수 있습니다.


이제 모델 파일의 models-master/object_detection/protos에 있는 모든 .proto 파일들로부터 각각 Python Module 파일(.py)을 생성할 것인데, 설명을 위해 protoc.exe 파일이 "D:/temp/protoc-3.3.0-win32/bin"에 존재한다고 가정하겠습니다.


Command Line Tool을 실행하여, models-master의 루트 경로로 이동합니다.

가령, "D:/MyProjects/PROGRAMMING/TensorFlow/models-master/"가 models-master의 루트 경로라면,


> d:
> cd D:/MyProjects/PROGRAMMING/TensorFlow/models-master/


과 같이 입력하면 되겠습니다. 경로 이동 후, 다음과 같이 명령을 입력하여 .proto 파일들로부터 Python Module을 생성합니다:


> D:/temp/protoc-3.3.0-win32/bin/protoc.exe object_detection/protos/*.proto --python_out=.



이제 "D:\MyProjects\PROGRAMMING\TensorFlow\models-master\object_detection\protos" 경로를 살펴보면 .proto와 동일한 이름의 .py 파일들이 생성되었음을 확인할 수 있습니다.

Tutorial Code 테스트

object_detection 폴더에 보시면 object_detection_tutorial.ipynb 파일이 있음을 확인할 수 있습니다. 앞서 언급한 Google Research Blog의 결과와 동일한 결과를 얻을 수 있는 Tutorial Code인데 Jupyter 노트북에서 열어서 Python Code를 베껴오던지 아니면 아래의 코드를 이용하시면 되겠습니다.


models-master/object_detection/object_detection_tutorial.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import numpy as np
import os
import six.moves.urllib as urllib
import sys
import tarfile
import tensorflow as tf
import zipfile
 
from collections import defaultdict
from io import StringIO
from matplotlib import pyplot as plt
from PIL import Image
 
# This is needed since the notebook is stored in the object_detection folder.
sys.path.append("..")
 
from utils import label_map_util
 
from utils import visualization_utils as vis_util
 
# What model to download.
MODEL_NAME = 'ssd_mobilenet_v1_coco_11_06_2017'
MODEL_FILE = MODEL_NAME + '.tar.gz'
DOWNLOAD_BASE = 'http://download.tensorflow.org/models/object_detection/'
 
# Path to frozen detection graph. This is the actual model that is used for the object detection.
PATH_TO_CKPT = MODEL_NAME + '/frozen_inference_graph.pb'
 
# List of the strings that is used to add correct label for each box.
PATH_TO_LABELS = os.path.join('data''mscoco_label_map.pbtxt')
 
NUM_CLASSES = 90
 
opener = urllib.request.URLopener()
opener.retrieve(DOWNLOAD_BASE + MODEL_FILE, MODEL_FILE)
tar_file = tarfile.open(MODEL_FILE)
for file in tar_file.getmembers():
    file_name = os.path.basename(file.name)
    if 'frozen_inference_graph.pb' in file_name:
        tar_file.extract(file, os.getcwd())
        
detection_graph = tf.Graph()
with detection_graph.as_default():
    od_graph_def = tf.GraphDef()
    with tf.gfile.GFile(PATH_TO_CKPT, 'rb') as fid:
        serialized_graph = fid.read()
        od_graph_def.ParseFromString(serialized_graph)
        tf.import_graph_def(od_graph_def, name='')
        
label_map = label_map_util.load_labelmap(PATH_TO_LABELS)
categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=NUM_CLASSES, use_display_name=True)
category_index = label_map_util.create_category_index(categories)
 
def load_image_into_numpy_array(image):
  (im_width, im_height) = image.size
  return np.array(image.getdata()).reshape(
      (im_height, im_width, 3)).astype(np.uint8)
  
# For the sake of simplicity we will use only 2 images:
# image1.jpg
# image2.jpg
# image3.jpg
# If you want to test the code with your images, just add path to the images to the TEST_IMAGE_PATHS.
PATH_TO_TEST_IMAGES_DIR = 'test_images'
TEST_IMAGE_PATHS = [ os.path.join(PATH_TO_TEST_IMAGES_DIR, 'image{}.jpg'.format(i)) for i in range(14) ]
 
# Size, in inches, of the output images.
IMAGE_SIZE = (128)
 
with detection_graph.as_default():
  with tf.Session(graph=detection_graph) as sess:
    for image_path in TEST_IMAGE_PATHS:
      image = Image.open(image_path)
      # the array based representation of the image will be used later in order to prepare the
      # result image with boxes and labels on it.
      image_np = load_image_into_numpy_array(image)
      # Expand dimensions since the model expects images to have shape: [1, None, None, 3]
      image_np_expanded = np.expand_dims(image_np, axis=0)
      image_tensor = detection_graph.get_tensor_by_name('image_tensor:0')
      # Each box represents a part of the image where a particular object was detected.
      boxes = detection_graph.get_tensor_by_name('detection_boxes:0')
      # Each score represent how level of confidence for each of the objects.
      # Score is shown on the result image, together with the class label.
      scores = detection_graph.get_tensor_by_name('detection_scores:0')
      classes = detection_graph.get_tensor_by_name('detection_classes:0')
      num_detections = detection_graph.get_tensor_by_name('num_detections:0')
      # Actual detection.
      (boxes, scores, classes, num_detections) = sess.run(
          [boxes, scores, classes, num_detections],
          feed_dict={image_tensor: image_np_expanded})
      # Visualization of the results of a detection.
      vis_util.visualize_boxes_and_labels_on_image_array(
          image_np,
          np.squeeze(boxes),
          np.squeeze(classes).astype(np.int32),
          np.squeeze(scores),
          category_index,
          use_normalized_coordinates=True,
          line_thickness=8)
      plt.figure(figsize=IMAGE_SIZE)
      plt.imshow(image_np)
cs


단, 주어진 테스트 이미지 외에 테스트 이미지(image3.jpg)를 하나 더 넣어보았는데, 이를 위해 원본 코드와 다르게 Line 62의 주석문을 추가하였으며, Line 65에 range(1,3)을 range(1,4)로 수정하였습니다.


추가한 테스트 이미지 image3.jpg는 다음과 같으며, models-master/object_detection/test_images 경로에 저장하면 되겠습니다.




코드 실행하기

이제 거의 다 왔습니다. 만약 Spyder 사용자라면 F5를 눌러 object_detection_tutorial.py을 실행합니다.


실행하여 얻은 결과는 다음과 같았으며, 객체의 위치를 잘 표시하고 또한 객체 인식률도 상당히 좋았음을 확인할 수 있었습니다.





맺음말

이로써 TensorFlow를 이용하여 다물체 인식(Multi-objects Detection) 방법에 대하여 알아 보았습니다.


Part 2.에서는 object_detection_tutorial.py 코드를 분석하고, 응용해 보도록 하겠습니다.

Comments