판정 원리
사진을 서버로 보내지 않고 브라우저 안에서 픽셀을 직접 재서 분류합니다. 어떤 값을 어떻게 재는지, 그리고 그 값이 왜 틀릴 수 있는지 숨기지 않고 적었습니다.
왜 얼굴 인식 AI를 쓰지 않나요
브라우저에서 외부 라이브러리 없이 돌릴 수 있는 얼굴 인식 모델이 마땅치 않고, 실사 사진으로 학습된 모델은 일러스트 얼굴에 잘 맞지 않습니다. 그래서 이미지의 픽셀을 직접 재는 방식을 골랐습니다. 정확도는 사람이 보는 것에 못 미치지만, 무엇을 근거로 그렇게 판정했는지 숫자로 보여줄 수 있습니다.
1단계 — 얼굴 찾기
사진을 160픽셀로 줄이고 색을 HSV로 바꾼 뒤, 살색으로 보이는 픽셀만 남깁니다. 그렇게 남은 덩어리 가운데 가장 크고 화면 중앙에 가까운 것을 얼굴로 잡습니다. 머리카락·배경·옷은 대부분 이 단계에서 걸러집니다.
2단계 — 얼굴 크기와 턱선
얼굴로 잡은 영역에서 가로줄마다 폭을 재면 얼굴의 윤곽이 나옵니다. 여기서 세로÷가로 비율과 턱선 테이퍼(아래쪽 폭 ÷ 중간 폭)를 계산합니다. 턱선 값이 작을수록 아래로 갈수록 좁아지는 V라인입니다.
3단계 — 눈
얼굴 위쪽 구간에서 주변보다 어두운 픽셀을 모아 좌우 한 쌍을 눈으로 봅니다. 여기서 눈 가로세로비와 눈 면적을 재고, 눈 윗선을 가로로 훑어 기울기를 직선으로 근사해 눈꼬리 각도를 얻습니다. 바깥쪽이 올라가 있으면 양수, 처져 있으면 음수입니다.
4단계 — 입
얼굴 아래쪽 구간에서 가장 큰 어두운 덩어리를 입으로 잡습니다. 입술은 살색 계열이라 얼굴 영역과 섞이기 쉬워서, 얼굴 안쪽에서 주변보다 어두운 정도를 기준으로 따로 찾습니다. 입 윗선의 가운데 y − 양끝 y가 입꼬리 곡률입니다. 화면 좌표는 아래로 갈수록 커지므로, 양끝이 가운데보다 위로 올라갈수록 이 값이 커집니다. 곧 웃는 입입니다. 입의 가로 폭도 함께 재서 입 너비로 씁니다.
재는 값 여섯 가지
| 값 | 의미 |
|---|---|
| 눈이 둥근 정도 | 눈의 세로÷가로. 클수록 동그랗고, 작을수록 가늘고 길다 |
| 눈꼬리 각도 | 눈 윗선 기울기. 양수면 바깥쪽이 올라가고, 음수면 처진다 |
| 턱선이 갸름한 정도 | 아래쪽 얼굴 폭÷중간 폭. 클수록 V라인, 작을수록 넓고 각지다 |
| 얼굴이 긴 정도 | 얼굴 세로÷가로. 클수록 길쭉하다 |
| 눈 크기 | 두 눈이 얼굴에서 차지하는 면적 |
| 입 너비 | 입 가로 폭÷얼굴 폭 |
이 숫자들은 얼굴을 눌렀을 때 뜨는 창의 측정값
칸에서 그대로 볼 수 있습니다.
판정이 이상하면 어떤 값이 튀었는지 직접 확인할 수 있게 열어 두었습니다.
점수 계산
- 여섯 값을 각각 −1에서 +1 사이로 정규화합니다. 0이 평균적인 얼굴입니다.
- 동물상 10종마다 정해둔 가중치를 곱해 더합니다. 어떤 상이 어떤 값을 중요하게 보는지는 동물상 가이드의 각 카드에 적혀 있습니다.
- 열 개의 합을 softmax로 0~100% 비율로 바꿉니다. 가장 높은 것이 판정 결과이고, 나머지도 창에서 막대로 함께 보여줍니다.
^^ 지수
표정은 따로 셈합니다. 입꼬리 곡률을 가장 크게 보고, 입이 벌어진 정도와
사진 전체의 밝기·채도, 눈매가 납작한 정도를 더해 tanh로 0~100 사이에 눌러 담습니다.
50 이상이면 ^^상, 미만이면 ㅍㅍ상입니다.
한계
- 앞머리가 눈을 덮거나 얼굴이 크게 기울면 눈을 제대로 못 잡습니다.
- 배경이 살색에 가까우면 얼굴 영역이 배경까지 번집니다.
- 눈이 거의 동그란 경우 눈꼬리 각도 신호가 약해집니다. 원은 돌려도 윗선 기울기가 잘 변하지 않기 때문입니다.
- 입이 아주 작거나 머리카락에 가리면 입꼬리를 못 재고, 이때는 밝기 위주로 판정합니다.
이 경우 창에
얼굴 인식 약함
이라고 표시됩니다. - 실제 캐릭터 그림에서는 곰상 쪽으로 쏠리는 경향이 있습니다. 둥글고 넓은 얼굴로 읽히는 그림이 많기 때문입니다.
잘 맞게 올리는 방법
- 얼굴이 사진의 대부분을 차지하도록 자릅니다. 창 안에서 휠로 확대하면 그 영역으로 다시 분석합니다.
- 정면에 가까운 각도, 눈과 입이 가려지지 않은 사진이 좋습니다.
- 배경이 살색과 뚜렷이 구분되는 사진이 좋습니다.