Dlib을 이용하여 얼굴 포인트와 얼굴 특징을 추출하는 얼굴 기술자를 배우다. (광주, 인공지능, 과학기술정보통신부, 광주광역시)
1. Facial Points
face_detector = dlib.get_frontal_face_detector()
# 68개의 얼굴 포인트를 감지함
points_detector = dlib.shape_predictor('/content/drive/MyDrive/Colab Notebooks/Udemy/Weights/shape_predictor_68_face_landmarks.dat')
얼굴 감지기와 얼굴 포인트 감지기를 정의한다. 얼굴 포인트 감지기를 정의할 때 경로를 보면 68이라는 숫자가 있는데, 68개의 얼굴 포인트를 감지한다는 의미이다. 얼굴 이미지에 사전에 정해둔 얼굴 포인트에 점을 찍는다. 눈, 눈썹, 코, 입 등을 나타내는 모든 포인트를 찾는다. 포인트 개수가 많을수록 당연히 처리속도가 느려진다.
# 1은 이미지 스케일
face_detection = face_detector(image, 1)
for face in face_detection:
points = points_detector(image, face)
print(points.parts())
print(len(points.parts()))
# 포인트 값은 x축과 y축 값을 의미한다.
for point in points.parts():
cv2.circle(image, (point.x, point.y), 2, (0, 255, 0), 1)
l, t, r, b = face.left(), face.top(), face.right(), face.bottom()
cv2.rectangle(image, (l, t), (r, b), (0, 255, 255), 2)
cv2_imshow(image)
# Dlib은 OpenCV를 활용한 얼굴감지에서 하르캐스케이드 분류기보다 뛰어난 성능을 보인다. Dlib가 얼굴을 감지할 때 눈, 눈썹, 코, 입 등을 나나태는 모든 포인트를 찾아낸다.
# 포인트 개수가 많을수록 처리 속도가 느리다.
먼저 얼굴 감지기로 해당 이미지(그림 1)에 존재하는 모든 얼굴을 감지한다. 감지한 얼굴에 포인트 감지기를 사용해서 포인트를 찍는다. points.parts( )는 각 포인트의 좌표를 나타낸다. 68개의 포인트를 찍어주는 것을 사용했기 때문에 len(points)는 당연하게 68이 나와야 한다. 포인트의 좌표값을 토대로 이미지의 얼굴에 포인트를 찍어보기위해서 cv2.circle을 사용한다.
얼굴을 감지한 것을 사각형으로 감싸고 얼굴 포인트를 초록색 점을 찍어 표시한다. 얼굴 포인트는 모두 68개로 동일하고 같은 기준을 가지고 얼굴포인트가 찍어진 것이다. Dlib는 OpenCV를 활용한 얼굴감지에서 하르캐스케이드 분류기보다 뛰어난 성능을 보인다. 그래서 예전에 OpenCV를 활용해서 그림 1이미지의 얼굴을 감지할 때 일부 얼굴은 감지하지 못했었는데, Dlib는 모든 얼굴을 감지하는 좋은 성능을 보인다.
2. Facial Descriptors
face_detector = dlib.get_frontal_face_detector()
points_detector = dlib.shape_predictor('/content/drive/MyDrive/Colab Notebooks/Udemy/Weights/shape_predictor_68_face_landmarks.dat')
face_descriptor_extractor = dlib.face_recognition_model_v1('/content/drive/MyDrive/Colab Notebooks/Udemy/Weights/dlib_face_recognition_resnet_model_v1.dat')
# resnet은 합성곱 신경망 아키텍처를 의미함
# Dlib라이브러리는 합성곱 신경망을 활용해서 얼굴 인식을 수행한다. 합성곱 신경망이 정확히 무엇인지 이해하지 못해도 상관없다.
# 다음에 설명
face_descriptor_extractor을 정의할 때 resnet모델은 합성곱 신경망 CNN을 의미한다. Dlib 라이브러리는 합성곱 신경망을 활용해서 얼굴 인식을 수행한다. 얼굴 기술자는 얼굴 이미지를 분석하고, 얼굴 특징을 수치화하는 데 사용되는 중요한 도구이다. 얼굴 이미지의 다양한 특징을 추출한다.
index = {}
idx = 0
face_descriptors = None
paths = [os.path.join('/content/yalefaces/train', f) for f in os.listdir("/content/yalefaces/train")]
for path in paths:
# print(path) 각 이미지 경로
image = Image.open(path).convert("RGB") # RGB 이미지를 넣을 수 있음
image_np = np.array(image, 'uint8')
face_detection = face_detector(image_np, 1)
# 얼굴 감지
for face in face_detection:
l, t, r, b = face.left(), face.top(), face.right(), face.bottom()
cv2.rectangle(image_np, (l, t), (r, b), (0, 0, 255), 2)
# 얼굴의 포인트
points = points_detector(image_np, face)
for point in points.parts():
cv2.circle(image_np, (point.x, point.y), 2, (0, 255, 0), 1)
# 얼굴 기술자
# 각 얼굴에 대한 정보
# 얼굴 기술자에게 68개의 포인트를 입력하면 128개의 값을 돌려준다. len 해서 알아낸 정보
# print(len(face_descriptor))
# 얼굴마다 가장 특징적인 부분을 추출한다.
# 전처리 과정
face_descriptor = face_descriptor_extractor.compute_face_descriptor(image_np, points) # 합성곱 신경망 이용
face_descriptor = [f for f in face_descriptor]
# print(face_descriptor) # 쉼표로 분리되어있음
face_descriptor = np.asarray(face_descriptor, dtype=np.float64)
# print(face_descriptor) # 쉼표로 분리되어 있지 않음
# print(face_descriptor.shpae) # (128,)
# 새로운 차원을 추가해야함
face_descriptor = face_descriptor[np.newaxis, :]
print(face_descriptor.shape) # (1, 128) 1 x 128 행렬이 되었음
if face_descriptors is None:
face_descriptors = face_descriptor
else:
# 각 얼굴의 기술자를 하나의 변수로 연결해야함
face_descriptors = np.concatenate((face_descriptors, face_descriptor), axis = 0)
index[idx] = path # 각 이미지의 이름을 저장
idx += 1
cv2_imshow(image_np)
얼굴마다 특징적인 부분을 추출하는 전처리 과정이 필요하다. 합성곱 신경망을 이용해서 넘파이 배열화된 이미지를 각 이미지의 특징의 좌표를 나타내는 points를 사용해서 얼굴의 특징을 추출한다. 각 얼굴 기술자의 shape을 확인하면서 차원이 없을 경우 차원을 추가해줘야 한다. 모든 얼굴 기술자를 하나의 변수로 연결해서 사용해야하기 때문에 concatenate 함수를 사용해서 가로로 이어 붙인다. axis = 0은 행방향으로 작동하기 때문에 우리가 원하는 방식으로 붙게된다.
각 얼굴의 특징이 담긴 0번째 이미지의 얼굴 기술자 결과이다. 이 특징들로 해당 이미지가 어떤 이미지인지 예측할 수 있다. 우리가 가지고 있는 이미지의 경로(이름)을 저장한 index 변수를 보면 다음과 같다.
각 subject의 거리를 계산한 결과를 거리값이라고 정의하겠다. 거리값이란 실제로 위치 개념의 거리가 아니라 얼굴과 얼굴이 얼마나 유사한지를 나타내는 거리값이다. 두 얼굴의 거리값을 구하기 위해서 선형 대수를 사용해야 한다.
# subject01 인지 subject04 인지 어떤 이미지인지 예측하려면 얼굴 사이의 거리를 계산해야한다
np.linalg.norm(face_descriptors[131] - face_descriptors[131]) # linalg : 선형대수, 결과 = 거리값, 거리값이 낮을수록 얼굴 사이의 유사도가 높다는 뜻
131번째 얼굴 이미지와 131번째 얼굴이미지를 비교하기 위해서 두 얼굴 디스크립터 벡터 사이의 거리를 계산하고, 이 거리가 작을수록 얼굴 사이의 유사도가 높다. 두 이미지는 그냥 같은 이미지니까 당연히 거리값이 0이 나온다. 이 방법으로 이미지끼리 얼마나 유사한지 거리값을 통해 확인하고 비슷한 이미지를 찾아내야 한다.
'딥러닝 > Computer vision' 카테고리의 다른 글
[Computer Vision] Face Recognition (얼굴 인식) LBPH 분류기 학습 / 인공지능사관학교 4기 (0) | 2023.10.31 |
---|---|
[Computer Vision] Face Recognition (얼굴 인식) 개념 및 이미지 전처리 / 인공지능사관학교 4기 (0) | 2023.10.23 |
[Computer Vision] Detecting faces with HOG / 인공지능사관학교 4기 (0) | 2023.10.16 |
[Computer Vision] Face Detection (얼굴 감지) / 인공지능사관학교 4기 (1) | 2023.10.10 |