1편: Semantic Segmentation 첫걸음!

Semantic Segmentation이란? 기본적인 접근 방법은?

출처: DeepLab V3+ 논문

Semantic Segmentation 은 컴퓨터비젼 분야에서 가장 핵심적인 분야중에 하나입니다. 단순히 사진을 보고 분류하는것에 그치지 않고 그 장면을 완벽하게 이해해야하는 높은 수준의 문제입니다. 자율주행에서부터 최근 Kaggle 에서 있었던 ‘해상에서 선박 찾기' 까지, 적용분야가 무궁무진 합니다. 다른 컴퓨터비젼 문제들과 마찬가지로 Deep Convolution Neural Network (깊은 신경망)을 적용해서 많은 발전을 이루었습니다.

이번 포스트에서는 Semantic Segmentation 에 대해서 자세히 설명하고, 자주 활용되는 몇가지 접근방법을 알아보겠습니다. 다음 포스트에서는 Google 이 공개한 DeepLab V3+ 모델을 PyTorch 코드와 함께 자세하게 설명하겠습니다.

(구글 AI 블로그에 의하면 Semantic Segmentation 모델인 DeepLab V3+를 사용해서 구글폰인 Pixel 2와 Pixel 2X의 Portrait Mode를 구현했다고 합니다. 아이폰의 Portrait Mode와 비슷한 기능으로, 사진을 찍을 때 인물을 찾아내서 인물을 제외한 배경을 흐릿하게 만듭니다. 아이폰X 는 Portrait Mode 를 딥러닝이 아닌 카메라 2개를 사용해서 같은 효과를 만들었습니다. 상대적으로 저렴(?) 하게 구글이 같은 기능을 구현해 냈다고 할 수 있을까요? )

DeepLab 모델을 이용한 Pixel 2 의 Portrait Mode 기능. 출처

들어가기 전에,

Semantic Segmentation 의 정확한 의미와 목적을 알아보겠습니다. 컴퓨터 비젼의 가장 많이 다뤄지는 문제들은 아래와 같은 것들이 있습니다.

  • Classification (분류): 인풋에 대해서 하나의 레이블을 예측하는 작업. 
    AlexNet, ResNet, Xception 등의 모델
  • Localization/Detection (발견): 물체의 레이블을 예측하면서 그 물체가 어디에 있는지 정보를 제공. 물체가 있는 곳에 네모를 그리는 등 
    YOLO, R-CNN 등의 모델
  • Segmentation (분할): 모든 픽셀의 레이블을 예측 
    FCN, SegNet, DeepLab 등의 모델
출처

더 자세하게는,

Semantic Image Segmentation의 목적은 사진에 있는 모든 픽셀을 해당하는 (미리 지정된 개수의) class로 분류하는 것입니다. 이미지에 있는 모든 픽셀에 대한 예측을 하는 것이기 때문에 dense prediction 이라고도 불립니다.

여기서 주의해야하는 점은 semantic image segmentation 은 같은 class의 instance 를 구별하지 않는다는 것입니다. 쉽게말해서, 밑에 가족사진처럼 같은 class 에 속하는 object (사람이 4명)가 있을 때

사람을 따로 분류하지 않고, 그 픽셀 자체가 어떤 class 에 속하는지에만 관심이 있습니다 (오른쪽 사진). 왼쪽 사진처럼 instance 를 구별하는 모델은 따로 instance segmentation 이라고 불립니다.

왼쪽: instance segmentation. 오른쪽: semantic segmentation

유명한 대회인 COCO detection challenge는 80개의 class, PASCAL VOC Challenge 는 21개의 class를 가지고 있습니다.

Semantic Segmentation의 예시

Semantic Segmentation Task 이해하기

Input
RGB color 이미지 (height X width X 3) 또는 흑백 (height X width X 1) 이미지

Output
각 필셀별 어느 class 에 속하는지 나타내는 레이블을 나타낸 Segmentation Map

출처. 주의: 단순화한 이미지입니다. 실제로는 인풋과 같은 resolution의 segmentation map을 나타냅니다.

One-Hot encoding 으로 각 class 에 대해 출력채널을 만들어서 segmentation map을 만듭니다. Class의 개수 만큼 만들어진 채널을argmax 를 통해서 위에 있는 이미지 처럼 하나의 출력물을 내놓습니다.

각 Class 별로 출력채널을 만든 후 argmax 사용

다양한 Semantic Segmentation 방법들

AlexNet, VGG 등 분류에 자주 쓰이는 깊은 신경망들은 Semantic Segmentation 을 하는데 적합하지 않습니다. 일단 이런 모델은 parameter 의 개수와 차원을 줄이는 layer 를 가지고 있어서 자세한 위치정보를 잃게 됩니다. 또한 보통 마지막에 쓰이는 Fully Connected Layer에 의해서 위치에 대한 정보를 잃게 됩니다.

만약 공간/위치에 대한 정보를 잃지 않기 위해서 Pooling 과 Fully Connected Layer 를 없애고 stride 가 1이고 Padding 도 일정한 Convolution 을 진행할 수도 있을 것입니다. 인풋의 차원은 보존하겠지만, parameter 의 개수가 많아져서 메모리 문제나 계산하는데 비용이 너무 많이 들어서 현실적으로는 불가능 할 것입니다.

이 문제의 중간점을 찾기 위해서 보통 Semantic Segmentation 모델들은 보통 Downsampling & Upsampling 의 형태를 가지고 있습니다.

Semantic Segmentation: 인코더 — 디코더의 형태
  • Downsampling: 주 목적은 차원을 줄여서 적은 메모리로 깊은 Convolution 을 할 수 있게 하는 것입니다. 보통 stride 를 2 이상으로 하는 Convolution 을 사용하거나, pooling을 사용합니다. 이 과정을 진행하면 어쩔 수 없이 feature 의 정보를 잃게됩니다. 
    마지막에 Fully-Connected Layer를 넣지 않고, Fully Connected Network 를 주로 사용합니다. FCN 모델에서 위와같은 방법을 제시한 후 이후에 나온 대부분의 모델들에서 사용하는 방법입니다.
  • Upsampling: Downsampling 을 통해서 받은 결과의 차원을 늘려서 인풋과 같은 차원으로 만들어 주는 과정입니다. 주로 Strided Transpose Convolution 을 사용합니다.

논문들에서 Downsampling 하는 부분을 인코더, Upsampling 하는 과정을 디코더이라고 부릅니다. (GAN 에서 쓰이는 모델과 비슷한 형태 & 이름을 가지고 있네요) 
인코더를 통해서 입력받은 이미지의 정보를 압축된 벡터에 표현하고, 디코더를 통해서 원하는 결과물의 크기로 만들어냅니다.

이러한 인코더 — 디코더의 형태를 가진 유명한 모델들로 FCN, SegNet, UNet 등이 있습니다. Shortcut connection 을 어떻게 하느냐에 따라서 몇가지의 모델들이 있습니다 (e.g. pooling indices을 활용한 SegNet, layer를 복사해서 합치는 U-Net등).

이런 형태의 모델을 상용화시키는데 큰 몫을 한 FCN 에 대해서 조금 자세히 알아보겠습니다.

Fully Convolutional Network for Semantic Segmentation (FCN)
2014년에 Long et al.의 유명한 논문인 Fully Convolutional Network가 나온 후 Fully Connected layer 가 없는 CNN이 통용되기 시작했습니다. 어떤 크기의 이미지로도 segmentation map 을 만들 수 있게 되었고 그 때 SoTA였던 Patch Classification 보다 훨씬 빠르게 결과를 낼 수 있었습니다. 이후에 나온 Semantic Segmentation 방법론은 거의 대부분 FCN 을 기반으로 했다고 할 정도로 큰 임팩트를 주었습니다.

모델의 특징:

  • VGG16으로부터 Tranfer Learning 을 사용한다
  • VGG16의 마지막 layer 인 fully connected layer 을 1x1의 convolution layer 로 바꾼다. 이 부분에서 이 모델의 이름인 ‘fully convolutional’이 나온다. 이를 통해서 낮은 해상도의 Class Presence Heat Map 을 얻는다 
    Fully Connected Layer를 없앤 이유는 마지막에 이 Layer 를 거치고 나면 위치 정보가 사라지는 문제가 있기 때문입니다. Segmentation 은 위치정보가 핵심적이기 때문에 심각한 문제였습니다.
  • Transposed Convolution 을 통해서 이 낮은 해상도의 heap map 을 업샘플링 해서 인풋과 같은 크기의 맵을 만든다
  • 업샘플링을 할 때 VGG16의 낮은 layer 의 특징맵을 더한다
  • 여러 단의 Convolutional Layer 중에 후반부에 있는 특징맵을 결합하면 중요한 정보를 얻을 수 있다는 것을 설명했습니다
  • 각 Convolution Block 이 끝난 후 Skip Connection 을 통해서 이전에 pooled 된 특징들을 다시한번 합쳐준다

하지만, FCN 모델은 정해진 Receptive Field 를 사용해서 작은 물체들은 무시가 되거나 이상하게 인식 될 수 있고, 큰 물체를 작은 물체로 인식하거나 일정하지 않은 결과가 나올 수 있습니다. 또한, Pooling 을 거치면서 해상도가 줄어든 것을 Upsampling을 통해서 복원하는 방식을 사용해서, 결과가 정확하지 않다는 문제점을 가지고 있었습니다.

논문에서 제시한 FCN 모델의 문제점

2. Dilated/Atrous Convolution 을 사용하는 방법

Deeplab 이 제시하는 방법으로, 신호가 소멸되는것을 제어하고 다양한 크기의 특징을 익히는 방법을 제시합니다. Atrous Convolution 은 dilation rate (확장 비율)이라는 새로운 변수를 사용합니다. 이 비율은 커널에서 사용할 값들 사이에 얼마 만큼의 공간을 넣어줄 것인지에 대한 것입니다. 커널 안에 공간이 없는 일반적인 convolution 은 확장비율은 1로 정의합니다. 3 x 3 의 크기의 커널이 2의 확장비율을 갖는다면 실제로는 5 x 5 커널의 시야를 갖게 됩니다. 위와 같은 방법은 동일한 계산 비용으로 보다 넓은 시야를 갖을 수 있게 합니다.

Atrous Convolution

Deeplab V3는 ImageNet에서 학습된 ResNet을 기본적인 특징 추출기로 사용합니다. ResNet의 마지막 블럭에서는 여러가지 확장비율을 사용한 Atrous Convolution을 사용해서 다양한 크기의 특징들을 뽑아낼 수 있도록 합니다.

또한 이전 Deeplab 버젼에서 소개되었던 Atrous Spatial Pyramid Pooling (ASPP)을 사용합니다. 새로운 아이디어라기 보다는, 좋은 성능을 보였던 모델들의 특징들을 섞어놓은 모델입니다. 다양한 확장비율을 가진 커널을 병렬적으로 사용한 convolution 입니다.

지금까지 Semantic Segmentation 이 무엇이고 흔히 사용되는 접근방법에 대해서 알아보았습니다. 다음 포스트에서는 DeepLab V3+ 의 논문을 리뷰하고 차근차근 PyTorch코드와 함께 알아보겠습니다.

Segmentation Dataset

읽을거리

참고: