반응형

www.analyticsvidhya.com의 [] 내용임.

www.analyticsvidhya.com의 객체 탐지관련 글 4개를 차례로 다룰 예정이며, 이 글은 그 첫번째이다.

Introduction

    우리가 이미지를 보았을 때, 우리의 뇌는 즉시 이미지에 포함된 객체를 인식한다. 반면, 기계는 이들 객체를 인식하기 위해 많은 시간과 훈련 데이터가 필요하다. 하지만 근래의 하드웨어와 딥러닝 발전으로 컴퓨터 비전 분야는 전체적으로 더 쉽고 더 직관적으로 바뀌었다.

    아래 이미지를 예제로 확인해보자. 시스템은 믿기 힘들 정도의 정확도로 이미지내 다른 객체를 확인할 수 있다.


    객체 탐지 기술은 다양한 산업에서 빠른 채택 비율을 보여왔다. 이는 자율주행 차량이 안전하게 운행하고 군중속에서 난폭한 행동을 찾아내는 데 도움이 된다.

    이 글에서는 객체 탐지가 무엇인지 이해하고 이 분야에서 문제를 해결할 수 있는 몇가지 다른 접근을 볼 것이다. 그리고 파이썬으로 객체 탐지 시스템을 구축할 것이다.

    Note : 이 글은 이전에 간단한 이미지 처리 문제를 해결했거나 기본적인 딥러닝에 대한 지식이 있다고 가정하고 진행한다. 그렇지 않다면 아래 링크의 글을 우선 참조 바란다.


Table of Contents

  • 객체 탐지란 무엇인가?
  • 객체 탐지 문제를 해결하기 위해 사용할 수 잇는 다른 방법들
    • 방법 1 : Naive way (Divide and Conquer) - 나이브 방법 (분할 정복)
    • 방법 2 : Increase the number of divisions - 분할수 증가
    • 방법 3 : Performing structured divisions - 구조화된 분할 수행
    • 방법 4 : Becoming more efficient - 더 효과적으로
    • 방법 5 : Using Deep Learnging for feature selection and to build and end-to-end approach - 특징 선택과 단대단 방식을 구축하기 위한 딥러닝 사용
  • 기술 습득 : ImageAI 라이브러리를 사용한 객체 탐지 모델 구축 방법

객체 탐지란 무엇인가?

    최신 모델 구축에 대해 알아보기 전에 우선, 객체 탐지가 무엇인가에 대해 알아보자. (가설로) 자율주행 차를 위한 보행자 감지 시스템을 구축한다고 해보자. 차량이 아래와 같은 이미지를 갭쳐했다고 가정하면, 이 이미지는 어떻게 설명할 수 있을까?


    이 이미지는 차량이 사각형 근처에 있고 몇 사람이 차량 앞에서 길을 건너고 있는 것을 나타낸다. 신호등이 명확하게 보이지 않기 때문에 차량의 보행자 인식 시스템은 보행자를 피할 수 있도록 정확히 어디에서 보행자가 걷고 있는지를 식별해야만 한다.

    그러면 차량의 시스텀이 이를 확실하게 하기 위해 하는 것은 무엇일까? 시스템이 하는 것은 이미지에서 사람이 어디에 있는지를 정확히 찾아내기 위해 이 사람들 주변에 바운딩 박스를 만드는 것이다. 그리고 그에 맞춰 작은 사고를 피하기 위해 어떤 경로로 갈것인가를 결정한다.


    객체 탐지를 대한 목적은 아래의 두가지이다.

  • 이미지에 있는 모든 객체가 무엇이고 어디에 있는지 식별하기 위해
  • 관심 객체를 걸러내기 위해

객체 탐지 문제를 해결하기 위해 사용할 수 잇는 다른 방법들

    이제 문제의 상태를 알았다. 그러면 이를 해결하기 위해 가능한 방법(또는 여러가지 방법)은 무엇일까? 여기서는 이미지내 객체를 탐지하기 위해 사용할 수 있는 몇가지 기술을 살펴본다.

방법 1 : Naive way (Divide and Conquer)

    사용할 수 있는 가장 간단한 방법은 이미지를 네조각으로 나누는 것이다.

  • 좌상단
    
    
  • 우상단
    
    
  • 좌하단
    
    
  • 우하단
    
    

    다음 단계는 각 부분을 이미지 분류기에 전달하는 것이다. 이 분류기는 이미지의 부분에 보행자기 있는지에 대한 결과를 제공한다. 만약 있다면, 원본 이미지의 해당 부분에 표시한다. 이 결과(output)은 아래와 같을 것이다.


    이는 처음으로 시도하기 좋은 방법이지만, 훨씬 더 정확하고 정밀한 시스템이 필요하다. 단지 객체 일부의 위치를 찾는 것은 비극적인 결과와 이어지기 때문에 전체 객체(이번 예의 경우에는 사람)를 식별해야 한다.

방법 2 : Increase the number of division

    방법 1도 잘 동작했지만 다른 할 수 있는 것은 없을까? 시스템에 입력하는 조각(부분)의 수를 기하급수적으로 늘리는 것으로 이를 개선할 수 있다. 이 방법의 결과는 아래와 같을 것이다.

아마도 이 방법은 전형적인 Region Proposal을 이야기 하는 것으로 보인다.


    이 방법은 결국 은해와 저주에 처하게 된다. 물론 이 방법이 naive 방법보다 좀 더 좋아 보이긴 하지만, 비슷하게 같은 많은 바운딩 박스로 벌집을 만들어 버린다. 이것이 한가지 문제이고 문제 해결을 위한 좀 더 구조적인 방법이 필요하다.

방법 3 : Performing structured divisions

    좀 더 구조화된 방법으로 객체 탐지 시스템을 구축하기 위해 아래와 같은 단계를 따를 수 있다.

Step 1 : 이미지를 아래와 같이 10 X 10 격자구조로 나눈다.


Step 2 : 각 조각(patch)에 대해 중심을 정의한다.

Step 3 : 각 중심에 대해서 다른 높이와 가로세로 비율(aspect ratio)로 세조각을 만든다.


Step 4 : 생성한 모든 조각(위의 경우 10 X 10 X 3 = 300 개)을 예측을 위한 이미지 분류기에 전달한다.

좀 더 구조적이고 훈련된 방법은 아래와 같은 결과를 보일 것이다.


    하지만 이는 더 개선될 수 있다.

방법 4 : Becoming more efficient

    이전 방법은 괜찮은 정도지만 최적화로 이를 좀 더 효율적으로 구축할 수 있다. 방법 3에 대해서 보자면, 모델을 좀 더 좋게 하기 위해 두가지를 할 수 있다.

  1. 격자 크기 늘리기 : 10 크기를 사용하느 대신 20과 같이 크기를 늘릴 수 있다.

  1. 3조각 대신, 다양한 높이와 가로세로 비율로 더 많은 조각 가져오기 :
    여기서는 단일 앵커에서 9개의 모양을 가져올 수 있다. 즉 세개의 사각형 조각, 다른 높이인 6개의 수직/수평 직사각형 조각이다. 이것들은 조각의 다른 가로세로 비율을 제공한다.

    다시 말하면, 이거은 장/단점이 있다. 두 방법 모두 좀 더 세밀한 수준이다. 하지만, 이 방법은 다시 이미지 분류 모델로 전달해야 하는 조각의 수를 늘린다.

    여기서 할 수 있는 것은 모두를 가져오는 대신 선택적으로 조각을 가지고 오는 것이다. 예를 들면, 조각이 실제로 배경인지 아니면 잠재지ㅓㄱ으로 객체를 포함하는지를 예측하기 위한 중간 분류기(intermmediate classifier)를 만들 수 있다. 이는 이미지 분류 모델이 처리해야 하는 조각을 기하급수적으로 줄인다.

    더 할 수 있는 최적화 한가지는 동일한 것에 대한 예측을 줄이는 것이다. 방법 3의 결과를 다시보자.


    보이는 것과 같이 예측 바운딩 박스 두개 모두 기본적으로 동일 사람이다. 여기서 두 바운딩 박스 중 하나를 선택하기 위한 옵션을 갖는다. 따라서 에측을 하기 위해서는 동일한 것을 나타내는 모든 바운딩 박스를 고려하고 사람을 탐지할 가장 높은 가능성을 가진 하나를 골라야 한다.

    이런 최적화 방법 모두는 지금까지 꽤 괜찮은 예측을 했다.

방법 5 : Using Deep Learning for feature selection and to build an end-to-end approach

    딥러닝은 객체 탐지 분야에서 많은 잠재력을 가지고 있다.

  • 원본 이미지에서 조각을 가져오는 대신, 차원을 줄이기 위해(reduce dimension) 신경망에 원본 이미지를 전달할 수 있다.
  • 또한 선택적인 조각을 얻기 위해(suggest selective patches) 신경망을 사용할 수 있다.
  • 가능한 원래 바운딩 박스와 가깝게 예측하기 위해 딥러닝 알고리즘을 강화할 수 있다. 이는 알고리즘이 더 정확한 바운딩 박스 예측을 할 수 있게 한다.

    이제 각각의 문제를 해결하기 위해 다른 신경망을 훈련하는 것 대신 스스로 모든 문제 해결을 시도하는 하나의 심층 신경망을 사용할 수 있다. 이것의 장점은 신경망의 더 작은 콤포넌트 각각이 동일한 신경망의 다른 부분을 최적화하는데 도움이 된다는 것이다. 이것은 전체 딥러닝 모델을 묶어서 훈련할 수 있게 한다.

    결과는 여태까지 본 모든 접근방법중 최고의 성능을 보인며 아래와 같을 것이다.



Getting Technical: How to build an Object Detection model using the ImageAI library

    컴퓨터 비전 작업을 위한 최신 머신러닝 알고리즘을 지원하는 파이썬 라이브러리인 ImageAI사용하여 객체 탐지 시스템을 구축해 보자.

    예측을 얻기위해 객체 탐지 모델을 실행하는 것은 꽤 간단하다. 시작하기 위해 복잡한 설치 스크립트를 사용할 필요가 없다. 또한 예측을 위한 GPU도 필요없다. 방법 5에서 본 예측 결과를 얻기 위해 이 ImageAI 라이브러리를 사용할 것이다.

    객체 탐지 모델을 생성하기 전에 시스템을 셋팅해야한다. 로컬 시스템에 ㅇ나콘다를 설치하고 아래 단계를 따라 진행한다.

Step 1 : Python 3.6 버전으로 아나콘다 환경 생성


conda create -n retinanet python=3.6 anaconda

Step 2 : 환경을 활성화하고 필요한 패키지 설치


source activate retinanet
conda install tensorflow numpy scipy opencv pillow matplotlib h5py keras

Step 3 : ImageAI 라이브러리 설치


pip install https://github.com/OlafenwaMoses/ImageAI/releases/download/2.0.1/imageai-2.0.1-py3-none-any.whl

Step 4 : 예측을 하기 위해 필요한 사전훈련된 모델을 다운로드

이 모델은 RetianNet을 기본으로 한다. [다운로드- RetinaNet Pretrained Model]

Step 5 : 다운로드한 파일을 작업 디렉토리에 복사.

Step 6 : 이미지 [다운로드]하여 image.png로 저장

Step 7 : 아래 코드를 실행


from imageai.Detection import ObjectDetection
import os

execution_path = os.getcwd()

detector = ObjectDetection()
detector.setModelTypeAsRetinaNet()
detector.setModelPath( os.path.join(execution_path , "resnet50_coco_best_v2.0.1.h5"))
detector.loadModel()
custom_objects = detector.CustomObjects(person=True, car=False)
detections = detector.detectCustomObjectsFromImage(input_image=os.path.join(execution_path , "image.png"), output_image_path=os.path.join(execution_path , "image_new.png"), custom_objects=custom_objects, minimum_percentage_probability=65)


for eachObject in detections:
   print(eachObject["name"] + " : " + eachObject["percentage_probability"] )
   print("--------------------------------")

    이 코드는 이미지에 대한 바운딩 박스를 포함한 image_new.png를 생성한다.

Step 8 : 이미지를 출력하기 위해 아래 코드를 실행 (이 부분은 추후 Matplotlib를 사용한 코드로 변경할 예정이다.)


from IPython.display import Image
Image("image_new.png")

반응형

+ Recent posts