이전 글에서 설명한 API와 logistic regression을 이용하여 얼굴 비대칭성을 계산하고 정상인과 환자 사진을 학습시켜 결과를 예측하도록 하였다. 뇌졸중 자가진단에 머신러닝을 사용하기 위해선 3단계의 과정이 필요하다. 첫 번째는 비대칭성 계산, 두 번째는 학습, 세 번째는 예측이다. 이 세 가지 단계는 다음과 같이 이루어져있다.

 

비대칭성 계산

    우리가 구현하고자 하는 기능을 위해선 얼굴의 눈, , 입을 인식하고 위치를 알 수 있는 API가 필요했다. APIgithub에 있는 cv2, dlib를 사용한 코드를 얻어올 수 있었다. API를 이용하여 아래 그림처럼 얼굴의 좌표를 얻을 수 있다.

뇌졸중의 초기 증상중 하나인 안면마비를 검증하기 위해 안면마비 환자들의 특징을 알아보았고 환자가 웃었을 때 왼쪽과 오른쪽의 비대칭성을 통해 의사가 판단한다는 것을 알 수 있었다. 따라서 얼굴의 좌표를 이용해 얼굴 중앙을 중심으로 3가지를 특징을 종합하여 왼쪽과 오른쪽의 비대칭성을 계산해보았다. 특징은 다음 3가지이다. 괄호 안에 있는 숫자는 아래 사진에서의 좌표 번호이다.

안면 비대칭을 확인하기 위한 거리 계산

1. 중심(34)에서 왼쪽 눈 끝(37)까지의 거리 : 중심(34)에서 오른쪽 눈 끝(46)까지의 거리

2. 중심(34)에서 왼쪽 코 끝(32)까지의 거리 : 중심(34)에서 오른쪽 코 끝(36)까지의 거리

3. 중심(34)에서 왼쪽 입술 끝(49)까지의 거리 : 중심(34)에서 오른쪽 입술 끝(55)까지의 거리

 

    얼굴의 비대칭성이 심할수록 왼쪽과 오른쪽 거리의 차이가 더 커질 것이다. 따라서 비대칭성을 표현하는 수는 (작은 거리)/(큰 거리)를 이용하여 비율로 나타내었다. 즉 이 값이 1에 가까울수록 얼굴이 대칭적이고 1에서 멀어질수록 얼굴이 비대칭적이라는 말이다. , , 입에 (작은 거리)/(큰 거리) 식을 이용하여 각각 계산하고 그 합을 더하였다. 따라서 3가지를 합하므로 3에 가까울수록 얼굴이 대칭적이라는 것이다.

 

학습

    실제 환자 사진과 정상인 사진으로부터 계산한 비대칭성을 나타낸 수를 이용하여 학습을 시켜야한다. 실제 환자 얼굴은 개인정보이기 때문에 많은 사진을 구할 수 없었다. 따라서 크롤링을 이용해 구글에서 찾을 수 있는 환자의 사진을 최대한 많이 모아보았다. 그 결과 160장의 사진을 구할 수 있었다. 정상인의 사진도 비슷한 개수로 구글링을 통해 154장을 구하여 총 314장의 사진으로 학습을 진행하였다. 1번 과정을 통해 얼굴의 비대칭성을 수로 표현할 수 있었다. 그 다음엔 각 사진이 하나의 숫자로 표현되기 때문에 logistic regressionClassification을 이용하여 뇌졸중이 의심된다(1) 아니다(0)로 판단할 수 있다. 학습 과정은 다음과 같다.

 

- linear regression(선형 회귀)

    선형 회귀로 환자와 정상인으로부터 계산한 비대칭성을 나타내는 수들의 분포로부터 최적의 직선을 하나 만든다. 수치미분을 하며 학습시킬 비대칭성 수들로부터 최적의 직선을 만든다. 이 직선의 기울기가 W, y절편이 b이다. x가 뇌졸중이 의심되는지 판단하고자 하는 사람의 비대칭성을 계산한 수라고하면 (W*x + b) 값은 학습한 점들로부터 유추되는 예측 값이다. 매번 학습시킬 수 없기 때문에 학습한 결과인 W값과 b값은 파일에 저장하여 예측을 할 때 사용된다.

 

- Classification(분류)

    과정 1에서 한 선형 회귀의 결과 값은 뇌졸중이 의심되는지 판단하기 위해 1 또는 0의 값만을 가져야한다. 따라서 분류에 자주 사용되는 함수인 sigmoid 함수를 이용하여 10 사이의 값으로 나타낸다. sigmoid함수는 오른쪽과 같은 수식과 함수 그래프로 나타난다. 따라서 sigmoid함수의 결과 값이 0.5보다 크면 안면마비일 확률이 높다는 뜻이므로 1을 리턴하고 0.5보다 작으면 안면마비일 확률이 낮으므로 0을 리턴한다.

sigmoid 함수 수식과 그래프

- 학습 과정 구성도

train.py 구성도

 

예측

     이제 학습된 결과를 이용해 사용자로부터 사진을 받으면 안면마비인지 예측할 수 있다. 우선 사진의 비대칭성을 나타내는 수를 구하여 Wx + b값을 얻는다. 그 다음 결과 값을 sigmoid함수에 넣어 0.5보다 클 경우 안면마비로 판단, 0.5보다 작을 경우 안면마비가 아닌 것으로 판단할 수 있다. 결과를 예측하는 과정은 아래와 같은 구성도와 같이 동작한다.

result.py 구성도

 

예시

환자 사진 예시

환자 사진을 예측한 결과이다. 아래서 세 번째 줄에 있는 0.2604..라는 값은 0이 완전 대칭이라고 할 때 얼마나 비대칭적인지를 나타낸 값이다. numpy배열로 나타난 아래서 두 번째 줄의 첫 번째 원소인 0.67138494는 sigmoid함수 결과 값으로 0.5보다 클 경우 뇌졸중으로, 0.5보다 작을 경우 정상으로 나온다. 0.67138494은 0.5보다 크므로 뒤에 1이라는 결과가 나와 뇌졸중 의심으로 판단한 것을 알 수 있다.

정상인 사진 예시

정산인 사진을 예측한 결과이다. 환자 사진과 비교해보면 0.0469..라는 값으로 0에서 크게 벗어나지 않은 것을 볼 수 있다. 또 0.28130981의 sigmoid 결과값은 0.5보다 훨씬 작은 수치로 뇌졸중 의심이 되지 않는다고 예측한 것을 알 수 있다.

 

머신러닝과 딥러닝API를 이용하여 안면비대칭을 진단하는 과정은 이렇게 이루어진다. 이제 사용자가 이용할 수 있게 웹사이트에 올려 사진을 받고 결과를 보여주는 작업이 남았다.

이전 글에서 다룬 기획 의도로 구현한 작품에 대한 설명을 해보겠다.

작품 개요

    사용자가 언제 어디서든 쉽게 사용할 수 있도록 하는 것이 중요한 사안이었기 때문에 웹페이지에 접속해 검사를 진행할 수 있도록 프로그램을 구현하였다. 웹페이지에 접속을 하게 되면 사용자는 사용하고 있는 전자기기에 따라 PC의 웹 카메라 또는 스마트폰의 전면 카메라를 통해 자신의 얼굴 사진을 캡처 하고 이 사진은 서버에 전송된다. 장고 웹 프레임워크를 사용하는 서버에 전달된 사진은 머신 러닝으로 학습된 함수 값에 따라 안면 비대칭에 근거한 뇌졸중 의심 여부를 판단하여 사용자가 분석 결과를 볼 수 있도록 웹페이지에 출력된다.

    웹페이지와 UIReact라는 JS 라이브러리를 사용하여 구현하였으며 검사를 위한 사진 캡처, 프로그램에 대한 설명과 같은 기능을 제공한다. 사용자는 웹페이지에 접속하자마자 별 다른 과정 없이 간편하게 사진 캡처를 하고 결과 분석을 열람할 수 있다.

    사용자가 자신의 얼굴을 캡처한 사진을 제출하게 되면 이는 장고 웹 프레임워크로 구현한 서버로 전송된다. 해당 사진은 서버의 DB에 저장되며 python으로 구현한 분석 함수의 입력 값으로 주어지게 된다. 분석 결과가 함수로부터 반환되면 이는 서버로부터 다시 웹페이지로 전송되어 사용자가 볼 수 있도록 결과와 함께 설명이 출력된다.

캡처한 사진이 담고 있는 얼굴을 분석하기 위해 이미지를 처리하는 라이브러리인 OpenCVdlib를 사용하였다. 이 중 사진에서 얼굴을 인식하는 face detector와 눈, , 입 등 얼굴의 주요 부위를 인식하는 landmark predictor라는 기능을 사용하였다. Landmark predictor는 사진에서 인식한 얼굴의 주요부위를 68개의 좌표 값으로 출력하며 해당 값들을 통해 얼굴의 전체적인 비대칭 비율을 계산하였다.

    뇌졸중으로 인한 안면 마비 증상을 보이는 환자들의 얼굴 사진들과 정상인의 얼굴 사진들을 미리 구해 앞서 언급한 비대칭 비율을 계산하여 logistic regressionclassification을 활용해 학습 과정을 진행하였다. 학습된 결과를 바탕으로 새로운 얼굴 사진이 주어졌을 때 sigmoid 함수를 이용해 뇌졸중 의심 여부를 판단하여 결과 값을 반환한다.

 

시스템 구성도

프로그램은 크게 세 가지로 이루어진다. 리액트를 이용한 웹 페이지와 장고를 이용한 웹 서버와 머신러닝, 딥러닝 API를 이용한 학습 및 예측으로 구성되어 있다. 이 세 가지가 서로 동작하는 방법은 위 그림과 같이 이루어진다.

 

사용한 API

얼굴의 landmark detection을 위해 구글링을 통해 얼굴을 인식하고 눈, 코 입 등의 좌표를 얻을 수 얻을 수 있는 API를 찾을 수 있었다.
링크 : http://matthewearl.github.io/2015/07/28/switching-eds-with-python/

 

Switching Eds: Face swapping with Python, dlib, and OpenCV - Matt's Ramblings

Switching Eds: Face swapping with Python, dlib, and OpenCV Image credit Introduction In this post I’ll describe how I wrote a short (200 line) Python script to automatically replace facial features on an image of a face, with the facial features from a s

matthewearl.github.io

여기서 제공하는 코드에서 dlib, OpenCV를 이용하여 얼굴을 인식하고 아래 그림과 같이 눈, 코, 입의 좌표를 얻을 수 있다.

다음에는 이 좌표를 가지고 뇌졸중의 증상 중 하나인 안면마비로 인한 안면 비대칭을 logistic regression을 이용하여 학습하고 예측하는 방법을 적어보겠다.

전 세계 사망 원인 2, 한국인 사망 원인 4위인 뇌졸중은 국내에서만 연간 60만 명에 달하는 환자들이 발생하고 있다. 현대인들의 식습관, 흡연, 운동 부족 등의 이유로 인하여 어느 날 갑자기 뇌졸중이 찾아올 수 있기 때문에 일반인은 미리 대비하는 것이 쉽지 않다. 뇌졸중이 발생한 후 적절한 응급 치료를 빠른 시간 내에 받지 못한다면 근력마비, 보행장애, 언어장애, 감각장애 등의 후유증이 생길 수 있고 최악의 경우에는 사망할 수 있다. 따라서 골든타임인 발병 후 6시간에서 최대 10시간 이내에 병원을 찾아 치료받는 것이 중요하다.

(출처: https://www.monews.co.kr/news/articleView.html?idxno=112694)

뇌졸중이 발병되었음을 인지할 수 있는 초기 증상들로는 말할 때 발음의 어눌함, 심한 두통, 얼굴이 부분적으로 마비되는 등 여러 종류가 있을 수 있다. 이들 중 안면 마비 증상이 제3자가 보았을 때 환자가 발생했음을 인지하기 제일 쉬운 방법이다. 뇌졸중이 발병한 환자들은 일반적으로 얼굴 한쪽이 마비되어서 심한 비대칭성을 나타내기 때문이다. 그러나 뇌졸중을 경험하고 있는 환자들은 감각에 대한 둔화가 오는 증상들이 동반되기 쉬워 거울을 보았을 때 스스로 얼굴에 이상이 있음을 인지하기 쉽지가 않다.

그래서 건강한 얼굴 건강한 정신이라는 프로그램을 기획하게 되었다. 이 프로그램은 주위에 제3자가 없더라도 핸드폰이나 노트북 등으로 손쉽게 뇌졸중의 초기 증상인 안면 마비 증상을 인지할 수 있도록 도움을 준다. 1인 가구 또는 혼자 보내는 시간이 많은 이들에게 자신이 뇌졸중을 경험하고 있는지 판단할 수 있도록 자가 진단을 제공하는 것이 이 프로그램의 목적이다.

+ Recent posts