본문 바로가기
  • 실행력이 모든걸 결정한다
개발 프로젝트/[개인] Web - 마스크 씌워주는 인공지능

[개발 완료] 마스크 씌워주는 인공지능

by 김코더 김주역 2021. 6. 6.
반응형

<실행 영상>

https://youtu.be/akly1JzHDoE

 

Github 링크 (소스 코드)

Spring Server

https://github.com/jooyeokkim/AIMask-SpringServer

 

jooyeokkim/AIMask-SpringServer

Contribute to jooyeokkim/AIMask-SpringServer development by creating an account on GitHub.

github.com

 

Flask Server

https://github.com/jooyeokkim/AIMask-FlaskServer

 

jooyeokkim/AIMask-FlaskServer

Contribute to jooyeokkim/AIMask-FlaskServer development by creating an account on GitHub.

github.com

 

 

프로젝트 소개

  • 프로젝트 이름 : 마스크 씌워주는 인공지능
  • 기술 스택 : Spring Framework, Flask Framework, Bootstrap, OpenCV, AI
  • 진행 인원 및 작업 기간 : 1인, 2021.4.10 ~ 2021.06.05 (주말, 휴일)
  • 사용 프로그램 : Visual Studio Code
  • 버전 관리 툴 : Git

 

 

프로젝트 내용

<개요>

  • 웹 프로젝트 구성
  • 마스크 합성
  • UploadView
  • ImageView
  • Result

 

1. 웹 프로젝트 구성

사용자가 처음에 /uploadView를 요청하게 되면 Spring Server의 Controller는 사용자를 uploadView.jsp로 이동시킨다.

uploadView.jsp에서는 사용자가 업로드할 이미지 파일을 골라서 /upload로 전송할 수 있게 한다.

/upload에서는 사용자가 올린 이미지를 구분하기 위해서 파일명에 시드값을 포함해서 지정해주고, 지정된 파일명으로 Spring 서버에 저장한 뒤에 사용자를 ImageView.jsp로 이동시키고, 사용자가 보낸 이미지와 일치하는지 확인하게 한다. 여기서 사용자가 다음을 누르면 파일명이 Flask 서버의 /aimask로 전송된다.

/aimask에서는 파일명을 확인하여 Spring 서버에 있는 이미지 파일을 가져와서 Flask서버에 저장하고, mask.py의 get_mask_img() 메소드를 호출한다.

get_mask_img() 메소드는 원본 이미지와 마스크를 합성하고, 합성한 이미지를 result_image 디렉토리에 저장하는 역할을 한다.

최종적으로, 사용자를 result.html로 이동시켜서 결과물을 화면에 출력하고, 사용자가 원할 경우에 이미지 파일을 다운로드할 수 있게 했다.

 

 

2. 마스크 합성

1) 이미지 선행 작업

AI가 이미지를 잘 인식할 수 있도록 이미지에 대한 선행 작업이 필요했으며, 그 선행 작업은 다음과 같다.

  • 크기 조절
  • 보간
  • 회색조 이미지로 변환

 

2) AI를 적용하여 얼굴 인식하기

학습 데이터를 가져오는 것은 cv의 CascadeClassifier() 메소드를 이용했다.

이미지 인식을 진행하기 전에 얼굴, 코, 입에 대해 각각 AI의 인식 민감도를 설정해야 하는데, 민감도를 너무 높게 설정하면 AI는 원하는 부위가 아닌 다른 부분을 찾게 될 수도 있고, 민감도를 너무 낮게 설정하면 원하는 부위를 찾지 못할 수도 있다.

특히 얼굴은 민감도를 높게 설정함으로써 최대한 많은 후보들을 고를 수 있게 했다. AI가 얼굴을 찾았다고 하더라도 그 얼굴 안에서 코와 입을 찾지 못했다면 다음 후보로 넘기면 되기 때문에 오히려 정확도가 높아질 것으로 기대했다.

 

3) 유력 후보 선정

  • 코 : 얼굴의 중심점과 가장 가까운 후보를 선택
  • 입 : 얼굴에서 가장 아래 부분에 위치하는 후보를 선택

 

4) 마스크 크기, 각도 설정

  • 마스크 가로 : 코와 입 사이의 거리 x 3.5
  • 마스크 세로 : 코와 입 사이의 거리 x 2.3
  • 마스크 각도 : 코와 입 사이의 각도

 

5) 마스크 추출

원본 이미지 위에 덮어 씌울 mask를 추출해야 하는데, 여기서 말한 mask는 사람이 쓰는 마스크라는 뜻이 아니고 배경 이미지 위에 씌우는 이미지라는 뜻이다. 마스크 이미지에서 마스크를 경계면대로 자르지 않고 그대로 원본 이미지에 덮어 씌운다면, 마스크 외의 부분도 같이 합성이 되버릴 것이다.

크기와 각도가 조절된 마스크 이미지를 회색조로 변경한 뒤에, 색상 값 10을 넘기는 픽셀은 모두 색상 값을 255로 변경하는 threshold 방법으로 mask를 생성했다.

 

[크기와 각도가 조절되기 전의 마스크 이미지]

 

6) 마스크 덮어 쓰기

적당히 잘 자른 마스크를 원본 이미지에 덮어 써서 최종 결과물을 만드는 작업이다.

원본 이미지에서 마스크 이미지를 덧붙일 부분(roi)를 추출하고 그 부분을 mask와 합성했다.

 

 

3. UploadView

 

 

4. ImageView

 

 

5. Result

[저장]

 

 

프로젝트를 마치며...

개인 프로젝트이다보니 알아야 될 것이 매우 많았던 만큼, 배운 것도 많았던 프로젝트였다.

특히 처음으로 Spring, Flask 총 2개의 웹 프레임워크를 이용하게 되었는데, 두 개의 서버로 분리한 이유는 파이썬이 연산 관련 라이브러리가 잘 되어 있기 때문이다. 그래서 이미지 처리와 AI작업은 Flask에 맡겼다.

작업 하면서 깨달은 것들 중 중요하면서 가장 기억에 남는 3가지를 적자면,

첫 번째는 Spring은 Workspace경로가 아닌 서버의 실제 경로를 기준으로 파일을 저장하고 불러올 수 있다는 것이고,

두 번째는 파일명을 정할 때는 날짜를 기준으로 시드 값을 생성하는 것이 중복을 막는 좋은 방법이라는 것이고,

세 번째는 웹 요소들을 가로로 넓게 배치하면 breakpoint처리가 어려워 진다는 것이다. 저번 프로젝트(주식 웹 어플리케이션)에서는 웹 요소들을 가로로 거의 꽉 채우다시피 배치했었는데, 이번 프로젝트는 좌우에 여유 공간을 충분히 둬서 확실히 웹 구성과 breakpoint처리가 저번 프로젝트보다 더 깔끔했다.

그리고 가장 힘들었던 작업은 AI의 민감도를 설정하는 작업이었다. 최적의 값을 찾기 위해 여러 샘플 이미지들을 대상으로 계속 테스트했고, 필자가 설정한 민감도가 최적이라는 보장은 없지만 정확도는 나쁘지 않다고 생각한다.

프로젝트를 하며 가장 아쉬웠던 점은, 학습된 AI가 고개를 많이 꺾은 사람의 얼굴은 잘 찾지 못했다는 것이었다. 얼굴의 민감도를 많이 높여봐도 잘 찾지 못했는데, 아마 학습시킬 때 고개를 많이 꺾은 인물 이미지 샘플의 수가 충분하지 않았던 것 같다.

AI 학습 데이터를 이용하여 재밌는 프로젝트를 만들 수 있어서 재밌었고, 귀중한 시간이었다.

다음 프로젝트는 OpenAPI를 이용하여 더 실용적인 작품을 만들어 볼 계획이다.

반응형

댓글