본문 바로가기

TIL

[TIL 2024. 05. 17] 얼굴인식 관련 의사결정

우리팀이 만들고 있는 AI 키오스크 도우미에는 기본적으로 키오스크에 내장된 카메라를 통해 해당 키오스크 사용자가 고령층인지 아닌지를 판단하는 기능이 필수적이다.

 

기획 초반에는 키오스크 자체를  "고령자를 위한 키오스크"라고 전제하고, 현재의 키오스크 사용자가 "사람"인지 여부만 카메라로 확인하는 방안도 검토했다.

 

하지만 우리 팀 프로젝트가 지향하는 바를 검토했을 때, 애초에 키오스크 사용이 어려운 어르신들이 "고령층을 위한 키오스크"라는 개념에 편리하게 접근하여 이용하실지에 대한 의문이 있었다. 그래서 그냥 일반인과 고령층 모두가 사용할 수 있는 키오스크라는 전제 하에 얼굴인식을 통해 해당 사용자의 연령을 추론하여 처리해야 할 필요성이 있었다.

 

이와 같은 얼굴인식을 위해 우리가 선택할 수 있는 선택지는 다음의 3가지였다.

 

1. gpt사용 (esp. gpt-4o사용)

2. deepface 사용

3. deepface외의 다른 오픈소스 라이브러리를 사용


 

우선 가장 먼저 제외된 선택지는 3번이었다.

 

deepface라는 라이브러리의 특성 자체가 시중에 존재하는 대부분의 얼굴인식 오픈소스들을 모아다가 한번에 사용할 수 있게 만든 것인만큼, 굳이 deepface외의 다른 오픈소스 라이브러리를 사용하는 것은 크게 효과가 없다는 판단이 들었다.

 

실제로 deepface가 제공하는 다양한 model, detector 버전들을 두고, 하나하나의 라이브러리만을 사용하는 것은 비효율적이다.

 

그리고 그 다음으로 제외된 선택지가 1번이었다.

 

팀원인 지현님과 함께 "사진"을 처리할 수 있는 gpt 4 이후의 버전 중에서도 가장 최근에 공개된 gtp-4o를 써본 결과, 반환되는 응답값의 정확도는 별론으로 하더라도 애초에 반환값에 "나이의 예측값"이 없는 경우가 너무 많았다.

 

즉, 주로 gtp-4o가 반환하는 응답의 요지는 "사람의 나이 판단은 복합적인 요소로부터 영향을 받으므로, 정확한 답을 주기 어렵다"였다. 지현님과 내가 각각 4번을 다른 사진들로 시도해본 결과, 나는 4번 중에 한 번만 신구 사진에 대해 60~70대 같다는 응답을 들었고, 나머지는 모두 위와 같이 답을 주기 어렵다는 응답을 얻었다. (지현님은 4번 다 답을 주기 어렵다는 응답이었다..)

 

따라서 신구 사진에 대해 60~70대라고 응답한 정확도를 판단하는 것 자체도 응답의 빈도값이 너무 낮아서 어려웠다.

무엇보다 gpt-4o를 사용한다고 하면, 얼굴인식 때에 나이의 추측값 자체를 얻지 못하는 경우가 너무 많아서 실제 이를 프로젝트에 활용하기는 어렵다는 결론을 냈다.

 

cf. gpt-4o를 사용하면 deepface를 사용할 때와는 달리 로컬에서 별도로 사진을 찍어서 "사람인지"에 대해 판단하고, 그 사진을 gpt-4o에게 보내서 연령을 추론하는 방식을 사용해야 했다 .즉, 2단계를 거쳐야 하는 셈이라 이 부분도 고려할 수 밖에 없었다.

 


이제 deepface사용은 정해졌지만, deepface내에서도 stream()을 사용할지, analyze()를 사용할지에 대한 의사결정이 필요했다.

 

pair programming을 하고 있는 지현님과 각각 써보고 논의한 결과, 나는 stream()을 사용하는 게 정확도가 좀 더 높아서 선호했고, 지현님은 속도 면에서 analyze()를 선호하셨다.

 

이에 대한 의사결정은 다른 팀원들의 의견도 들어봐야 할 듯해서 다른 팀원들에게도 이 사항을 공유하고, 두 개를 비교해서 각각 사용해보도록 하고 의견을 취합했다.

 

그 과정에서 컴퓨터 사양이 높으면 두 방식 사이의 속도 차이가 현격해진다는 점을 발견할 수 있었다.

즉, 컴퓨터 사양이 높은 편인 지현님은 analyze()가 매우 빠르게 처리됐는데, 나를 포함한 나머지 팀원들은 두 가지의 속도 면에서는 크게 차이가 없었다.

 

대신 정확도 면에서는 아무래도 stream()이 좀 더 낫다는 현준님의 피드백이 있었다.

그리고 팀원들과의 논의 결과, 아무래도 키오스크에 들어가는 컴퓨터에 높은 사양을 기대할 수는 없다는 전제 하에 stream()을 사용하는 게 좋겠다는 의견일치가 있었다.

 

(cf. 오늘자로 stream()을 통해 age값을 print해보는 데 까지는 오픈소스 코드 자체를 수정했다.)

 


참고로!
stream()을 쓸 건지, analyze()를 쓸 건지에 파생되는 하위 의사결정도 있었다.

stream()을 쓰게 된다면, 오픈소스 라이브러리의 코드를 수정해서 활용하게 되는 만큼, 우리가 수정한 코드를 별도로 배포해서 활용해야 한다. 다행히도 deepface의 license는 deepface의 개발자의 성명만 언급하면 대부분의 활동이 자유로웠다. 배포해서 사용하는 방법으로는 github에서 배포를 진행하거나 pypi(->pip install로 사용가능해짐)를 사용하는 방법이 있다.

analyze()를 사용하면 pip install deepface만으로 사용이 가능하다

--> stream()을 활용해서 진행하기로 했으니, 배포해서 관리하는 방법도 이후에 TIL로 정리해둬야겠다