"얼굴추적"의 두 판 사이의 차이

Pywiki
둘러보기로 가기 검색하러 가기
(새 문서: == 개요 == 주 방법은 [https://www.youtube.com/watch?v=3LNHxezPi1I 링크], [https://www.youtube.com/watch?v=tpWVyJqehG4&t=53s 링크(얼굴인식 스노우 카메라 따라만...)
 
 
(같은 사용자의 중간 판 6개는 보이지 않습니다)
4번째 줄: 4번째 줄:
 
단순히 찾는 것 뿐이라면 cv2만으로도 가능하지만, 매끄럽게 처리하려면 dlib이 있어야 좋다.
 
단순히 찾는 것 뿐이라면 cv2만으로도 가능하지만, 매끄럽게 처리하려면 dlib이 있어야 좋다.
  
== 방법 ==
+
= 방법 =
  
=== 준비 ===
+
== 준비 ==
 +
 
 +
=== 공통과정 ===
 +
아래에 이어질 모든 과정 이전에 사용될 준비과정을 여기에 담는다.
 
{| class="wikitable"
 
{| class="wikitable"
 
!과정
 
!과정
14번째 줄: 17번째 줄:
 
|이후 이 디렉터리 안의 모델을 사용한다.
 
|이후 이 디렉터리 안의 모델을 사용한다.
 
|-
 
|-
|사용할 모듈 불러오기
+
|사용할 모듈 설치 및 불러오기
|<syntaxhighlight lang="python">
+
|pip install cmake dlib opencv-python numpy
 +
 
 +
* 윈도우에선 visual studio 설치가 선행되어야 한다.(설치 옵션에서 C++ 모듈을 포함하게 하면 관련 컴파일러 등이 함께 설치된다.)
 +
* cmake는 dlib를 설치하기 위해 필요하다.
 +
<syntaxhighlight lang="python">
 
import dlib  # 얼굴인식
 
import dlib  # 얼굴인식
 
import cv2  # 이미지처리
 
import cv2  # 이미지처리
26번째 줄: 33번째 줄:
 
|-
 
|-
 
|모델객체 생성
 
|모델객체 생성
|<syntaxhighlight lang="python">
+
|이미 학습된 bat파일을 불러오는데, 이는 [https://github.com/davisking/dlib-models/blob/master/shape_predictor_68_face_landmarks.dat.bz2 링크]에서 다운받을 수 있다.<syntaxhighlight lang="python">
 
detector = dlib.get_frontal_face_detector()  # 얼굴탐지모델
 
detector = dlib.get_frontal_face_detector()  # 얼굴탐지모델
sp = dlib.shape_predictor('models/shape_predictor_68_face_landmarks.dat')  # 얼굴 랜드마크 탐지 모델. 학습된 모델을 가져온다.
+
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')  # 얼굴 랜드마크 탐지 모델. 학습된 모델을 가져온다.
 
+
cap = cv2.VideoCapture(0)  # 영상 캡쳐. 경로 대신 0을 넣으면 웹캠이 켜진다.
 
</syntaxhighlight>
 
</syntaxhighlight>
|-
 
|
 
|
 
|-
 
|얼굴 특징점 표시
 
|
 
 
|}
 
|}
  
=== 얼굴 찾기 ===
+
== 얼굴 찾기 ==
<syntaxhighlight lang="python">
+
얼굴을 찾아 네모칸으로 표시한다.(필요에 따라 변형하여 사용하면 될듯.)
# 영상 캡쳐
+
{| class="wikitable"
cap = cv2.VideoCapture('영상경로')  # 경로 대신 0을 넣으면 웹캠이 켜진다.
+
!과정
 +
!코드 및 설명
 +
|-
 +
|함수 정의
 +
|코드를 파편화 하기 위해 함수를 정의하여 사용한다.<syntaxhighlight lang="python">
 +
def find_face(img):
 +
    '''이미지를 받아 해당 얼굴을 찾는다.'''
 +
    faces = detector(img)  # 디텍터에 이미지를 넣어주어 얼굴을 찾는다.
 +
    for face in faces:
 +
        # 인식이 잘 되었는지 확인. 네모 그리기. 기존 이미지에 덧씌워 보여준다.
 +
        img = cv2.rectangle(img, pt1=(face.left(), face.top()), pt2=(face.right(), face.bottom()),
 +
                            color=(255, 255, 255),  # 색 지정이 가능하다.
 +
                            thickness=2,            # 두께지정
 +
                            lineType=cv2.LINE_AA    # 선의 타입 지정
 +
                            )
 +
    cv2.imshow('window', img)  # 창에 해당하는 이미지를 띄운다.
 +
    cv2.waitKey(1)  # 이게 있어야 창이 제대로 열린다.
  
def find_face(cap)
+
</syntaxhighlight>
     ret, img = cap.read()  # 캡처한 영상을 프레임 단위로 읽는다.
+
|-
     if not ret:
+
|실행
 +
|다음과 같이 실행한다.<syntaxhighlight lang="python">
 +
while True:  # 기본적으로 계속 진행
 +
     ret, img = cap.read()  # 캡처한 영상을 프레임 단위로 읽는다.
 +
     if not ret: # 잘 찍히면 ret은 True를 반환한다.
 
         break  # 프레임이 없다면 종료.
 
         break  # 프레임이 없다면 종료.
     faces = detector(img)  # 디텍터에 이미지를 넣어주어 얼굴을 찾는다.
+
     find_face(img)
    face = faces[0]  # 인식된 얼굴 중 첫번째.
 
   
 
    # 인식이 잘 되었는지 확인. 네모 그리기.
 
    # 기본 이미지에 덧씌워 보여준다.
 
    # 좌 상단과 우 하단을 잡아준다.
 
    img = cv2.rectangle(img, pt1=(face.left(), face.top()), pt2=(face.right(), face.bottom)
 
            color=(255,255,255),    # 색 지정이 가능하다.
 
            thickness=2,            # 두께지정
 
            lineType=cv2.LINE_AA    # 선의 타입 지정
 
            )
 
   
 
   
 
   
 
    cv2.imshow('창이름', img)  # 창에 해당하는 이미지를 띄운다.
 
    cv2.waitKey(1)  # 1ms만큼 대기 해야 창이 제대로 열린다.
 
   
 
   
 
   
 
   
 
while True:  # 기본적으로 계속 진행
 
    find_face(cap=cap)
 
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
|}
  
=== 얼굴 특징점 찾기 ===
+
== 얼굴 특징점 찾기 ==
얼굴 찾기를 진행한 후 진행한다.<syntaxhighlight lang="python">
+
위에서 함수만 바꾸어주면 얼굴의 특징점을 찾아준다.<syntaxhighlight lang="python">
def find_shape(img, face)  # img가 꼭 필요할까?
+
def find_shape(img):
     dlib_shape = predictor(img, face)  # 특징점을 리턴받는다.
+
    '''이미지를 받아 얼굴의 특징점을 찾는다.'''
   
+
    faces = detector(img)  # 디텍터에 이미지를 넣어주어 얼굴을 찾는다.
    shape_2d = np.array([[p.x, p.y] for p in dlib_shape.parts()])  # 연산을 위해 배열로 저장.
+
     for face in faces:
    for s in shape_2d:  # 해당 좌표에 원 그리기. 68개의 특징점을 찾는다.
+
        dlib_shape = predictor(img, face)  # 특징점을 리턴받는다.
        cv2.circle(img, center=tuple(s), radius=1, color=(255, 255, 255), thickness=2, lineType=cv2.LINE_AA)
+
        shape_2d = np.array([[p.x, p.y] for p in dlib_shape.parts()])  # 연산을 위해 배열로 저장.
</syntaxhighlight>
+
        for s in shape_2d:  # 해당 좌표에 원 그리기. 68개의 특징점을 찾는다.
 +
            cv2.circle(img, center=tuple(s), radius=1, color=(255, 255, 255), thickness=2, lineType=cv2.LINE_AA)
  
=== 얼굴을 특정 이미지로 가리기 ===
+
    cv2.imshow('window', img)  # 창에 해당하는 이미지를 띄운다.
<syntaxhighlight lang="python">
+
     cv2.waitKey(1)  # 이게 있어야 창이 제대로 열린다.
def blind_face(img, address='파일경로.png')
+
</syntaxhighlight>앞으로의 목표는 많은 얼굴에 대해서도 찾는 것...
    dlib_shape = predictor(img, face)  # 특징점을 리턴받는다.
 
    shape_2d = np.array([[p.x, p.y] for p in dlib_shape.parts()])  # 연산을 위해 배열로 저장.
 
   
 
    center_x, center_y = np.mean(shape_2d, axis=0).astype(np.int)
 
     overlay = cv2.imread(address, cv2.IMREAD_UNCHANGED)  # 알파채널까지 읽기 위한 옵션.
 
   
 
    # compute face size
 
    face_size = max(max_coords - min_coords)
 
    face_sizes.append(face_size)
 
    if len(face_sizes) > 10:  # 덮을 이미지가 얼굴 인식에 따라 급격하게 변하기 때문에, 이를 중화하기 위한 코드.
 
        del face_sizes[0]
 
    mean_face_size = int(np.mean(face_sizes) * 1.8)  # 얼굴을 적절히 덮기 위한 보정.
 
    ori = img.copy()
 
    # 다음 사용하는 함수는 아랫쪽에 정의되어 있다.
 
    result = overlay_transparent(background_img=ori,    # 기존 이미지.
 
                    img_to_overlay_t=overlay,          # 덮을 이미지.
 
                    center_x + 8, center_y - 25,        # 얼굴의 중심을 찾고 숫자로 보정해준다.
 
                    overlay_size=(mean_face_size, mean_face_size))
 
  
      
+
== 얼굴을 특정 이미지로 가리기 ==
 +
{| class="wikitable"
 +
!과정
 +
!코드 및 설명
 +
|-
 +
|함수 정의
 +
|코드를 파편화 하기 위해 함수를 정의하여 사용한다.<syntaxhighlight lang="python">
 +
def blind_face(img, address='test_image.png'):
 +
     '''1. 이미지를 받아 얼굴의 중심점을 찾는다. 2. 그 지점에 이미지를 불러온다.'''
 +
    faces = detector(img)  # 디텍터에 이미지를 넣어주어 얼굴을 찾는다.
 +
    blind_image = img.copy()
 +
    for face in faces:
 +
        try:
 +
            dlib_shape = predictor(img, face)  # 특징점을 리턴받는다.
 +
            shape_2d = np.array([[p.x, p.y] for p in dlib_shape.parts()])  # 연산을 위해 배열로 저장.
 +
            center_x, center_y = np.mean(shape_2d, axis=0).astype(np.int)  # 중심점을 찾는다.
 +
            overlay = cv2.imread(address, cv2.IMREAD_UNCHANGED)  # 이미지를 불러온다. 알파채널까지 읽기 위한 옵션.
 +
            # 얼굴 경계 찾기.
 +
            min_coords = np.min(shape_2d, axis=0)  # 각 열에 대해 가장 작은 값들.
 +
            max_coords = np.max(shape_2d, axis=0)
 +
            face_size = max(max_coords - min_coords)
 +
            # 덮을 이미지가 얼굴 인식에 따라 급격하게 변하기 때문에, 이를 중화하기 위한 코드.
 +
            face_sizes.append(face_size)
 +
            if len(face_sizes) > 10:
 +
                del face_sizes[0]
 +
            mean_face_size = int(np.mean(face_sizes) * 2.0)  # 얼굴을 적절히 덮기 위한 숫자보정.
 +
            # 다음 사용하는 함수는 아랫쪽에 정의되어 있다.
 +
            blind_image = overlay_transparent(x=center_x, y=center_y - 25,  # 얼굴의 중심을 찾고 숫자로 보정해준다.
 +
                                        background_img=blind_image,  # 기존 이미지.
 +
                                        img_to_overlay_t=overlay,  # 덮을 이미지.
 +
                                        overlay_size=(mean_face_size, mean_face_size))
 +
        except:  # 이상하게 얼굴 2개를 인식하게 되는 순간 에러가 난다....왤까...
 +
            pass  # 근데, 에러가 나도 1,2 프레임 뿐인지, 그냥 pass처리하면 잘 나온다;;
 +
        '''이유를 찾았다.
 +
        OpenCV(4.5.3) C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-czu11tvl\opencv\modules\core\src\arithm.cpp:230: error: (-215:Assertion failed) (mtype == CV_8U || mtype == CV_8S) && _mask.sameSize(*psrc1) in function 'cv::binary_op'
 +
        위 에러는 덮어씌우는 이미지가 해당 창 밖으로 나갈 때 발생하는 에러이다.
 +
        '''
 +
    cv2.imshow('window', blind_image)  # 창에 해당하는 이미지를 띄운다.
 +
    cv2.waitKey(1)  # 이게 있어야 창이 제대로 열린다.
 +
</syntaxhighlight>
 +
|-
 +
|이미지로 덮기
 +
|위에서 사용하는, 이미지로 덮는 함수는 다음과 같다.<syntaxhighlight lang="python">
 
def overlay_transparent(background_img, img_to_overlay_t, x, y, overlay_size=None):
 
def overlay_transparent(background_img, img_to_overlay_t, x, y, overlay_size=None):
 
   bg_img = background_img.copy()
 
   bg_img = background_img.copy()
131번째 줄: 157번째 줄:
 
   return bg_img
 
   return bg_img
 
</syntaxhighlight>
 
</syntaxhighlight>
[[분류:딥러닝 트래킹]]
+
|-
 +
|실행
 +
|맨 위의 과정에서 face_size들을 담는 리스트가 추가된다.<syntaxhighlight lang="python">
 +
while True:  # 기본적으로 계속 진행
 +
    ret, img = cap.read()  # 캡처한 영상을 프레임 단위로 읽는다.
 +
    if not ret:  # 잘 찍히면 ret은 True를 반환한다.
 +
        break  # 프레임이 없다면 종료.
 +
    face_sizes = []  # 얼굴 크기를 자연스럽게 변형하기 위한 리스트.
 +
    blind_face(img)
 +
</syntaxhighlight>
 +
|}
 +
[[분류:딥러닝 트레킹]]

2021년 9월 30일 (목) 16:34 기준 최신판

1 개요[편집 | 원본 편집]

주 방법은 링크, 링크(얼굴인식 스노우 카메라 따라만들기)를 참고하였습니다.

단순히 찾는 것 뿐이라면 cv2만으로도 가능하지만, 매끄럽게 처리하려면 dlib이 있어야 좋다.

2 방법[편집 | 원본 편집]

2.1 준비[편집 | 원본 편집]

2.1.1 공통과정[편집 | 원본 편집]

아래에 이어질 모든 과정 이전에 사용될 준비과정을 여기에 담는다.

과정 코드 및 설명
model 디렉터리에 모델 준비하기 이후 이 디렉터리 안의 모델을 사용한다.
사용할 모듈 설치 및 불러오기 pip install cmake dlib opencv-python numpy
  • 윈도우에선 visual studio 설치가 선행되어야 한다.(설치 옵션에서 C++ 모듈을 포함하게 하면 관련 컴파일러 등이 함께 설치된다.)
  • cmake는 dlib를 설치하기 위해 필요하다.
import dlib  # 얼굴인식
import cv2  # 이미지처리
import numpy as np  # 연산
과정 코드 및 설명
모델객체 생성 이미 학습된 bat파일을 불러오는데, 이는 링크에서 다운받을 수 있다.
detector = dlib.get_frontal_face_detector()  # 얼굴탐지모델
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')  # 얼굴 랜드마크 탐지 모델. 학습된 모델을 가져온다.
cap = cv2.VideoCapture(0)  # 영상 캡쳐. 경로 대신 0을 넣으면 웹캠이 켜진다.

2.2 얼굴 찾기[편집 | 원본 편집]

얼굴을 찾아 네모칸으로 표시한다.(필요에 따라 변형하여 사용하면 될듯.)

과정 코드 및 설명
함수 정의 코드를 파편화 하기 위해 함수를 정의하여 사용한다.
def find_face(img):
    '''이미지를 받아 해당 얼굴을 찾는다.'''
    faces = detector(img)  # 디텍터에 이미지를 넣어주어 얼굴을 찾는다.
    for face in faces:
        # 인식이 잘 되었는지 확인. 네모 그리기. 기존 이미지에 덧씌워 보여준다.
        img = cv2.rectangle(img, pt1=(face.left(), face.top()), pt2=(face.right(), face.bottom()),
                            color=(255, 255, 255),  # 색 지정이 가능하다.
                            thickness=2,            # 두께지정
                            lineType=cv2.LINE_AA    # 선의 타입 지정
                            )
    cv2.imshow('window', img)  # 창에 해당하는 이미지를 띄운다.
    cv2.waitKey(1)  # 이게 있어야 창이 제대로 열린다.
실행 다음과 같이 실행한다.
while True:  # 기본적으로 계속 진행
    ret, img = cap.read()  # 캡처한 영상을 프레임 단위로 읽는다.
    if not ret:  # 잘 찍히면 ret은 True를 반환한다.
        break  # 프레임이 없다면 종료.
    find_face(img)

2.3 얼굴 특징점 찾기[편집 | 원본 편집]

위에서 함수만 바꾸어주면 얼굴의 특징점을 찾아준다.

def find_shape(img):
    '''이미지를 받아 얼굴의 특징점을 찾는다.'''
    faces = detector(img)  # 디텍터에 이미지를 넣어주어 얼굴을 찾는다.
    for face in faces:
        dlib_shape = predictor(img, face)  # 특징점을 리턴받는다.
        shape_2d = np.array([[p.x, p.y] for p in dlib_shape.parts()])  # 연산을 위해 배열로 저장.
        for s in shape_2d:  # 해당 좌표에 원 그리기. 68개의 특징점을 찾는다.
            cv2.circle(img, center=tuple(s), radius=1, color=(255, 255, 255), thickness=2, lineType=cv2.LINE_AA)

    cv2.imshow('window', img)  # 창에 해당하는 이미지를 띄운다.
    cv2.waitKey(1)  # 이게 있어야 창이 제대로 열린다.

앞으로의 목표는 많은 얼굴에 대해서도 찾는 것...

2.4 얼굴을 특정 이미지로 가리기[편집 | 원본 편집]

과정 코드 및 설명
함수 정의 코드를 파편화 하기 위해 함수를 정의하여 사용한다.
def blind_face(img, address='test_image.png'):
    '''1. 이미지를 받아 얼굴의 중심점을 찾는다. 2. 그 지점에 이미지를 불러온다.'''
    faces = detector(img)  # 디텍터에 이미지를 넣어주어 얼굴을 찾는다.
    blind_image = img.copy()
    for face in faces:
        try:
            dlib_shape = predictor(img, face)  # 특징점을 리턴받는다.
            shape_2d = np.array([[p.x, p.y] for p in dlib_shape.parts()])  # 연산을 위해 배열로 저장.
            center_x, center_y = np.mean(shape_2d, axis=0).astype(np.int)  # 중심점을 찾는다.
            overlay = cv2.imread(address, cv2.IMREAD_UNCHANGED)  # 이미지를 불러온다. 알파채널까지 읽기 위한 옵션.
            # 얼굴 경계 찾기.
            min_coords = np.min(shape_2d, axis=0)  # 각 열에 대해 가장 작은 값들.
            max_coords = np.max(shape_2d, axis=0)
            face_size = max(max_coords - min_coords)
            # 덮을 이미지가 얼굴 인식에 따라 급격하게 변하기 때문에, 이를 중화하기 위한 코드.
            face_sizes.append(face_size)
            if len(face_sizes) > 10:
                del face_sizes[0]
            mean_face_size = int(np.mean(face_sizes) * 2.0)  # 얼굴을 적절히 덮기 위한 숫자보정.
            # 다음 사용하는 함수는 아랫쪽에 정의되어 있다.
            blind_image = overlay_transparent(x=center_x, y=center_y - 25,  # 얼굴의 중심을 찾고 숫자로 보정해준다.
                                        background_img=blind_image,  # 기존 이미지.
                                        img_to_overlay_t=overlay,  # 덮을 이미지.
                                        overlay_size=(mean_face_size, mean_face_size))
        except:  # 이상하게 얼굴 2개를 인식하게 되는 순간 에러가 난다....왤까...
            pass  # 근데, 에러가 나도 1,2 프레임 뿐인지, 그냥 pass처리하면 잘 나온다;;
        '''이유를 찾았다.
        OpenCV(4.5.3) C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-czu11tvl\opencv\modules\core\src\arithm.cpp:230: error: (-215:Assertion failed) (mtype == CV_8U || mtype == CV_8S) && _mask.sameSize(*psrc1) in function 'cv::binary_op'
        위 에러는 덮어씌우는 이미지가 해당 창 밖으로 나갈 때 발생하는 에러이다.
        '''
    cv2.imshow('window', blind_image)  # 창에 해당하는 이미지를 띄운다.
    cv2.waitKey(1)  # 이게 있어야 창이 제대로 열린다.
이미지로 덮기 위에서 사용하는, 이미지로 덮는 함수는 다음과 같다.
def overlay_transparent(background_img, img_to_overlay_t, x, y, overlay_size=None):
  bg_img = background_img.copy()
  # convert 3 channels to 4 channels
  if bg_img.shape[2] == 3:
    bg_img = cv2.cvtColor(bg_img, cv2.COLOR_BGR2BGRA)

  if overlay_size is not None:
    img_to_overlay_t = cv2.resize(img_to_overlay_t.copy(), overlay_size)

  b, g, r, a = cv2.split(img_to_overlay_t)

  mask = cv2.medianBlur(a, 5)

  h, w, _ = img_to_overlay_t.shape
  roi = bg_img[int(y-h/2):int(y+h/2), int(x-w/2):int(x+w/2)]

  img1_bg = cv2.bitwise_and(roi.copy(), roi.copy(), mask=cv2.bitwise_not(mask))
  img2_fg = cv2.bitwise_and(img_to_overlay_t, img_to_overlay_t, mask=mask)

  bg_img[int(y-h/2):int(y+h/2), int(x-w/2):int(x+w/2)] = cv2.add(img1_bg, img2_fg)

  # convert 4 channels to 4 channels
  bg_img = cv2.cvtColor(bg_img, cv2.COLOR_BGRA2BGR)

  return bg_img
실행 맨 위의 과정에서 face_size들을 담는 리스트가 추가된다.
while True:  # 기본적으로 계속 진행
    ret, img = cap.read()  # 캡처한 영상을 프레임 단위로 읽는다.
    if not ret:  # 잘 찍히면 ret은 True를 반환한다.
        break  # 프레임이 없다면 종료.
    face_sizes = []  # 얼굴 크기를 자연스럽게 변형하기 위한 리스트.
    blind_face(img)