공부/AIFFEL

Going Deeper(CV)_DJ 14 : 카메라 스티커앱을 개선하자!

dong_dong_2 2021. 4. 27. 18:06

1. 들어가며
    - 이전에 만들었던 카메라 스티커앱이 동영상을 처리할 수 있도록 개선하는 프로젝트를 진행하려 한다.
    - 하지만 지난 시간에 살펴봤듯, 동영상을 처리하는 카메라앱을 만들기 위해서는 단순 이미지를 처리하는 작업 이상으로 고려해야 할 것들이 있다.
    - 피사체인 사람이 움직이기 때문에 발생하는 여러가지 예외 상황, 처리속도의 문제, 화면 떨림 등의 안정성 문제 등에 대응하는 방법이 필요하다.
2. 프로젝트 1 : moviepy로 비디오 처리하기
    - 먼저 동영상을 쉽게 다룰 수 있는 방법을 찾고 있다.
    - 대안으로 떠오른 것은 moviepy라는 파이썬 기반의 동영상 처리 라이브러리이다.
    - 하지만 동영상을 다룰 때의 실행시간, 즉 처리 속도가 중요하다는 것을 잊으면 안된다.
    - 그래서 moviepy를 쓰는 것이 성능면에서 적합한지 알아본다.
    - 코드를 통해 moviepy로 파일을 읽어와서 width를 조정하여 축소시켜 화면에 플레이해보고 저장해봤다.
    - 그리고 원본과 비교해서 어떻게 다른지 보았다.
    - 다음으로는 밝기를 50% 줄여봤다.
    - 마지막으로 OpenCV와 moviepy가 영상을 읽고 쓰는데 시간이 얼마나 걸리는지 측정해봤다.
3. 프로젝트 2 : 어디까지 만들고 싶은지 정의하기
    - 실시간 카메라 스티커앱 만들기
       1) 이전에 img2sticker_orig라는 메소드를 구현해서 addsticker라는 py확장자를 가진 파일을 저장한 적이 있다.
       2) 이 메소드를 복사하여 img2sticker라는 메소드로 만들고 newaddsticker라는 py확장자를 가진 파일로 저장했다.
       3) 오늘은 이 파일을 보완해서 구현하는 과정을 진행한다.
       4) 먼저 위에서 말한 파일을 만들고 카메라를 실행시켜서 잘 작동하는지 테스트 했다.
    - 스티커앱을 실행하고 카메라를 고정하고 서서히 멀어지거나 가까이 다가와 보자.
       1) 얼만큼 멀리 혹은 가까이 카메라와 거리를 두면 얼굴을 찾지 못하는지 기록해보자.
       2) 일반적으로 약 15ch ~ 1m 30cm 범위 사이에서 얼굴 인식이 가능하다고 한다.
       3) 실제로 측정했을 때 1m쯤 멀어지니까 스티커가 불안정하게 붙었다. (거의 대부분 안 붙어있었다)
    - 다시 자리로 돌아온 후 고개를 상하좌우로 움직여보자.
       1) yaw, pitch, roll 각도의 개념을 직접 실험해 보고 각각 몇 도까지 정상적으로 스티커앱이 동작하는지 기록해보자.
       2) 참고사항
          (1) yaw : y축 기준 회전 -> 높이 축
          (2) pitch : x축 기준 회전 -> 좌우 축
          (3) roll : z축 기준 회전 -> 거리 축
       3) 일반적인 허용 범위는 아래와 같다고 알려져 있다.
          (1) yaw : -45도 ~ 45도
          (2) pitch : -20도 ~ 30도
          (3) roll : -45도 ~ 45도
       4) 실제 측정 결과 본인의 가르마로 인해 이마가 부분적으로 들어나 있는데 이마가 보이면 스티커가 잘 붙어있는 경향이 있고, 이마가 안 보이고 머리카락만 보이면 조금만 뒤틀어도 스티커가 떨어지는 경향을 보였다.
4. 프로젝트 3 : 스티커 Out Bound 예외처리 하기
    - 이전 스텝에서 만든 스티커앱의 문제점들을 찾아서 보완해 가도록 하자.
    - 지금까지 만든 스티커앱을 이용해서 예외 상황을 찾아보자. 특히 서서히 영상에서 좌우 경계 밖으로 나가며 코드의 행동을 확인해보자.
       1) 얼굴이 카메라 왼쪽 경계를 벗어나서 detection 되는 경우 refined_x의 값이 음수가 된다.
       2) img_bgr[..., refined_x:...]에서 numpy array의 음수 index에 접근하게 되므로 예외가 발생한다.
       3) 따라서 x축이 음수가 됬을 경우 처리를 해줘야 한다.
    - Out bound 오류(경계 밖으로 대상이 나가서 생기는 오류)를 해결하자.
       1) 해당 오류는 과제에서 해결했다.
5. 프로젝트 4 : 스티커앱 분석 - 거리, 인원 수, 각도, 시계열 안정성
    - 멀어지는 경우 왜 스티커앱이 동작하지 않는지 분석해보자.
       1) detection, landmark, blending 단계 중 무엇이 문제일까?
          (1) dlib detection이 문제이다. 멀어지면 detector_hog 단계에서 bbox가 출력되지 않는다.
    - detector_hog의 문제를 해결하기 위해, 이미지 피라미드를 조절하여 성능을 향상시키는 간단한 방법이 있다.
       1) 이 방법을 활용하여 img2sticker 메소드를 고쳐보자.
    - 수정 후 실행시켜 보니 문제점이 생겼다.
       1) 속도가 너무 느려졌다.
       2) 기존 30ms에서 150ms로 5배 정도 느려졌다.
       3) 때문에 실시간 구동이 불가능하다. 보기에 너무 답답하다.
    - 실행시간을 만족할 수 있는 방법을 찾아보자.
       1) hog 디텍터를 딥러닝 기반 디텍터로 변경할 수 있다.
       2) hog 학습 단계에서 다양한 각도에 대한 hog 특징을 모두 추출해서 일반화 하기 어렵기 때문에 딥러닝 기반 검출기의 성능이 훨씬 좋다.
       3) opencv는 intel cpu을 사용할 때 dnn 모듈이 가속화를 지원하고 있다.
       4) 따라서 mobilenet과 같은 작은 backbone 모델을 사용하고 ssd를 사용한다면 충분히 만족할 만한 시간과 성능을 얻을 수 있다.
6. 프로젝트 5 : 칼만 필터 적용하기
    - 카메라 앞에서 가만히 있을 때 스티커의 움직임을 관찰해 보자. 어떤 문제가 발생하는가?
       1) 가만히 있어도 스티커의 크리가 일정하게 유지되지 않고, 떨리는 것처럼 보이는 현상이 발생한다.
    - 이론 강의에서 배운 칼만 필터를 적용해서 스티커 움직임을 안정화시켜라.
       1) 칼만 필터를 구현한 모듈인 kalman파일과 이를 이용하여 tracker를 구현한 kpkf파일이 있고, 이를 이용하여 칼만필터를 적용한 webcam_sticker_kf파일을 함께 첨부했다.
       2) 실행시켜보면 웹캠이 아니라 샘플 동영상에 칼만필터가 적용된 것을 확인할 수 있는데 이 코드를 살짝만 바꾸면 웹캠에 적용할 수 있다.
       3) 이 파일을 이용하여 칼만 필터를 적용한 스티커앱을 실행시켜보자.