약초의 숲으로 놀러오세요

Mask R-CNN 논문(Mask R-CNN) 리뷰 본문

Computer Vision/Object Detection

Mask R-CNN 논문(Mask R-CNN) 리뷰

herbwood 2021. 2. 14. 19:49

이번 포스팅에서는 Mask R-CNN 논문(Mask R-CNN)을 읽고 리뷰해보도록 하겠습니다. Mask R-CNN은 일반적으로detection task보다는  instance segmentation task에서 주로 사용됩니다. Segmentation 논문을 읽어본 경험이 없었지만 Faster R-CNN에 기반한 모델이기 때문에 이해하기 용이했던 것 같습니다. 논문 리뷰에 앞서 Instance segmentation에 대해 가볍게 짚고 넘어가도록 하겠습니다. 

 

Instance segmentation

Instance segentation은 이미지 내에 존재하는 모든 객체를 탐지하는 동시에 각각의 경우(instance)를 정확하게 픽셀 단위로 분류하는 task입니다. Semantic segmentation이 동일하게 분류된 카테고리의 instance를 구분하지 않는다는 점에서 차이가 있습니다. 즉 객체를 탐지하는 object detection task와 각각의 픽셀의 카테고리를 분류하는 semantic segmentation task가 결합된 것입니다. 


Preview

Mask R-CNN architecture

Mask R-CNN은 Faster R-CNN의 RPN에서 얻은 RoI(Region of Interest)에 대하여 객체의 class를 예측하는 classification branch, bbox regression을 수행하는 bbox regression branch와 평행으로 segmentation mask를 예측하는 mask branch를 추가한 구조를 가지고 있습니다. mask branch는 각각의 RoI에 작은 크기의 FCN(Fully Convolutional Network)가 추가된 형태입니다. segmentation task를 보다 효과적으로 수행하기 위해 논문에서는 객체의 spatial location을 보존하는 RoIAlign layer를 추가했습니다. 

Main Ideas 

Mask branch

Faster R-CNN architecture

Faster R-CNN은 backbone network를 통해 얻은 feature map을 RPN(Region Proposal Network)에 입력하여 RoIs(Region of Interests)를 얻습니다. 이를 RoI pooling을 통해 고정된 크기의 feature map을 얻고 이를 fc layer에 입력한 후 classification branch와 bbox regression branch에 입력하여 class label과 bbox offset이라는 두 가지 결과를 예측합니다.

 

Mask branch

Mask R-CNN은 두 branch와 평행(pararell)으로 segmentation mask를 예측하는 mask branch가 추가된 구조입니다. 위의 그림은 정식 Mask R-CNN의 구조가 아닙니다. Mask branch가 추가된 구조라는 점만 시각적으로 확인하시기 바랍니다. RoI pooling을 통해 얻은 고정된 크기의 feature map을 mask branch에 입력하여 segmentation mask를 얻습니다. 여기서 말하는 segmentation mask는 class에 따라 분할된 이미지 조각(segment)입니다. 

 

segmentation task는 픽셀 단위로 class를 분류해야 하기 때문에 detection task보다 더 정교한 spatial layout(공간에 대한 배치 정보)를 필요로 합니다. 이를 위해 mask branch는 여러 개의 conv layer로 구성된 작은 FCN의 구조를 띄고 있습니다. class label이나 bbox offset이 fc layer(이하 fully connected layer)에 의해 output vector로 붕괴(collapse)되는 것과 달리 mask는 이미지 내 객체에 대한 공간 정보를 효과적으로 encode하는 것이 가능합니다. 

 

Binary mask

mask branch는 각각의 RoI에 대하여 class별로 binary mask를 출력합니다. 이는 mask prediction이 classfication branch에 의존하는 기존의 방식과는 반대됩니다. 기존의 instance segmentation 모델은 하나의 이미지에서 여러 class를 예측한 반면, Mask R-CNN은 class별로 mask를 생성한 후 픽셀이 해당 class에 해당하는지 여부를 표시합니다. 이는 mask branch와 classification branch를 분리(decouple)시킨다는 것을 의미합니다. 논문에서는 두 branch를 결합하는 방식을 사용할 경우 성능이 크게 하락했다고 합니다. 

 

mask branch는 최종적으로 $K^2m$ 크기의 feature map을 출력합니다. 여기서 m은 feature map의 크기이며, K는 class의 수를 의미합니다. 이후 post-processing 과정이 있지만 이는 Mask R-CNN 학습 과정에서 자세히 살펴보도록 하겠습니다. 

RoIAlign

RoI pooling을 사용하면 입력 이미지 크기와 상관없이 고정된 크기의 feature map을 얻을 수 있다는 이점이 있습니다. 하지만 논문에서는 RoI pooling으로 인해 얻은 feature와 RoI 사이가 어긋나는 misalignment가 발생한다고 주장합니다. 이러한 어긋남은 pixel mask를 예측하는데 매우 안 좋은 영향을 끼친다고 합니다. 기존에 사용했던 RoI pooling와 문제점을 짚은 후 논문에서 제시한 RoIAlign 방법을 살펴보도록 하겠습니다. RoI pooling과 RoIAlign에 대한 설명은 많은 부분 Kemal Erdem님의 블로그를 참고했습니다. 

RoI pooling

먼저 RoI pooling에 앞서 RPN을 통해 얻은 RoI를 backbone network에서 추출한 feature map의 크기에 맞게 투영(projection)하는 과정이 있습니다. 위의 그림의 경우 RoI의 크기는 145x200이며, feature map은 16x16입니다. 이를 sub sampling ratio(=32)에 맞게 나눠주면 projection을 수행한 feature map은 4.53 x 6.25크기를 가지게 됩니다. 하지만 픽셀 미만의 크기로 분할하는 것은 불가능하기 때문에 크기에서 정수값을 사용하여 4x6 크기의 feature map을 얻습니다. 

 

이후 위의 그림에서는 3x3 크기의 고정된 feature map을 얻기 위해 4x6 크기의 RoI에 대하여 RoI pooling을 수행합니다. 이 과정에서 고정된 크기에 맞추기 위해 stride는 1x2로 설정됩니다. 최종적으로 3x3 크기의 feature map을 얻을 수 있습니다. 

Quantization losses

논문에서는 RoI pooling 방식이 quantization 과정을 수반하여 misalignment를 유도한다고 보았습니다. quantization은 실수(floating) 입력값을 정수와 같은 이산 수치(discrete value)으로 제한하는 방법입니다. 위의 그림은 RoI pooling 시 quantization으로 인해 소실되는 정보를 보여주고 있습니다. 왼쪽 그림을 통해 RoI projection을 수행하는 과정에서 소수점 부분이 반올림 되면서 초록색과 파란색 영역에 대한 정보가 손실됨을 알 수 있습니다. 또한 오른쪽 그림은 RoI pooling 시 stride를 반올림하게 되면서 feature map의 마지막 row에 대한 정보가 소실됨을 보여주고 있습니다. 

 

quantization으로 인한 misalignment는 translation invariant한 classification task 시에는 큰 영향이 없지만 pixel 단위로 mask를 예측하는 segmentation task 시에는 매우 안 좋은 영향을 끼치게 됩니다. 논문에서는 이러한 문제를 해결하기 위해 각각의 RoI에 대하여 RoIAlign 방법을 적용합니다. RoIAlign은 다음과 같은 순서로 동작합니다. 

 

1) 먼저 RoI projection을 통해 얻은 feature map을 quantization 과정 없이 그대로 사용합니다. 그 다음 출력하고자 하는 feature map의 크기에 맞게 projection된 feature map을 분할해줍니다. 위의 예시에서는 3x3 크기의 feature map으로 출력할 것이기 때문에 width, height를 각각 3등분해줍니다.

 

2) 분할된 하나의 cell에서 4개의 sampling point를 찾습니다. 이는 cell의 height, width를 각각 3등분하는 점에 해당합니다. 

 

3) 그 다음 Bilinear interpolation을 적용합니다. 

Bilinear interpolation

Bilinear interpolation은 2차원 좌표 상에서 두 좌표가 주어졌을 때 중간에 있는 값을 추정하는 방법입니다. 이를 구하는 공식은 다음과 같습니다. 

 

$$P \approx {{y_2 - y} \over {y_2 - y_1}}({{x_2-x} \over {x_2-x_1}}Q_{11} + {{x-x_1} \over {x_2-x_1}}Q_{21}) + {{y-y_1} \over {y_2-y_1}}({{x_2-x} \over {x_2-x_1}}Q_{12} + {{x-x_1} \over {x_2-x_1}}Q_{22})$$

 

여기서 $x, x_1, x_2, y, y_1, y_2$는 2)번 과정에서 얻은 4개의 sampling point의 좌표이며, $Q_{11}, Q_{21}, Q_{12}, Q_{22}$는 sampling point에 인접한 cell의 값입니다. 위의 공식에 따라 입력된 feature의 각각의 RoI bin의 4개의 sampled location의 값을 연산합니다. 

 

 

4) 2)~3) 과정을 모든 cell에 대하여 반복합니다. 

5) 하나의 cell에 있는 4개의 sampling point에 대하여 max pooling을 수행합니다. 

 

위와 같은 RoIAlign 방법을 통해 feature와 RoI 사이가 어긋나는 misalignment 문제를 해결합니다. 이를 통해 RoI의 정확한 spatial location을 보존하는 것이 가능해집니다. 이 변화를 통해 mask accuracy가 크게 향상된다고 합니다. 

Loss function

$$L = L_{cls} + L_{box} + L_{mask}$$

 

Mask R-CNN은 위와 같이 구성된 multi-task loss function을 통해 네트워크를 학습시킵니다. $L_{cls}$는 classification loss, $L_{box}$는 bounding box loss로 Faster R-CNN과 동일합니다. $L_{mask}$는 mask loss로 binary cross entropy loss입니다. mask branch에서 출력한 $K^2m$ 크기의 feature map의 각 cell에 sigmoid function을 적용한 후 loss를 구합니다. 

 

기존의 segmentation 모델이 픽셀별로 서로 다른 class를  softmax loss function을 사용했습니다. 하지만 Mask R-CNN은 class branch와 mask branch를 분리하여 class별로 mask를 생성한 후 binary loss를 구합니다. 

Backbone network

Mask R-CNN은 backbone network로 ResNet-FPN을 사용합니다. 

Training Mask R-CNN

전체적인 구조는 Faster R-CNN에 기반하지만 FPN이 추가되었고, 이미지 및 feature map에 대한 전처리, 후처리를 필요로 하기 때문에 학습 과정이 살짝 복잡합니다😭. 심지어 Faster R-CNN에서 사용되었던 4-step alternating training 방법을 통해 네트워크를 학습시킨다고 합니다🔥

 

1) Input image Pre-processing

이미지를 네트워크에 입력하기에 앞서 전처리 과정이 있습니다. 원본 이미지의 width, height 중 더 짧은 쪽(shorter edge)이 target size로 resize됩니다. 그리고 더 긴 쪽(longer edge)은 aspect ratio를 보존하는 방향으로 resize됩니다. 만약 더 긴 쪽이 maximum size를 초과하면 maximum size로 resize되고 더 짧은 쪽이 aspect ratio를 보존하는 방향을 resize됩니다. target size, maximum size의 디폴트값은 각각 800, 1333입니다. 

 

  • Input : image
  • Process : image pre-processing
  • Output : resized image

2) Feature pyramid by backbone network

ResNet-FPN

전처리된 이미지를 ResNet-FPN backbone network에 입력하여 feature pyramid {P2, P3, P4, P5, P6}를 얻습니다.  feature pyramid에 대한 자세한 내용은 FPN 논문 리뷰 포스팅을 참고하시기 바랍니다. 

 

  • Input : resized image
  • Process : constructing feature pyramid 
  • Output : feature pyramid {P2, P3, P4, P5, P6}

3) Region proposal by RPN

2)번 과정에서 얻은 feature pyramid별로 RPN(Region Proposal Network)에 입력하여 objectness score과 bbox regressor를 가진 Region proposal을 출력합니다. 

 

현재 학습과정에서 Anchor generation layer 역시 생략되어 있습니다. Mask R-CNN에 대한 전체적인 과정을 살펴보고자 생략했으니 자세한 내용은 Faster R-CNN 논문 리뷰 포스팅을 참고하시기 바랍니다. 

 

  • Input : feature pyramid {P2, P3, P4, P5, P6}
  • Process : Region proposal
  • Output : Region proposals with objectness score and bbox regressor per feature pyramid {P2, P3, P4, P5, P6}

4) Select best RoI by Proposal layer

그 다음 RPN을 통해 얻은 Region proposal 중 최적의 RoI를 선정합니다. 이 과정은 Faster R-CNN의 Proposal layer, Anchor target layer, Proposal target layer에서 수행하는 과정입니다. 

 

1) objectness score가 높은 top-k개의 anchor를 선정합니다. 학습 시 k=12000로 설정합니다.

2) bbox regressor에 따라 anchor box의 크기를 조정해줍니다.

3) 이미지의 경계를 벗어나는 anchor box를 제거해줍니다.

4) threshold=0.7로 지정하여 Non maximum suppression을 수행합니다.

5) 지금까지의 과정은 각각의 feature pyramid level별({P2, P3, P4, P5, P6})로 수행되었습니다. 이전 과정까지 얻은 모든 feature pyramid level의 anchor box에 대한 정보를 결합(concatenate)해줍니다.

6) 마지막으로 결합된 모든 anchor box에 대하여 objectness score에 따라 top-N개의 anchor box를 선정합니다. 학습 시 N=2000로 설정합니다. 

 

최종적으로 수많은 anchor box 중 최적의 N개의 box만이 학습에 사용됩니다.

 

  • Input : Region proposals 
  • Process : selecting top-N RoIs
  • Output : top-N RoIs

5) feature map by RoI Align layer

$$k = [k_0 + log_{2}(\sqrt{wh}/224)]$$

 

backbone network를 통해 여러 scale을 가진 feature pyramid {P2, P3, P4, P5, P6}가 생성됩니다. 그리고 RPN과 Proposal layer를 거쳐 N개의 RoI가 선정됩니다. feature pyramid는 multi-scale feature map이기 때문에 RoI를 어떤 scale의 feature map과 매칭시킬지를 결정하는 과정이 필요합니다. 위와 같은 공식에 따라 RoI와 feature pyramid를 매칭시켜줍니다. w, h는 RoI의 크기를 의미하며, k는 feature pyramid의 level의 index입니다. 

 

그 다음 RoI와 feature map을 사용하여 RoIAlign 과정을 통해 7x7 크기의 feature map을 출력합니다. 

 

  • Input : feature pyramid and RoIs
  • Process : RoIAlign
  • Output : 7x7 sized feature map

6) Classification and Bounding box regression by Fast R-CNN

Mask R-CNN architecture

RoIAlign 과정을 통해 얻은 7x7 크기의 feature map을 fc layer를 거쳐 classfication branch, bbox regression branch에 정달합니다. 이를 통해 최종적인 class score과 bbox regressor를 얻을 수 있습니다. 

 

  • Input : 7x7 sized feature map
  • Process : classification by classification branch, bbox regressor by bbox regression branch
  • Output : class scores and bbox regressors

7) Mask segment by Mask branch

Mask branch

RoIAlign 과정을 통해 얻은 7x7 크기의 feature map을 mask branch에 전달합니다. mask branch는 3x3 conv - ReLU - deconv(by 2) - 1x1(xK) conv layer로 구성되어 있습니다. 여기서 K는 class의 수를 의미합니다. 이를 통해 14x14(xK) 크기의 feature map을 얻을 수 있습니다. 해당 feature map은 class별로 생성된 binary mask입니다. 

 

14x14(xK) 크기의 feature map 중 앞서 classification branch에서 얻은 가장 높은 score의 class에 해당하는 feature map을 선정하여 최종 prediction에 사용합니다. 즉 단 하나의 14x14 크기의 feature map이 선정되는 셈입니다. 이후 feature map의 각 cell별로 sigmoid 함수를 적용하여 0~1 사이의 값을 가지도록 조정합니다. 

 

  • Input : 7x7 sized feature map
  • Process : mask segment by mask branch
  • Output : 14x14 sized feature map 

8) Post-processing of masks

최종적으로 선정된 14x14 크기의 featue map을 원본 이미지의 mask와 비교하기 위해 rescale해주는 과정을 수행해줍니다. 이후 mask threshold(=0.5)에 따라 mask segment의 각 픽셀값이 0.5 이상인 경우 class에 해당하는 객체가 있어 1을 할당하고, threshold 미만의 경우 0을 할당합니다. 이를 통해 실제 mask와 비교할 수 있는 mask segment가 생성되었습니다. 

 

  • Input : 14x14 sized feature map
  • Process : rescale and apply mask threshold
  • Output : mask segment

9) Train Mask R-CNN by multi-task loss

Mask R-CNN 네트워크를 위에서 언급한 multi-task loss function을 사용하여 학습시킵니다. 

Inference

Inference 시에 Proposal layer 구간에서 모든 feature pyramid level에 걸쳐 상위 1000개의 RoI만을 선정합니다. 이후 RoI를 classification branch와 bbox regression branch에 입력하여 나온 예측 결과에 Non maximum suppression을 적용하고, 상위 100개의 box만을 선정하여 mask branch에 입력합니다. 이러한 방식은 3개의 branch가 평행하게 위치했던 학습 과정과 다르지만, inference 시간을 줄여주고 정확도가 더 높게 나온다는 장점이 있습니다.


Mask R-CNN은 ResNeXt-101-FPN을 backbone network로 사용하여 COCO 데이터셋을 학습에 사용한 결과, AP값이 37.1%를 보였습니다. 이는 당시 instance segmentation task에서 가장 좋은 성능을 보인 FCIS+++와 OHEM을 결합한 모델보다 AP값이 2.5% 더 높게 나온 결과입니다. 참고로 detection task에서도 당시 가장 높은 성능을 보였다고 합니다. 

 

Instance segmentation 모델의 논문은 처음 읽어보는지라 생소하게 느껴진 부분들이 많았던 것 같습니다. 새삼스럽지만 논문을 읽으면 연구자가 문제 삼은 부분과 연구자만의 관점을 엿볼 수 있어 좋은 것 같습니다.이번 달까지 Mask R-CNN을 pytorch로 구현해야하기 때문에(이미 구현되어 있지만 수정을 할 것 같습니다) 조만간 Mask R-CNN 코드 리뷰 포스팅도 올라갈 것 같습니다. 다음 포스팅에서는 YOLO v3 논문을 읽고 리뷰해도록 하겠습니다. 

 

Reference

Mask R-CNN 논문(Mask R-CNN)

Fast R-CNN 논문 리뷰(RoI pooling 설명)

Faster R-CNN 논문 리뷰(RPN 설명)

FPN 논문 리뷰

Bilinear interpolation 설명

오리진님이 설명한 Bilinear interpolation 포스팅

Mask R-CNN 학습 과정 상세한 설명

Xiang Zhang님의 Mask R-CNN 설명 

CodeEmporium님의 Mask R-CNN 설명

RoI Align 설명   

Developer Paper 블로그의 Mask R-CNN 설명

Comments