4번째 줄: |
4번째 줄: |
| 단순히 찾는 것 뿐이라면 cv2만으로도 가능하지만, 매끄럽게 처리하려면 dlib이 있어야 좋다. | | 단순히 찾는 것 뿐이라면 cv2만으로도 가능하지만, 매끄럽게 처리하려면 dlib이 있어야 좋다. |
| | | |
− | == 방법 ==
| + | = 방법 = |
| | | |
− | === 준비 === | + | == 준비 == |
| + | |
| + | === 공통과정 === |
| + | 아래에 이어질 모든 과정 이전에 사용될 준비과정을 여기에 담는다. |
| {| class="wikitable" | | {| class="wikitable" |
| !과정 | | !과정 |
15번째 줄: |
18번째 줄: |
| |- | | |- |
| |사용할 모듈 설치 및 불러오기 | | |사용할 모듈 설치 및 불러오기 |
− | |pip install CMake dlib opencv-python numpy | + | |pip install cmake dlib opencv-python numpy |
| | | |
| * 윈도우에선 visual studio 설치가 선행되어야 한다.(설치 옵션에서 C++ 모듈을 포함하게 하면 관련 컴파일러 등이 함께 설치된다.) | | * 윈도우에선 visual studio 설치가 선행되어야 한다.(설치 옵션에서 C++ 모듈을 포함하게 하면 관련 컴파일러 등이 함께 설치된다.) |
− | | + | * cmake는 dlib를 설치하기 위해 필요하다. |
− | cmake는 dlib를 설치하기 위해 필요하다.<syntaxhighlight lang="python"> | + | <syntaxhighlight lang="python"> |
| import dlib # 얼굴인식 | | import dlib # 얼굴인식 |
| import cv2 # 이미지처리 | | import cv2 # 이미지처리 |
30번째 줄: |
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() # 얼굴탐지모델 |
− | predictor = 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을 넣으면 웹캠이 켜진다.
| + | !과정 |
− | | + | !코드 및 설명 |
− | def find_face(cap) | + | |- |
− | ret, img = cap.read() # 캡처한 영상을 프레임 단위로 읽는다.
| + | |함수 정의 |
− | if not ret: | + | |코드를 파편화 하기 위해 함수를 정의하여 사용한다.<syntaxhighlight lang="python"> |
− | break # 프레임이 없다면 종료.
| + | def find_face(img): |
| + | '''이미지를 받아 해당 얼굴을 찾는다.''' |
| faces = detector(img) # 디텍터에 이미지를 넣어주어 얼굴을 찾는다. | | faces = detector(img) # 디텍터에 이미지를 넣어주어 얼굴을 찾는다. |
− | face = faces[0] # 인식된 얼굴 중 첫번째. | + | try: |
− |
| + | face = faces[0] # 인식된 얼굴 중 첫번째. |
− | # 인식이 잘 되었는지 확인. 네모 그리기.
| + | # 인식이 잘 되었는지 확인. 네모 그리기. 기존 이미지에 덧씌워 보여준다. |
− | # 기본 이미지에 덧씌워 보여준다.
| + | img = cv2.rectangle(img, pt1=(face.left(), face.top()), pt2=(face.right(), face.bottom()), |
− | # 좌 상단과 우 하단을 잡아준다.
| + | color=(255, 255, 255), # 색 지정이 가능하다. |
− | img = cv2.rectangle(img, pt1=(face.left(), face.top()), pt2=(face.right(), face.bottom)
| + | thickness=2, # 두께지정 |
− | color=(255,255,255), # 색 지정이 가능하다.
| + | lineType=cv2.LINE_AA # 선의 타입 지정 |
− | thickness=2, # 두께지정
| + | ) |
− | lineType=cv2.LINE_AA # 선의 타입 지정
| + | except: # 얼굴이 없으면 faces[0]에서 인덱스 에러가 뜬다. 그럴 땐 그냥 패스! |
− | )
| + | pass |
− | | + | cv2.imshow('window', img) # 창에 해당하는 이미지를 띄운다. |
− |
| |
− |
| |
− | cv2.imshow('창이름', img) # 창에 해당하는 이미지를 띄운다. | |
| cv2.waitKey(1) # 1ms만큼 대기 해야 창이 제대로 열린다. | | cv2.waitKey(1) # 1ms만큼 대기 해야 창이 제대로 열린다. |
− |
| + | </syntaxhighlight> |
− |
| + | |- |
− |
| + | |실행 |
− |
| + | |다음과 같이 실행한다.<syntaxhighlight lang="python"> |
| while True: # 기본적으로 계속 진행 | | while True: # 기본적으로 계속 진행 |
− | find_face(cap=cap) | + | ret, img = cap.read() # 캡처한 영상을 프레임 단위로 읽는다. |
| + | if not ret: # 잘 찍히면 ret은 True를 반환한다. |
| + | break # 프레임이 없다면 종료. |
| + | find_face(img) |
| </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()]) # 연산을 위해 배열로 저장.
| + | try: |
− | for s in shape_2d: # 해당 좌표에 원 그리기. 68개의 특징점을 찾는다.
| + | face = faces[0] # 인식된 얼굴 중 첫번째. |
− | cv2.circle(img, center=tuple(s), radius=1, color=(255, 255, 255), thickness=2, lineType=cv2.LINE_AA)
| + | 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) |
| + | except: |
| + | pass |
| + | cv2.imshow('window', img) # 창에 해당하는 이미지를 띄운다. |
| + | cv2.waitKey(1) # 1ms만큼 대기 해야 창이 제대로 열린다. |
| + | </syntaxhighlight>앞으로의 목표는 많은 얼굴에 대해서도 찾는 것... |
| + | |
| + | == 얼굴을 특정 이미지로 가리기 == |
| + | {| class="wikitable" |
| + | !과정 |
| + | !코드 및 설명 |
| + | |- |
| + | |함수 정의 |
| + | |코드를 파편화 하기 위해 함수를 정의하여 사용한다.<syntaxhighlight lang="python"> |
| + | def blind_face(img, address='test_image.png'): |
| + | '''1. 이미지를 받아 얼굴의 중심점을 찾는다. 2. 그 지점에 이미지를 불러온다.''' |
| + | faces = detector(img) # 디텍터에 이미지를 넣어주어 얼굴을 찾는다. |
| + | try: |
| + | face = faces[0] # 인식된 얼굴 중 첫번째. |
| + | 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) # 얼굴을 적절히 덮기 위한 숫자보정. |
| + | origin_image = img.copy() |
| + | # 다음 사용하는 함수는 아랫쪽에 정의되어 있다. |
| + | result = overlay_transparent(x=center_x, y=center_y - 25, # 얼굴의 중심을 찾고 숫자로 보정해준다. |
| + | background_img=origin_image, # 기존 이미지. |
| + | img_to_overlay_t=overlay, # 덮을 이미지. |
| + | overlay_size=(mean_face_size, mean_face_size)) |
| + | cv2.imshow('window', result) # 창에 해당하는 이미지를 띄운다. |
| + | except: |
| + | cv2.imshow('window', img) # 얼굴 인식이 안되면 이미지를 그냥 띄우기 |
| + | pass |
| + | cv2.waitKey(1) # 1ms만큼 대기 해야 창이 제대로 열린다. |
| </syntaxhighlight> | | </syntaxhighlight> |
− | | + | |- |
− | === 얼굴을 특정 이미지로 가리기 ===
| + | |이미지로 덮기 |
− | <syntaxhighlight lang="python"> | + | |위에서 사용하는, 이미지로 덮는 함수는 다음과 같다.<syntaxhighlight lang="python"> |
− | def blind_face(img, address='파일경로.png')
| |
− | 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))
| |
− | | |
− |
| |
| 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() |
129번째 줄: |
158번째 줄: |
| 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> |
| + | |} |
| [[분류:딥러닝 트래킹]] | | [[분류:딥러닝 트래킹]] |