본문 바로가기
코딩과 알고리즘

파도(20) - 동영상 얼굴인식

※ '파도'는 크레이의 파이스크립트 도전기의 줄임말입니다.

지난 게시글에서 연재되는 글입니다 => https://itadventure.tistory.com/561

 

파도(19) - 파이스크립트 동영상 재생! 근데 넘 느려요 ㅎ..

※ '파도'는 파이스크립트 도전기의 줄임말입니다. 지난 게시글에서 연재되는 글입니다. https://itadventure.tistory.com/560 파도(18) - 랜덤고양이 이미지 불러오기 ※ '파도'는 크레이의 '파이스크립트

itadventure.tistory.com

 

첩보 영화를 보다 보면 악당들이 주인공을 찾기위해 CCTV에서의 영상이 얼굴을 인식해 찾아주는 장면이 있는데요. 물론 반대의 경우도 있지만요 :)
인물까지는 아니더라도 파이썬에서는 이미 훈련된 데이터를 이용해 사진에서 얼굴의 위치를 판독할 수 있습니다.

사진도 물론이거니와 동영상에서도 말이지요 
파이스크립트에서는 느린게 단점입니다. ( 크레이의 컴퓨터만 그런지도 모르겠습니다 ㅎㅎ.. )

 

cv2의 얼굴인식 XML

 

cv2 는 영상을 다루는 도구인 동시에 장면에서 사람의 얼굴위치를 판독하는 기능도 가지고 있는데요.
캐시케이드 클래스파이어(CascadeClassifier) 라는게 바로 그것입니다.
개발단계에 사용할 수 있도록 공개되어 있지요.

얼굴 인식기능만 있는게 아니라 손 위치라든가 사람 몸도 판별하는 등의 기능도 들어있긴 하지만
오늘은 얼굴 위치 판독에 집중해 보도록 하겠습니다.

얼굴인식을 위해서는 얼굴위치를 판독하기 위해 훈련된 데이터가 있어야 하는데요.
보통 'haarcascade_frontalface_alt2.xml'라는 데이터를 많이 사용합니다.

다른 종류의 XML 파일들은 opencv 공식 GITHUB, 아래 URL을 방문하시면 찾아보실수 있습니다.

https://github.com/opencv/opencv/tree/master/data/haarcascades

 

<py-env> 에 XML 훈련데이터 포함

 

'구슬이 서말이라도 꾀어야 보배다'라는 말이 있지요?
실제 사용해보지 못한다면 별 의미가 없을테니, 파이스크립트에서도 이 기능을 활용해보겠습니다!

지난 소스에서 변경된 부분을 단계적으로 설명드리고 마지막에 최종 소스를 공개하도록 할텐데요.

<py-env> 태그에 영상주소가 변경되었습니다. 픽사베이에서 다운받은 공개파일입니다.
( URL : 
https://pixabay.com/ko/videos/여자-춤-헤드폰-여성-모델-44686 )

그리고 얼굴을 판독할 xml 파일을 포함했는데요.
haarcascade_frontalface_alt2.xml 파일이 
얼굴인식용으로 성능이 좋다고 합니다.


    <py-env>
    - matplotlib
    - opencv-python
    - paths:
      - http://dreamplan7.cafe24.com/pyscript/pixabay-44686.mp4
      - http://dreamplan7.cafe24.com/pyscript/haarcascade_frontalface_alt2.xml
    </py-env>


성능좋은 XML 이 아닌 기본 XML 로 테스트한 결과
엉뚱한 위치를 얼굴로 판독하더군요.

특히 배경 부분을요 ㅎ..


이 XML 파일을 사용하는 방법은 아래와 같습니다.
먼저 캐시케이드 클래스파이어 모듈을 이용해 XML 파일을 불러온 다음에,


얼굴인식 = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml')

 

 



사진이나 동영상의 해당 장면을 파라미터로 넣어주면 되는데요.
영상의 RGB 색상이 반대이기 때문에 반전한 다음 판별하도록 하였습니다.


reverse = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
판독된얼굴들 = 얼굴인식.detectMultiScale(reverse)


판독된얼굴들 변수에는 장면에서 판독된 얼굴의 위치정보가 입력됩니다.
여러사람이 존재할 수 있기 때문에 아래와 같은 배열형태로 입력되는데요.


[[x , y, w, h], [x , y, w, h], ... ]


이 배열을 받아서, 장면에 사각형을 그려주는 코드는 아래와 같습니다.
반전된 색상을 바로 잡아준 장면이 reverse 변수에 있으니 이 변수에 바로 찍는 것이지요.


for (x, y, w, h) in 판독된얼굴들:
    cv2.rectangle(reverse, (x, y), (x + w, y + h), (255, 255, 255), 5) 


좋은 사례는 아니지만 영상 중간에 손가락을 얼굴로 잘못 판별하는 경우가 있긴 합니다.
이럴 때 2개의 얼굴이 판별되기도 합니다.

그 외 변경된 부분은 영상의 해상도가 좀 커서 setInterval 대신 setTimeout 이벤트를 사용해서 영상을 재생하도록 했습니다. 이 경우 최대속도를 발휘해 재생이 됩니다.


  gc.collect()  
  setTimeout(create_proxy(ShowFrame), 0)

setTimeout(create_proxy(ShowFrame), 0)


 

최종소스로 마무~리

최종 소스는 아래와 같고 실행 예제는 아래 URL에서 확인해 보실 수 있습니다.
http://dreamplan7.cafe24.com/pyscript/pycam-2.html

<!DOCTYPE html>
<html> 
  <head> 
    <link 
      rel="stylesheet" 
      href="https://pyscript.net/alpha/pyscript.css" 
    /> 
    <script 
      defer 
      src="https://pyscript.net/alpha/pyscript.js"
    ></script> 
    <py-env>
    - matplotlib
    - opencv-python
    - paths:
      - http://dreamplan7.cafe24.com/pyscript/pixabay-44686.mp4
      - http://dreamplan7.cafe24.com/pyscript/haarcascade_frontalface_alt2.xml
    </py-env>
    <py-config>
      - autoclose_loader: true
      - runtimes:
        -
          src: "https://cdn.jsdelivr.net/pyodide/dev/full/pyodide.js"
          name: pyodide-0.20
          lang: python
    </py-config>
  </head>
  <body> 
    <link rel="stylesheet" href="pytable.css"/>
    프레임번호 : <div id="frameNo"></div>
    <div id="graph"></div>
<py-script>
import matplotlib.pyplot as plt
import cv2
from js import document, setInterval, setTimeout
from pyodide.ffi import create_proxy
import gc

얼굴인식 = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml')

캡쳐 = cv2.VideoCapture('pixabay-44686.mp4')
프레임번호 = 0

def ShowFrame():
  global 캡쳐, 그래프, cv2, plt, 프레임번호, document, 얼굴인식
  캡쳐.set(cv2.CAP_PROP_POS_FRAMES, 프레임번호)
  ret, frame = 캡쳐.read() # 두 개의 값을 반환하므로 두 변수 지정
  
  reverse = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)  
  판독된얼굴들 = 얼굴인식.detectMultiScale(reverse)
  for (x, y, w, h) in 판독된얼굴들:
    cv2.rectangle(reverse, (x, y), (x + w, y + h), (255, 255, 255), 5)
  그래프 = plt.figure(figsize=(8, 6))
  plt.axis('off')
  ax = plt.gca()
  ax.margins(x=0, y=0)
  그래프.tight_layout()
  plt.imshow(reverse)
  pyscript.write('graph', 그래프)
  plt.close(그래프)
  document.getElementById('frameNo').innerHTML=프레임번호  
  프레임번호=프레임번호+15
  gc.collect()  
  setTimeout(create_proxy(ShowFrame), 0)

setTimeout(create_proxy(ShowFrame), 0)

</py-script> 
  </body> 
</html>

 

오늘은 영상에서 얼굴의 위치를 판별하여 사각형을 그려보는 부분을 다뤄보았는데요.
캐시케이드 클래스파이어! 라는 기술을 사용해 보았습니다.
무슨 게임 스킬 같네요 ㅎㅎ

오늘도 필요하신 분께 도움이 되셨을까 모르겠습니다.
읽어주시고 구독하시고 찾아와 주시는 모든 분들께 감사드립니다.

유용한 정보라면 공감 한방, 댓글은 베리 베리 굿잡!
감사합니다!


다음 게시글 : https://itadventure.tistory.com/563

 

파도(21) - 동영상 사람인식 & HTML 캔버스 연동

※ '파도'는 크레이의 '파이스크립트 도전기'의 줄임말입니다. 지난 게시글에서 연재되는 글입니다 => https://itadventure.tistory.com/562 https://itadventure.tistory.com/561 파도(19) - 파이스크립트 동영상..

itadventure.tistory.com