0. Before Reading
Image Segmentation은 영상 혹은 이미지에서 의미있는 부분들을 구별해내는 기술이다.
이미지를 영역별로 나눠준 후, 각 개체에 맞게 합쳐주는 task 이다.
Object Detection 혹은 Classification과 비교해봤을 때, 정확하게 개체들의 경계선까지 추출하여 의미있는 영역들로 분할해줘야 하므로 더 어려운 작업이라 볼 수 있다.
Image Segmentation은 아래의 2가지로 분류된다.
1) Semantic Segmentation
2) Instance Segmentation
(1) Semantic Segmentation
Semantic Segementation은 동일한 객체들끼리는 한 번에 Masking을 수행하는 방법이다.
위의 사진과 같이 segmentation을 진행할 때, class가 같다면 구분하지 않고 같은 영역 혹은 색으로 분할한다.
같은 클래스의 다른 개체들이어도 구분을 하지 않는다.
FCN에서는 각 픽셀 별로 해당 클래스를 계산하고 픽셀 별로 색을 칠해 Semantic segmentation을 진행한다.
Sementic Segmentation은 Pixel Wise Classification 이라고도 불린다.
왜냐하면 개별 픽셀 단위로 어떤 클래스에 속하는지 Masking을 하기 때문이다.
아래 그림을 보자.
개별 픽셀들이 위와 같은 그림처럼 몇번 클래스인지 표시가 된다.
위의 그림처럼 5개의 채널에 따라서 이미지의 개별 픽셀 별로 Classification 할 수 있다.
Sementic Segmentation은 AutoEncoder의 형태를 띤다.
AutoEncoder는 원본 이미지를 Convolution으로 차원을 축소해 원본 이미지의 응집되고 추상화된 특징을 추출한다.
그리고 이를 Up-Sampling을 사용해서 다시 복원하며 필요한 정보를 학습한다.
이렇게 학습된 정보를 기반으로 Segmentation Prediction을 수행하고 위 그림의 Output과 같은 결과를 출력한다.
AutoEncoder에서 주의할 점은 원본 이미지를 똑같이 복사하는 것이 아니라
원본 이미지에서 찾을 수 없었던 Feature들을 찾아내는 것이다.
(2) Instance Segmentation
Instance Segmentation은 동일한 객체들이어도 개별 Object 별로 Masking을 수행하는 방법이다.
class가 같더라도 다른 개체라면 이를 구분해 인식한다.
위 사진처럼 "Person"은 같은 class 이지만, instance로 인식해 각자 다르게 영역 혹은 색으로 분할해준다.
1. Faster R-CNN
Mask RCNN 이해를 위해 Faster R-CNN에 관해 복기하고 가자.
Faster RCNN = RPN(Region Proposal Network) + Fast RCNN
1) CNN을 통과하여 원본 이미지의 Feature Map을 추출하여 RPN의 input으로 넣어준다.
2) RPN에서 Anchor Box를 통해 Region Proposal 영역을 추출한다.
3) ROI pooling을 통해 Feature Map에 맵핑 시킨다.
4) Classification과 Bounding Box Regression 2가지 task를 동시에 진행하며 학습한다.
2. FCN(Fully Convolutional Network)
FCN은 Semantic Segmentation Encoder-Decoder Model의 종류 중 하나이다.
FCN의 기법을 약간 변형해 활용한 것이 Mask RCNN 모델이다.
FCN은 Convolution Layer를 거치면서 차원 축소된 Feature Map을 뽑아낸다.
원본 이미지에 대한 위치 정보는 소실되지만 원본이 가지고 있는 응축된 정보들을 가지고 있게 된다.
이를 마지막에 Flatten 하지 않고 다시 Up-sampling 하며 복원하면서 필요한 정보를 학습하는 형태의 네트워크를 형성한다.
여기서 FCN은 Skip Connection을 이용한다.
Skip Connection : 하나의 layer의 output을 몇 개의 layer를 건너뛰고 다음 layer의 input에 추가하는 것
일반적인 신경망 모델 학습 시 모델의 layer가 깊어질수록 학습 결과가 좋을 수 있다고 알려져 있다.
하지만 layer을 너무 깊이 쌓거나 노드 수를 너무 크게 증가시키면 입력 정보가 여러 layer를 거치면서 이전 layer에 대한 정보 손실이 발생할 수 있고 weight가 잘못된 방향으로 갱신되는 문제가 발생할 수 있다.
그래서 이전 layer의 정보를 이용하기 위해 이전 layer의 정보를 연결하는 잔차 연결(skip connection)을 적용 한다.
FCN의 Skip Connection 동작 과정은 아래와 같다.
1) 각 Convolutional Layer에서 나오는 Feature Map을 Skip Connection 할 대상으로 사용한다.
2) 그리고 뒤에서 원본 이미지 사이즈 크기로 Up-Sampling을 진행할 때 Skip Connection 한다.
3) 최종 Segmentation은 보통 마지막 Up-Sampling을 진행해 나오게 되는 FCN-8s(초록색 박스)를 사용한다고 한다.
아래 그림처럼 FCN-8s를 활용했을 때가 Ground Truth와 가장 가까운 결과를 낸다.
FCN Process는 다음과 같다.
- 1) $224 \times 224$ size 원본 이미지가 사이즈가 줄어들면서
- 2) $7 \times 7$ size (depth$= 4096$) : 개별 피쳐맵들의 픽셀 단위로 클래스에 속할 확률 정보를 가진다.
- 7x7 size (depth=21) : cat에 대한 Heatmap = 21 (PASCAL VOC = 20 class + 1 background)
- 3) Pixelwise Prediction을 하기 위해서 32배 Up-sampling ($224 \times 224 \times 21$)한다.
- 4) 그러면서 Ground Truth에 있는 Masking 정보에 대한 학습을 한다.
2.1) FCN vs FCL
FCL이 당시 처음 나왔을 때, Classification에서 Fully Connected Layer를 통해 1차원으로 flat하게 만들어버리는 것이 필요했다.
반면 FCN은 Fully Connected Layer 없이 Convoluitonal Layer만으로 구성된 모델이다.
FCN은 FCL과 다르게 Flatten 하게 만들지 않고 여전히 $1 \times 1$ Convolution을 사용한다.
FCL에서 Flatten 하는 단계에서 FCN에서의 Depth는 4096만큼 있다.
그리고 마지막의 Ouput Feature map의 Depth는 1000개로 만든다.
Heatmap을 살펴보면 Cat일 확률에 대한 정보를 Pixel by Pixel로 가지고 있다.
그리고 이것을 다시 Up-sampling 한다.
3. Mask RCNN
Mask RCNN은 기존 Object Detection에서 사용되던 Faster RCNN(RPN + Fast RCNN)에 Mask branch를 추가해
classification, bbox regression, predicting object mask를 동시에 처리하는 모델이다.
Mask RCNN에서는 ROI 내에서 각 클래스별로 Instance인지를 구분하는 Mask를 씌워준다.
그 후 Classification layer를 통해 계산된 Classfication에 대해 Instance가 있다고 판단된 픽셀들에 색을 칠해 Instance Segmentation을 진행 해준다.
4. Mask RCNN Feature Extractor
Mask RCNN은 ResNet + FPN(Feature Pyramid Network)를 이용한다.
Mask RCNN의 특이한 점은 2가지이다.
우선 Faster RCNN의 ROI Pooling이 아닌 ROI Align 기법을 사용했다는 것과,
FCN을 통해 분류를 수행할 때 Multi-Class Classification이 아닌 Binary Classification을 했다는 것이다.
4.1) ROI Pooling의 문제점
ROI Align이라는 기술이 등장한 이유는 분명히 ROI Pooling 이라는 기술이 한계가 있을 것이기 때문이다.
따라서 ROI Align을 이해하기 전에 ROI Pooling이 무슨 문제점을 가지는지 알아보자.
ROI Pooling은 기본적으로 7x7 그리드만으로 분면을 나누어 Bag Of Visual Words 기법을 수행하는 것이다.
따라서 '그리드 분할' 이라는 특성을 감안해야 하기 때문에 Feature Map에서 ROI Feature Map으로 변환할 때 무조건 높이, 너비 사이즈가 정수값이어야 한다.
그렇기 때문에 만약 소수점으로 계산되더라도 소수점은 다 버리고 정수값만을 남겨 사이즈를 설정해야 한다.
이를 Quantization 문제라고 부른다.
Quantization문제가 뭘까? 간단하게 얘기하면 "반올림"해버린다는 것이다.
이런 5x5 Feature map이 있다고 가정했을 때, 현재 ROI가 점선 상자와 같이 존재한다고 가정하자.
현재 ROI의 경계는 Feature map과 딱 떨어지지가 않는다.
이때 ROI Pooling은 이 문제를 해결하기 위해서 그냥 아래와 같이 "반올림"해버린다.
이렇게 되면 위치정보에 혼란이 온다. 들어와야할 정보는 들어오지 않고, 이상한 정보가 들어오기 떄문이다.
pixel 단위로 Segmentation을 진행해야되는 mask를 예측하는 task에 대해서 아주 큰 부정적인 효과를 가져온다.
이를 해결하기 위해서 논문에서는 ROI와 Feature map이 딱! 맞도록 하는 ROI Align이라는 것을 적용한다.
위 그림을 보면 결국 ROI Pooling 과정은 이미지의 중요한 부분인 ROI Feature를 일부 손실하게 된다는 것을 알 수 있다.
4.2) ROI Align
ROI Align은 Bilinear Interpolation인 이중선형 보간법을 사용한다.
ROI Align 과정을 3단계로 구분하면 다음과 같다.
1) ROI의 사이즈 소수점을 그대로 유지하고 ROI 개별 그리드에 Point를 균등하게 배열한다.
2) 개별 Point에서 가장 가까운 Feature Map 그리드를 고려하며 Point에 들어갈 값을 Weighted Sum 해준다.
3) 계산된 모든 Point들에 대해서 지정돤 사이즈의 Max Pooling을 수행해준다.
피쳐맵이 들어오면 Masking 정보들을 학습하면서 Masking 기반의 Prediction 할 수 있는 모델에 대한 Weight들을 채우게 된다.
5. Mask Prediction
5.1) Binary Masking Classification
Mask RCNN의 FCN에서는 특정 픽셀값이 어떤 Object 클래스로 분류되는지 결정되는 Multi-Class Classification을 사용하지 않고
특정 픽셀값이 어떤 클래스인지(ex.강아지인지 고양이인지, 사람인지) 상관없이 단순히 Object를 나타내는 Masking 인지 아닌지만 분류하는 Binary Masking Classification을 수행한다.
ROI Align 후, FCN 레벨에서 $7 \times 7$ 에서 $14 \times 14$로 Up-sampling 거친 후
이 부분에 대해서 Mask Prediction을 하게 된다.
위 그림은 80은 coco dataset에 대한 Binary Masking Classification 하는 것이다.
여기서 어떤 클래스인지 찾지는 않고 그 클래스 인가 아닌가만 판단한다.
5.2) Resize 후 원본 이미지에 적용
그리고 Binary Masking Prediction을 거친 후
Predicted Mask($14 \times 14$)를 원본 이미지의 Object 사이즈 만큼 복원하고 이를 원본 이미지 위에 덮어씌우게(Overlap) 된다.
Mask Prediction 후 Resize하여 원본 이미지에 적용한다.
5.2) Loss Function
Mask RCNN의 Loss Function은 그동안 배워왔던 Object Detection 모델들의 Loss Function에 Masking에 대한 Loss Function을 추가한 것과 다름없다.
단, Mask RCNN을 구성하는 2가지 요소
즉, Faster RCNN에서는 Object의 클래스를 분류하는 Multi-Class Cross-entropy Loss와
Bounding Box를 찾는 L1 Smooth Loss 함수를 사용하는 반면,
Masking 여부를 예측하는 FCN에서는 Binary Cross-entropy Loss를 사용하게 된다.