본문 바로가기
딥러닝/CV 논문

[Instance Segmentation] SOLO

by 혜 림 2021. 8. 12.

[들어가는 사족]

 문득 예전에 썼던 글을 읽다가.. 음 뭔가 읽는데 급급해 보인다는 느낌이 들었다. 두루뭉술하게 이해하고 후루룩 후루룩 쩝쩝 하는 그런 느낌.. 그리고 한글인데 한글같지 않은 느낌 그래서 앞으로는 논문의 순서대로 리뷰하지 않고 그냥 내가 이해하기에 중요한 부분만 뽑아서, 배가 부르다 라고 할 수 있을만큼 읽기로 했다. 그리고 글을 쓰는 것도 그냥 내 맘대로 내 의식의 흐름대로. 배가 터지도록 먹겠다는 생각은 나에게는 너무 버겁다. 

 

그나저나 2020년 논문이다 나 이제 너무나 현대인!ㅎㅎ 저번에 포스팅한 yolo랑 이름이 비슷하다 웃기다

 

 

SOLO: Segmenting Objects by Locations

 

 

 

[Instance Segmentation 이란?]

 

 SOLO는 instance segmentation을 위해 만들어진 모델이다. semantic segmentation은 보지도 않고 바로 instance segmentation으로 넘어오는 게 조금 걸리기는 하지만.. 그래도 설명을 해보자! 

 segmentation은 무엇인가? 픽셀 별로 predict 하는 걸 의미한다. 

 그 중에서도 semantic segmentation은 같은 class 끼리는 구분을 안 한다. 픽셀별로 그냥 class만 구분하면 된다.

 반면 instance segmentation은 같은 class여도 구분을 한다. 픽셀별로 그냥 class 를 구분할 뿐 아니라, 동일한 클래스 내에서도 서로 다른 개체들을 구분한다. 그림으로 보면 이해가 쉽다. 

 

https://ai-pool.com/d/could-you-explain-me-how-instance-segmentation-works 여기서 누군가 instance segmentation이 뭔지 묻고 있다

 

[ 기존의 instance segmentation 연구]

 

 그렇다면, instance segmentation은 어떻게 발전해 오고 있었는가?? 

 크게 두 가지 흐름으로 나눌 수 있다. 

 

#1. top - bottom 

 

 이 방법은 "detect - then - segment" 라고도 한다. detect then segment의 이름이 더 직관적이다! 

 먼저 bbox를 통해서 개체를 찾은 다음에 pixel 별로 predict를 하는 방법이다. 

 익숙한 Mask R-CNN 이 여기에 해당한다! 이것도 리뷰 글 올려야 하는데 바쁘다 바빠 현대사회다. 

 

Mask R-CNN 논문의 figure 1 

 

#2. bottom - up 

 

 이 방법은 픽셀들 간의 affinity relation을 학습한 후에 동일한 instance의 픽셀인 경우 grouping, 다른 instance의 픽셀인 경우 pulling 함으로써 이제 각 픽셀에 임베딩 벡터 값을 assign 한다. 

 쉽게 생각해서, 1번 픽셀과 2번 픽셀의 값 사이에 차이가 얼마나 나는지를 통해서 segment를 하는 것 같다.

 

두 방법의 문제는? 바로 step-wise 하고 indirect 하다는 거다. 

1번을 예로 들자면, bbox가 얼마나 정확한지에 따라서 segment 정확도도 달라지니, 정확성이 bbox에 의존하고 있다는 거다. 

 

따라서 본 논문을 작성하신 분들은 direct 하게 instance segment를 하고 싶었다!

그래서 아래와 같은 고민에 빠졌다. 

 

[어떻게 direct 한 instance segmentation을 할 것인가?]

 

 이에 대한 답을 얻기 위해서 근본적으로 이미지 내에 동일한 class의 개체가 두 개가 있을 때 어떻게 구분할 수 있을까? 를 먼저 생각해보자. 

 

 본 논문에서 집중하고 있는 다른 점은 

 

 # 1. 중심점의 위치 (Location)

 # 2. 개체의 사이즈 (Size) 

 

 이다.

더보기

 하지만 현실적으로도 이런 것일까? 에 나는 글쎄.. 논문에서는 COCO 데이터 셋을 보고 이걸 떠올렸다고 해서 그런 한계가 있는 것 같다. 아니면 내가 논문에서 못 찾는 것일까...

 여기서 논문의 이름의 기원이 나온다! Segment Object by LOcations 

 그럼 이걸 이용해서 어떻게 instance segmentation을 더 효율적으로 할 수 없을까? 해서 고안된 것이 "instance categories"이다.

 

[instance categories의 배경]

 

 이게 어디서 나왔는가? segmantic segmentation에서 dominant했던 방법인 FCN!

 

 이 FCN의 결과는 N개의 채널이 있다. 각 채널별로 한 클래스에 대해서 T/F 예측을 한 것이다. 

 그림으로 그리면? 

 

재밌는 색칠놀이...ㅎㅎ

 

 이런식으로.. 

 

 하지만 이걸 instance segmentation에 적용시키려면 뭐가 문제인가? 

 우리는 이미지 속에 instance가 몇 개인지 모르기 때문에 채널을 몇 개로 설정해야 할지가 애매해진다. 

 

 그래서 비슷하지만 다르게, 이미지의 instance 들을 구분하기 위해서 'instance categories'를 도입한다. 

 즉 위에서는 각 채널별로 클래스를 predict 했다면, 이제는 각 채널별로 instance category를 predict 한다는 것이다! 

 

그림으로 보면 요렇게

SOLO논문의 figure 1 - (b) 

 

 각 채널에 한 클래스가 모두 담긴게 아니고 채널마다 instance 하나 이렇게 담겨있다.

 어 그런데 위에서 annotation은 N인데요? 클래스 개수 아닌가요? 이건 나중에 다루자

[SOLO의 architecture]

 

 그래서 위에서 언급한 instance category를 모델에 적용시키면 아래와 같은 구조다. 

 

Figure 2

 

instance segmentation은 크게 2가지의 sub-task(semantic category와 instance mas)로 나눌 수 있다. 

 

#0. grid

 

먼저 위에서 언급한 sub-task를 하기 전에 이미지를 SxS 그리드 셀로 나눈다. Yolo가 생각난다.

 

#1. Semantic category

 

Fig2. 에서 위의 그림인 category branch에 해당한다. 보면 알 수 있듯이 output은 SxSxC 이다. C는 클래스의 갯수다. 

 

그러면 이렇게 한 그리드마다 각각의 클래스에 대한 확률을 예측하게 될 것이다. 

 

#2. Instance Mask

 

 이때의 output tensor의 크기를 보면 HxWx$S^{s}$ 이다. 그러니까 원본 이미지의 해상도에 그리드 갯수만큼 채널이 붙은 셈이다. 따라서 각 그리드 셀 마다 instance mask를 만들게 된다. 

 이때 k번째 채널은 원래 이미지에서 몇 번째 그리드 셀인가? 는 아래와 같은 식으로 계산한다. 

 

 $k = i \time S + j$

 

 (i,j)는 그리드 셀의 위치, 그리고 S는 그리드 셀을 나눈 간격을 뜻한다. 

 

 instance mask를 predict 하기 위해서는 FCN 같은 fully convolutional network를 이용한다. 

 다만 convolution network는 spatially invariant한데, 이는 classification에는 오히려 좋은 점이지만 segmentation에서는 그렇지 않다. segmentation에서는 공간 정보가 변하면 masking된 좌표값도 변해야 하기 때문이다. 따라서 spatially variant가 바람직한 속성이고, 이를 이해서 참고한 것이 'CoordConv'라고 하는 선행 연구이다. 

 

An intriguing failing of convolutional neural networks and the CoordConv solution 논문의 Fig 3

 

오른쪽에 보이는 그림 중 i coordinate와 j coordinate 와 같은 채널을 network 시작할 때 붙여주었다는 뜻이다. 

 

 i coordinate같은 경우 아래로 가면 색깔이 진해지고, j coordinate 같은 경우는 오른쪽으로 갈수록 색깔이 연해진다. 

 이런 텐서는 어떻게 나오냐면 (1) 동일한 크기를 가진 텐서에다가 (2) 픽셀 좌표 값을 넣어주고 (3) [-1,1] 사이의 값으로 정규화를 해준다. 

 

 그리고 이거를 인풋에다가 붙여준concatenated 후에 다음 레이어를 거치고 이런 식이다. 

Fig 3

 

 그래서 아래 mask branch를 보면 256+2 인 것을 확인할 수 있다. 2가 i coordinate와 j coordinate로 구성된 셈이다. 

 

[Network Architecture]

Feature Pyramid Networks for Object Detection 논문의 Fig1

 

 SOLO의 백본으로 FPN을 이용했다. 

 위 그림을 보면 이해가 쉽다. 여러 개의 사이즈로 feature map의 피라미드를 만들어내는 구조다. 

 

 이렇게 만들어진 맵들을 이제 semantic category와 instance mask의 인력값으로 사용한다. 

 

 서로 다른 스케일의 피쳐 맵이지만 마지막 conv layer 빼고는  가중치를 고유한다. 

 

 

 

 그러니까 지금까지 돌아보면 
이 SOLO라는 거는 instance를 구분하는 핵심이 중심점의 좌표와 이미지의 사이즈라고 생각했다. 
 따라서 중심점의 좌표가 다른 점을 반영하기 위해서 instance category를 도입하고, 사이즈가 다른 점을 반영하기 위해서 FPN을 백본으로 이용했다고 할 수 있다. 

 

 

[그렇다면 학습은 어떻게?]

 

 $ L = L_{cate} + \lambda L_{mask}$

 

이때 $L_{cate}$는 클래스 분류에 대한 Focal Loss, $L_{mask}$는

 

Eq (2)

아래와 같이 계산된다. 

 

 이때 $d_{mask}$는 dice loss 라고 한다. 처음 들어봤다. 다른 Binay Cross Entropy나 Focal Loss 도 같이 사용해봤는데, 지금 사용한 Dice Loss가 많은 하이퍼 파리미터 튜닝 없이 좋은 성능을 낼 수 있어써 채택했다고 한다. 

 

이때 D는 다이스 상관계수로, 아래의 수식을 통해 계산된다. 

p가 prediction, q가 ground truth 

 

[그렇다면 예측은 어떻게?]

 

(1) 백본 네트워크와 FP을 input image가 거처가면 

(2) 각 그리드 셀마다의 클래스 점수인 $p_{i,j}$와 마스크 값인 $m_{k}$값을 계산한다. 

(3) 0.1을 임계값으로 두고 예측된 것들을 거른다. 

(4) 걸러진 것 중 점수를 기준으로 상위 500개의 mask 에만 NMS 를 거친다. 

(5) 그리고 마지막으로 0.5의 임계값으로 거른 후 최종적인 예측만 남긴다. 

 

Fig 4

 

그래서 나눠진 그리드 셀마다 Fig 4의 아래 그림들처럼 mask 이미지를 예측한다. 신기하다!

[성과]

 

Table 1 

[추가 연구]

 

1. 그리드의 수과 FPN 

 그리드 수를 늘리는 것도 좋지만, FPN 이 특히 mAP를 더 높여준다. 하지만 만약 이미지의 스케일이 비슷하다면 SOLO의 성능은 꽤 괜찮을 것으로 예상된다. 

Table 2

2. Decoupled SOLO

 SOLO의 advance된 버전 포스팅에선 과감하게 패쓰 관심있으면 읽어보시길

그나저나 난 바닐라 좋아하는데 여기서 바닐라 보면 싱숭생숭하다. 그냥 기본적인 애라고 취급받는 것 가탕...

 

 

[reference] 

reference로 논문을 보는 아이러니함...ㅜㅜ

https://arxiv.org/pdf/1912.04488.pdf

https://openaccess.thecvf.com/content_cvpr_2017/papers/Lin_Feature_Pyramid_Networks_CVPR_2017_paper.pdf

https://arxiv.org/pdf/1506.01497.pdf

https://arxiv.org/pdf/1807.03247.pdf

https://arxiv.org/pdf/1703.06870.pdf

 

 

[나가시는 말ㅎㅎ] 

 안뇽~

 

그리고 내게 남은 임시저장 글 2편...

댓글