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> |
| + | |} |
| + | [[분류:딥러닝 트레킹]] |