본문 바로가기

갈아먹는 Face Detection [1] MTCNN

들어가며

이번에는 CNN을 활용하여 얼굴 검출 분야에서 정확도와 성능을 끌어올린 MTCNN[1] 논문을 리뷰해보도록 하겠습니다.

얼굴 검출 분야에서 높은 성능과 빠른 속도를 보여주어 아직도 많은 논문들과 프로젝트들에서 사용됩니다.

MTCNN 결과 예시

페이퍼 자체는 5쪽 밖에 되어 처음에는 좋아했으나 ㅎㅎ 생략되어 있는 부분이 많아서 오히려 더 고생한 기억이 납니다.

빠진 부분은 소스 코드 구현체[2]를 참고하거나 블로그 포스팅 등을 참고했으며, 약간의 상상력을 보탰습니다.

그럼 시작하겠습니다!

 

영향력: CNN을 이용해서 얼굴 검출 정확도를 95% 수준까지 끌어올렸으며 약 1300회 인용되었습니다.

주요 기여: face detection, bounding box regression, face alignment 세 가지 테스크를 동시에 학습시키는 joint learning 방식을 제안하였으며, 이를 통해서 떠 빠른 속도와 높은 정확도를 달성하였습니다. 

 

핵심 아이디어

본 논문은 얼굴을 검출해내는 Face Detection과 눈, 코, 입의 좌표를 알아내는 Face Alignment 두 가지 테스크가 서로 긴밀하여 연결되어 있을 것이라는 아이디어에서 출발합니다. 여기에 얼굴 위치를 나타내는 박스의 위치를 세밀하게 조절해주는 bounding box regression 테스크를 추가하여 세 가지 테스크를 동시에 학습시키면 시너지가 날 것이며 학습 자체도 단순해 질 것이라고 주장합니다. 저자들은 이러한 세 테스크를 학습한 P-net, R-net, O-net이라는 세 CNN을 차례로 통과하는 Cascade 모델을 제안합니다. 전반적은 구조는 아래 그림과 같으며, 이제 단계적으로 어떻게 이러한 네트워크가 구성되었는지 알아보겠습니다.

MTCNN structure

Stage 1. P-net

먼저 입력 이미지를 단계별로 Resize하여 이미지 피라미드를 만듭니다. 예를 들어 300x200 크기의 이미지가 입력되면 이를 200x166, 100 x 66, 30 x 20 크기로 리사이즈한 이미지의 list를 만들어 줍니다. 이렇게 해주는 이유는 작은 얼굴도 검출하기 위해서입니다. 우선 이렇게 만든 이미지 피라미드를 통과시킬 P-net의 구조를 살펴보겠습니다.

P-Net Structure

P-Net은 12x12x3 크기의 작은 이미지를 입력 받습니다. 그리고 컨볼루션만 거쳐서 (Fully Connected Layer 없음) 해당 영역이 얼굴인지 아닌지를 각각 나타내는 face classification, 얼굴 영역을 나타내는 좌측 상단 꼭지점의 x, y 좌표와 박스의 너비, 크기를 나타내는  4개의 bounding box regression 값, 그리고 양쪽 눈, 코, 양쪽 입고리의 x, y 좌표를 나타내는 10개의 landmark localization 값을 결과로 리턴합니다. 앞서서 만든 이미지 피라미드를 입력받아서 각각의 이미지에 12x12 크기의 윈도우로 스캔을 하며 얼굴에 해당하는 영역을 찾아내는 것입니다. 아래는 이해를 돕기 위한 영상을 첨부하였습니다.

https://www.youtube.com/watch?v=w4tigQn-7Jw

 

12x12의 아주 작은 크기로 윈도우를 설정하였기 때문에 작은 얼굴일지라도 잘 찾아낼 수 있는 것입니다. 이렇게 찾은 얼굴 영역들을 다시 원래의 이미지 크기로 되돌려줍니다. 앞선 예시를 들어보면 30x20 크기 이미지에서 찾은 얼굴 영역 좌표를 300x200 이미지에 해당하는 좌표로 변환해주는 것입니다. 그 다음 이렇게 찾은 박스들을 대상으로 Non-Maximum-Suppression과 bouding box regression을 적용해줍니다. NMS는 동일한 얼굴에 여러 번 박스가 쳐진 경우, 가장 얼굴일 확률이 높은 것만 남기고 제거하는 것을 말하며 자세한 내용은 제 이전 포스팅[4]을 참고해주시 바랍니다.

 

Stage 2. R-Net

이제 우리는 P-Net을 통해서 얼굴로 추정되는 박스들의 리스트를 얻었습니다. R-Net의 역할은 이 박스들 중에서도 진짜 얼굴에 해당하는 영역들을 추려내고, bounding box regression을 더 정교하게 수행하는 것입니다. 먼저 앞서 구한 박스들을 모두 24x24 크기로 resize 합니다. 그 다음 R-Net을 통과시킵니다. 그렇다면 R-Net의 구조를 한번 살펴 보겠습니다.

R-Net Structure

P-Net과 매우 유사하지만 Fully Connected Layer를 사용한 점이 눈에 띕니다. 앞선 P-Net의 경우 위치 정보를 잃어버리는 것을 방지하기 위해서 FC 레이어를 배제하고 Conv 레이어만으로 네트워크를 구성한 것과 대조됩니다. 논문에 드러나진 않았지만, 전체 이미지에서 얼굴에 해당하는 부분을 추측하는 역할은 P-Net이 수행하고, R-Net은 이를 더 정교하게 만드는 역할을 수행하기 때문에 이러한 차이가 나타나지 않았나 생각합니다. R-Net에서 찾아낸 박스는 마찾가지로 원래 입력 이미지 크기로 되돌린 다음, NMS와 BBR을 적용합니다. 여기서 살아남은 박스들만 O-Net에 전달합니다.

Stage 3. O-Net

O-Net Structure

대망의 마지막 O-Net입니다. O-Net은 R-Net을 통해 찾아낸 박스들을 모두 48x48 크기로 resize한 것을 입력으로 받습니다. 점점 필터의 크기를 키우면서 얼굴에 해당하는 더 추상적인 정보를 찾아내기 위한 의도로 보입니다. 아무튼, 여러 Conv 레이어와 FC 레이어를 거친 뒤 세 종류의 output을 내게 되며, 이것이 최종 Face Detection, Face Alignment 결과 값이 됩니다.

 

지금까지 MTCNN을 구성하는 P-Net, R-Net, O-Net의 구조와 역할에 대해서 알아보았습니다. 특이한 점은 세 네트워크 모두 구조가 비슷하고, output의 형태도 동일하게 내는 점입니다. 우리가 흔히 생각하는 end-to-end 모델과는 사뭇 다릅니다. 그렇다면 이러한 네트워크를 학습시키기 위해서 Loss Function을 어떻게 디자인 하였는지와 어떻게 학습시켰는 지를 알아보겠습니다.

 

Multi Task Loss

MTCNN은 classification, regression, localization 세 가지 테스크에 대하여 각각 loss를 구한 뒤, 이를 가중치를 두어 합치는 방식을 취합니다. 먼저 Classification으로는 log loss를 사용합니다. (Cross Entrophy로 봐도 무방합니다.)

Classification Loss

그 다음으로 Bounding Box Regression Loss입니다. 흔히 bounding box regression의 결과 값으로 좌측 상단 점의 x, y 좌표의 위치 조절 값과 너비와 높이의 조절 비율을 얻어내며 이는 4차원 벡터에 해당합니다. 이를 ground truth box와 유클리드 거리를 측정하여 로스로 사용합니다. (Bounding Box Regression과 관련된 내용은 이전 포스팅[4]에서 좀 더 자세히 다룬 것이 있습니다.)

|| || 기호는 선형 대수에서의 norm을 나타내며 우측 하단의 2는 각 차원별 차이의 제곱의 합을 구하란 의미이며, 우측 상단의 2는 전체 결과값을 제곱하라는 의미입니다. 이를 수식으로 풀어내면 아래와 같습니다.

마지막으로 localization loss를 살펴보겠습니다. 얼굴의 각 주요 지점을 나타내는 좌표는 x,y로 이루어져 있으며 총 다섯개의 지점을 예측합니다. 그 결과는 10차원 벡터라고 볼 수 있으며, 앞선 regression loss와 비슷하게 아래와 같이 loss를 계산합니다.

이제 세 가지 Loss를 엮은 최종 로스를 구해보겠습니다. 최종 로스는 각각의 로스에 가중치를 반영하여 모두 합쳐준 것이며 수식과 P, R, O net별 가중치는 아래와 같습니다. 아래에 N은 전체 데이터의 수이며 베타는 특정 샘플이 선택되었는지 안되었는 지를 (0, 1)로 표현합니다. 즉, Stochastic Gradient Descent를 적용하여 전체 데이터 셋에서 일부분만 뽑아내어 로스를 계산한다는 의미입니다.

모델 학습 및 성능

논문에서는 전체 로스와 모델 구조만 제시해주고 구체적으로 어떻게 학습을 시켰는 지를 언급하지 않습니다. R-Net을 학습시키기 위해선 P-Net이 필요하고 P-Net이 단순히 얼굴 영역만 제시하지 않고 localization도 학습하는 측면을 고려했을 때, P-Net을 먼저 학습시키지 않을까 추측합니다. 그 다음 학습된 P-Net을 이용해서 R-Net을 학습시키고, 이 둘을 이용해서 O-Net을 학습시킬 것으로 생각합니다. 직관적으로 보면 R-Net과 O-Net은 P-Net의 결과를 더 정교하게 만들어주는 역할을 하므로 정확도가 점점 더 향상될 것으로 짐작할 수 있습니다. 아래는 논문에 제시된 실험 결과입니다.

한계점 및 개선 방향

지금까지 MTCNN을 살펴보았습니다. 뛰어난 모델이지만 분명히 개선할 점이 있다고 생각합니다. 먼저 입력 이미지에서 피라미드를 만들고, 이를 12x12 크기의 윈도우로 CNN inference를 하는 부분이 가장 큰 bottle neck으로 작용할 수 있습니다. 이미지의 크기가 커질 수록 CNN inference의 수가 급격히 늘어나게 되고 이는 곧 성능 저하로 이어집니다. 실제로 이용해본 결과 1080x720의 고해상도 이미지를 입력하면 GPU를 사용함에도 10초가 넘게 걸리는 현상을 경험했었습니다.

 

아마도 후속 논문들에서는 이러한 이미지 피라미드 방식을 개선하여 한번의 CNN inference 만으로 얼굴 영역을 찾아내는 방식들이 제안되었을 것으로 예상합니다. 후속으로 이어지는 Face Detection 논문을 읽게 되면 리뷰하도록 하겠습니다.

 

마치며

얼굴 검출은 굉장히 수요가 많은 테스크이고 MTCNN은 이 분야에서 가장 널리 사용되는 모델입니다.

그러나 한국어로 된 리뷰가 없었고, 논문 자체만으로는 이해할 수 있는데 한계가 있어서 직접 살을 붙여서 리뷰를 작성해보았습니다.

리뷰 포스팅을 작성하면서 이렇게 제 생각을 많이 개입시킨 적이 있나 싶네요 ㅎㅎ

 

잘못된 내용이 있더라도 너그러이 봐주시고 수정해야할 내용이 있다면 댓글로 남겨주세요.

감사합니다.

Reference

[1] Zhang et al, Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks, 2016

[2] github, https://github.com/ipazc/mtcnn

[3] Chi-Feng Wang, blog, https://towardsdatascience.com/how-do-you-train-a-face-detection-model-a60330f15fd5  

[4] 갈아먹는 R-CNN, https://yeomko.tistory.com/13?category=851298