hyeonzzz's Tech Blog

[boostcourse] 3. Seg&Det - Semantic Segmentation 본문

Deep Learning/CV

[boostcourse] 3. Seg&Det - Semantic Segmentation

hyeonzzz 2024. 6. 17. 13:48

Semantic Segmentation

 

  • Image Classification이 이미지 단위로 분류를 수행하는 거라면, Semantic Segmentation은 픽셀 단위로 분류를 수행하는 것이라 볼 수 있습니다.
  • 하나의 픽셀이 사람에 속하는지, 오토바이에 속하는지, 자동차에 속하는지 등을 분류하는 task인 것이죠.
  • 이때 주의할 점은 여러 명의 사람을 각각 사람1, 사람2, ... 이런 식으로 한명한명 구분하는 것이 아니라 모두 "사람"으로 분류한다는 점입니다.

 

사용되는 곳

  • 의료 이미지
  • 자율주행자동차
  • computational photography
  • 영상 내의 장면을 이해하는 부분

 

Semantic Segmentation Architectures

1. Fully Convolutional Networks (FCN)

 

  • Semantic Segmentation을 위해 제안된 첫 번째 end-to-end 모델 (입력에서부터 출력까지 모두 미분가능한 nn의 형태로 구성되어, 입력과 출력 데이터의 pair만 있으면 학습을 통해서 target task를 해결할 수 있음)
  • 이전에는 다양한 알고리즘을 결합하여 사용했기 때문에 학습가능한 부분이 적었던 반면, FCN의 경우 입력 단부터 출력 단까지 모두 학습가능한 end-to-end 구조를 가집니다. 입력으로 임의의 해상도의 영상을 넣을 수 있고 출력도 입력 해상도에 맞춰서 나올수있는 구조입니다. 
  • 예를 들어 AlexNet의 경우에는 convolutional layer 뒤쪽에 flattening 파트가 있었습니다. 따라서 벡터화를 시키기 때문에 입력 해상도가 호환되지 않으면 학습된 FC layer를 사용하지 못하는 한계가 있었습니다. (convolutional layer의 activation map의 차원이 달라지게 되고 flattening하면 벡터의 길이가 달라지기 때문에 FC layer와 호환이 안되는 문제)
  • FCN은 입력 이미지의 해상도와 상관없이 동작할 수 있어 호환성이 높은 구조를 가진다고 볼 수 있습니다.

 

FCN의 구조

Fully connected layer

  • 이전 convolutional layer에서 출력된 feature map을 flattening하여 입력으로 사용했었습니다.
  • 즉 이미지의 공간 정보를 고려하지 않는 것입니다.
  • fixed dimensional vector가 주어지면 또다른 fixed dimensional vector로 출력해줍니다. 

Fully convolutional layer

  • 입력도 activation map(텐서)이고 출력도 activation map(텐서)입니다.
  • 공간 정보가 유지된 상태로 operation을 수행합니다.
  • 보통 1x1 convolution으로 구현됩니다. 

 

FCN 연산

어떻게 바꿔야 각 픽셀 위치마다 classification을 수행할 수 있도록 만들어 줄 수 있을까요?

 

이전 layer에서 activation map이 출력되면 각 픽셀 위치마다 채널 축으로 flattening하여 각 위치에 해당하는 벡터를 각각 구하면 됩니다. 각 벡터에 대해 fully-connected layer를 적용합니다. 

 

1x1 convolution이 이러한 연산을 수행합니다. 채널축으로 1x1 convolution 커널이 FC layer의 하나의 weight column이라고 볼 수 있습니다. 이를 필터 개수만큼 통과시키고 각 위치마다 FC layer를 별도로 돌립니다. 1x1 convolution을 하기 위해서는 sliding window방식을 적용하기 때문에 공간 정보를 고려할 수 있고, 채널 수 만큼의 feature map을 얻을 수 있는 것입니다.

 

 

따라서 FCN에서도 fully connected layer 대신 1x1 convolution을 사용하였으며, 이를 통해 어떤 입력 사이즈에도 대응가능한 Fully convolutional network를 가질 수 있는 것입니다. 이제 각 위치별로 classification이 가능합니다.

이렇게 semantic segmentation 모델을 만들어서 사용하면 작은 score map을 얻게 됩니다. input이 크지만 output score map은 작은 것입니다. 넓은 receptive field를 확보하기 위한 stride나 pooling layer로 인해 최종 activation map이 저해상도가 되는 문제가 발생합니다. 

 

해결방안 : upsampling layer

작은 activation map을 원래의 입력 사이즈에 맞춰주기 위해서 upsampling layer을 사용합니다. stride와 pooling을 사용하지 않으면 똑같은 수의 layer을 사용했을 때 receptive field의 사이즈가 작기 때문에 영상의 전반적인 context를 파악하지 못합니다.

<trade off> 따라서 일단 activation map을 작게 만들어서 receptive field를 최대한 키우는게 성능에 좋고 그 후 upsampling을 통해서 강제로 resolution을 맞춰줍니다.  

 

upsampling 방법 - Transposed convolution, Upsample and convolution

1) Transposed convolution

Transposed convolution을 보다 쉽게 이해하기 위해 1D로 펼쳐둔 그림은 위와 같습니다.

먼저 입력과 필터를 곱하여 각각 해당하는 위치에 출력하는 방식이며, 겹치는 위치의 경우 그 값을 합하여 출력합니다.

커널사이즈가 중첩된다고 해서 결과를 일정한 간격으로 더해도 되는건가? 하는 의문이 들 수 있습니다. 그렇기 때문에 중첩되는 부분에서 checkerboard artifact가 관찰되는 이슈가 있기도합니다. 따라서 Transposed convolution을 활용할 때, 이러한 이슈를 주의하여 stride와 filter 사이즈를 잘 설정해서 중첩이 생기지 않도록 해주어야 합니다.

 

2) Upsample and convolution

 

이러한 어려움을 극복하면서도 쉽게 활용할 수 있는 방법이 바로 Upsample and convolution입니다.

말그대로 전체 upsampling 과정을 두 단계로 분리하여, 먼저 Nearest-neighbor, Bilinear interpolation 등의 interpolation 과정을 통해 upsample시키고(해상도만 키워줌), 다음으로 학습가능한 형태를 더해주기 위해 이를 convolution layer를 통과시키는 방법입니다. (3x3 등의 conv를 일괄적으로 적용)

 

 

다시 FCN으로 돌아와 그 특징을 살펴보겠습니다. upsampling을 했다 하더라도 해상도가 이미 줄어든 상태에서 잃어버린 정보를 다시 살리는 일은 쉽지 않습니다. FCN의 각 레이어 별로 feature map의 해상도와 의미를 살펴보면 다음과 같습니다.

  • 낮은 레이어의 경우 receptive field 사이즈가 작기 때문에 국지적이고 디테일한 부분들에 대한 특징을 보며 작은 차이에도 굉장히 민감한 경향이 있습니다. fine-grained한 특징에 대한 정보를 가지고 있습니다.
  • 높은 레이어의 경우 해상도는 낮아지지만 큰 receptive field를 가지고 coarse한 레벨, 전반적이고 의미론적인 특징에 대한 정보를 담고 있습니다. 

semantic segmentation을 위해서는 각 픽셀별로 의미를 파악해야하고, 영상 전체를 바라보면서 현재 픽셀이 물체 경계의 안/밖 중 어디에 해당하는지 파악해야 하기 때문에 이 두 가지 정보가 모두 필요합니다.

 

 

따라서 FCN에서는 높은 레이어의 activation map을 upsampling을 통해서 해상도를 크게 올리고 그에 맞춰 중간층의 activation map을 upsampling을 통해서 가져옵니다. 이것을 concatenation해서 최종 출력을 만듭니다. skip connection을 사용하여 낮은 레이어의 feature map을 직접적으로 고려할 수 있도록 설계되었습니다.

  • pool4 & conv7 -> FCN-16s
  • pool3 & pool4 & conv7 -> FCN-8s (가장 많은 activation map을 사용함)

이것을 사용해 각 픽셀마다 class의 score을 출력해줍니다. 

 

 

중간 단계의 특징들을 합치는 것이 큰 도움이 된다는 것을 알 수 있습니다. 

 

<정리>

  • FCN은 end-to-end 네트워크
  • 손으로 만든 별도의 알고리즘을 도입하지 않고 모두 NN layer로 구성되어 있기에 GPU로 병렬처리도 가능하고 굉장히 빠릅니다. 
  • 모델이 해당 task에 대해 학습되기 때문에 좋은 성능을 보여줍니다.
  • low-level feature와 high-level feature를 모두 고려해 좋은 성능을 보여줍니다.

 

2. Hypercolumns for Object Segmentation

Hypercolumn

  • 1x1 convolution을 동일하게 사용합니다. 
  • 낮은 레이어의 특징과 높은 레이어의 특징을 해상도를 맞춰 결합해 사용합니다.
  • 낮은 레이어의 특징과 높은 레이어의 특징의 결합을 가장 강조하고 있다는 점에서 FCN과 차이가 있습니다.

구조는 위의 그림과 같은데, 여기서도 별도의 알고리즘을 사용하여 얻은 물체의 bounding box를 입력으로 사용한다는 점에서 FCN과 차이가 있습니다.

FCN이 더 인용수가 높습니다!!!

 

 

3. U-Net - segmentation 모델의 breakthrough 시작!

다음은 Semantic Segmenation 뿐만 아니라 다양한 Computer Vision task에서 강력한 성능을 보여줬던 U-Net입니다. 

  • 영상과 비슷한 사이즈의 출력을 가지는 모델
  • object detection, segmentation 등 영상의 일부분을 자세히 봐야하는 기술

에서 U-Net에 기원이 있는 경우가 많습니다.

 

U-Net의 특징

  • fully convolutional networks
  • 낮은 층의 feature와 높은 층의 feature의 특징을 잘 결합하는 방법을 skip connection을 통해 제시했습니다.
  • 더 정교한 segmentation 결과를 보여줍니다.

 

U-Net의 구조

 

U-Net은 대칭적인 downsampling, upsampling 과정(contracting path, expanding path)을 거치는 구조를 가지고 있습니다. Downsampling 과정에서는 pooling을 통해 공간해상도를 절반으로 줄이고, 채널 수를 두배로 늘리는 방식으로 feature map을 얻고 있습니다.

 

<Contracting path> - 일반적인 CNN과 동일 / activation map의 해상도 절반으로 줄임 / 채널 수 2배로 늘림

  • 입력 영상을 몇 개의 convolution layer에 통과시킵니다.
  • pooling을 통해서 receptive field를 크게 확보하기 위해서 해상도를 낮추고 채널수를 늘립니다. (64 -> 128)
  • 몇 차례 반복을 통해 작은 activation map을 구하고 여기에 영상의 전반적인 정보가 녹아있다고 가정합니다.

<Expanding Path> - upsampling 부분 / activation map의 해상도 2배로 늘림 / 채널 수 절반으로 줄임

  • 한번에 upsampling하는 대신 점진적으로 activation map의 해상도를 올려줍니다. 
  • contracting path와 반대로 채널 사이즈가 점점 줄어듭니다. (256 -> 128) 대신에 해상도는 늘어납니다.
  • activation map의 해상도와 채널 사이즈는 contracting path에서 오는 (대칭으로 대응되는) layer와 동일하게 맞춰서 낮은 층에 있었던 activation map을 합쳐서 사용할 수 있도록 만들어 줍니다.
  • skip connection을 통해 지역적인 정보를 담고있는 downsampling 과정에서의 feature map을 upsampling 과정의 segmentation map에 concatenation 해주고 있는 것을 확인할 수 있습니다.

 

Concatenation of feature maps provides localized information의 의미

낮은 레이어에서 전달되는 특징이 localized된 정보를 가진다? -> 공간적으로 높은 해상도와 입력이 약간 바뀌는 것만으로 민감한 정보를 제공하기 때문에 경계선이나 공간적으로 중요한 정보들을 뒤쪽 레이어에 바로 전달하는 중요한 역할을 합니다.

 

feature map의 spatial 사이즈(공간해상도)가 홀수는 가지면 어떻게 되는가?

 

각 skip connection을 통해 전달되는 activation map과 expanding path의 activation map이 concatenation이 되려면 해상도가 일치해야 합니다. 

<왼쪽> 7x7 입력이 주어졌을 때 downsampling 과정에서 3x3 혹은 4x4를 출력해야합니다. (일반적으로 버림되어 3x3이 출력됩니다)

<오른쪽> 대칭되는 upsampling 과정에서 3x3 혹은 4x4의 입력이 들어온다면, 7x7 출력으로 복구될 수 있을까요? 아닙니다. 6x6 혹은 8x8이 출력될 것입니다.

허나 Contracting path에서의 feature map을 expanding path에서 대응되는 부분에 concatenation 시켜주기 위해서는 공간해상도가 맞아야 합니다. 따라서 홀수 해상도의 activation map이 나오지 않도록 유의해야 합니다.

 

Pytorch code for U-Net

  • double_conv 함수 정의
  • conv 2개 사이에 relu 
  • 각 contracting path에서는 double_conv 블럭 1번과 maxpool통해서 사이즈(해상도) 줄임 / 채널은 늘림
  • 여기까지는 다른 CNN과 차이 없음

  • upsampling을 위해 ConvTransposed가 사용됨 - 하이퍼파라미터 주목 (stride=2, kernel_size=2) -> 중첩이 안생겨서  checkerboard artifact가 생기지 않음
  • 채널 수 줄어듬

 

4. DeepLab

Semantic Segmantation에서 중요한 한 획을 그었던 모델

  • CRFS 라는 후처리의 존재
  • Atrous Convolution 의 사용

 

1) Conditional Ramdon Fields(CRF) - 후처리 도구로 활용 

그래프 모델링을 통해 픽셀과 픽셀 사이의 관계를 다 이어줍니다.

 

Neural network를 기반으로 semantic segmentation을 수행했을 때 위 그림과 같이 경계가 흐릿한 결과를 확인할 수 있습니다. 이는 neural network이 출력을 입력과 비교하는 feedback loop이 부재한 단순 feed forward 구조를 가지고 있기 때문입니다.

이를 극복하기 위해 rough한 score map과 이미지의 edge를 추출한 경계선을 활용하여 해당 score map이 경계선이 잘 맞아떨어지도록 반복적으로 확산을 시켜줍니다. 반대로 background에 대한 score들은 물체의 경계까지 확산이 되어서 물체의 안쪽과 바깥쪽 모두 확산이 일어나게 만들고, 물체의 mask와 background의 mask가 tight하게 만들어줍니다. 

실제로 그 결과를 확인해보면, 10번의 iteration을 수행한 경우 최우측 이미지와 같이 경계에 잘 들어맞는 segmentation map을 출력하는 것을 확인할 수 있습니다.

 

2) Dilated convolution

 

convolution filter들 사이에 dilation factor 만큼 space를 넣어주는 방법입니다. 이를 통해 실제 convolution filter보다 넓은 영역을 고려할 수 있는, 즉 지수적으로 receptive field를 확장할 수 있는 방법입니다. 파라미터 수는 늘어나지 않습니다.

 

3) Depthwise separable convolution

 

DeepLab v3+에서는 semantic segmentation의 입력 해상도가 워낙 크기 때문에 연산이 복잡해지는 것을 완화하기 위해 dilated convolution을 depthwise separable convolution과 결합하여 사용합니다.

 

<Standard convolution의 경우>

하나의 출력 픽셀에 대한 activation을 얻기 위해 전체 필터 사이즈의 크기를 채널 축으로 내적하는 과정을 거칩니다. 이에 필요한 연산을 따져보면  D_k^2MND_F^2 (6승)입니다.

<Depth-wise convolution>

이 절차를 두 개의 과정으로 나눕니다.

1. 각 채널 축으로 convolution을 수행하여 각 채널에 대한 값을 추출 (채널별로 activation map이 나옴)

2. 이를 point-wise convoltuion, 즉 1x1 convolution을 통해 하나의 activation으로 추출

 

이러한 방식을 사용하게 되면, convolution의 표현력도 유지할 수 있으면서, 필요한 연산은  D_K^2Md_F^2 (5승) + MND_F^2 (4승) 로 standard convolution에 비해 연산량을 크게 줄일 수 있게 됩니다.

 

DeepLab v3+의 구조

 

  • 먼저 dilated convolution을 적용하며, 일반적인 convoltuion 보다 큰 receptive field를 가지는 convoltution을 수행해 feature map을 구합니다.
  • 영역 별로 주변 물체와의 거리, 연관된 정보들이 서로 다르기 때문에 multi-scale을 다룰 수 있도록 spatial pyramid pooling을 수행해줍니다.
  • 이렇게 얻은 feature map들을 concatenation한 이후에 1x1 convolution을 적용하여 하나로 합쳐줍니다.
  • 그 이후에는 Decoder 단에서 낮은 레이어의 feature map pyramid pooling을 거친 feature mapconcatenation 시켜줍니다. 이를 upsampling하여 최종적인 segmentation map을 출력하는 구조입니다.

 

최근에는 semantic segmentation보다 instance segmentation이나 panoptic segmentation 이라는 보다 유용한 segmentation 을 하는 방향으로 빠르게 발전하고 있습니다.