facelandmark - 황금 비율 측정(PFLD)
2024. 2. 25. 17:17ㆍ파이썬
PFLD
- PFLD는 "Parallel Facial Landmark Detection"의 약어로, 얼굴의 랜드마크(landmark)를 탐지하는 모델입니다. 이 모델은 병렬로 동작하여 얼굴의 다양한 특징 포인트(랜드마크)를 감지하고 추정합니다. 주로 얼굴 인식, 표정 분석, 동작 인식 등의 응용 프로그램에서 사용됩니다.
- PFLD는 여러 가지 랜드마크를 예측하여 얼굴의 다양한 부분을 포착할 수 있습니다. 이를 통해 얼굴의 특징을 추출하고, 예를 들어 눈, 코, 입 등의 위치를 식별할 수 있습니다. 이러한 랜드마크는 보통 2D 이미지에서 얼굴의 구조를 설명하거나 3D 얼굴 모델링에 활용됩니다.
- PFLD와 같은 얼굴 랜드마크 감지 모델은 주로 컴퓨터 비전 및 인공지능 분야에서 얼굴 관련 작업에 사용되며, 얼굴 기반 응용프로그램에서 인간의 얼굴 특징을 이해하고 활용하는 데 도움을 줍니다.
0. 데이터 준비 및 전처리(구글 코랩)
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/MyDrive/facelandmark
!git clone https://github.com/polarisZhao/PFLD-pytorch
%cd /content/drive/MyDrive/facelandmark/PFLD-pytorch/data/WFLW
GitHub - polarisZhao/PFLD-pytorch: PFLD pytorch 구현
위 링크에서 데이터셋(WFLW) 다운로드 후 위 경로에 폴더 생성
!tar -zxvf WFLW_images.tar.gz #압축 해제
!tar -zxvf WFLW_annotations.tar.gz #압축 해제
%cd /content/drive/MyDrive/facelandmark/PFLD-pytorch/data
!python SetPreparation.py #데이터 전처리
1. 학습(구글 코랩)
!python train.py --dataroot data/train_data/list.txt --train_batchsize 320 --val_batchsize 320
2. 하이퍼 파라미터 설정(vscode 가상환경)
가상환경 설정
2024.02.24 - [파이썬] - face dection-Retina face, Dlib
cd C:PFLD-pytorch #PFLD-pytorch 경로
import numpy as np
import cv2
import torch
import torchvision
import matplotlib.pyplot as plt
from mtcnn.detector import detect_faces
from collections import OrderedDict
from models.pfld import PFLDInference, AuxiliaryNet
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model_path = 'tar 경로'
#PFLD Inference 함수 (모델 불러오기 포함)
def landmark_detection(img, det, model_path):
# 모델을 불러옵니다.
checkpoint = torch.load(model_path, map_location=device)
pfld_backbone = PFLDInference().to(device)
pfld_backbone.load_state_dict(checkpoint['pfld_backbone'])
pfld_backbone.eval()
pfld_backbone = pfld_backbone.to(device)
# 이미지를 변환합니다.
transform = torchvision.transforms.Compose(
[torchvision.transforms.ToTensor()])
# 얼굴을 둘러싸는 bounding box 좌표를 가져옵니다.
height, width = img.shape[:2]
x1, y1, x2, y2 = (det[:4] + 0.5).astype(np.int32)
# bounding box를 조정합니다.(얼굴보다 여유가 있는 정사각형)
w = x2 - x1 + 1
h = y2 - y1 + 1
cx = x1 + w // 2
cy = y1 + h // 2
size = int(max([w, h]) * 1.1)
x1 = cx - size // 2
x2 = x1 + size
y1 = cy - size // 2
y2 = y1 + size
# 이미지 경계를 벗어나지 않도록 보정합니다.
x1 = max(0, x1)
y1 = max(0, y1)
x2 = min(width, x2)
y2 = min(height, y2)
edx1 = max(0, -x1)
edy1 = max(0, -y1)
edx2 = max(0, x2 - width)
edy2 = max(0, y2 - height)
cropped = img[y1:y2, x1:x2] #행과 열로 바꿔야 하는데 OPENCV에선 HEIGHT가 행, WIDTH가 열이므로 서로 바꿔서 대입
# 이미지가 bounding box를 벗어날 경우 경계를 0으로 채웁니다.
if (edx1 > 0 or edy1 > 0 or edx2 > 0 or edy2 > 0):
cropped = cv2.copyMakeBorder(cropped, edy1, edy2, edx1, edx2,
cv2.BORDER_CONSTANT, 0)
# 이미지를 모델에 적합한 크기로 조정하고 변환합니다.
input = cv2.resize(cropped, (112, 112))
input = transform(input).unsqueeze(0).to(device)
# 얼굴 랜드마크를 예측합니다.
_, landmarks = pfld_backbone(input)
pre_landmark = landmarks[0]
pre_landmark = pre_landmark.cpu().detach().numpy().reshape(
-1, 2) * [size, size] - [edx1, edy1]
result = []
# 예측된 랜드마크를 원래 이미지 좌표로 변환합니다.
for p in pre_landmark:
x = p[0] + x1
y = p[1] + y1
result.append([int(x), int(y)])
return result
#황금 비율 계산 함수
def calc_gr(pts, bounding_boxes, n=4):
# 비율 계산 결과를 저장할 리스트
result = []
# 랜드마크 지점을 사용하여 비율 계산
A = pts[64][1] - pts[76][1]
B = pts[76][1] - pts[16][1]
result.append(round(A / B, n))
A = bounding_boxes[1] - pts[59][1]
B = pts[59][1] - pts[16][1]
result.append(round(A / B, n))
A = pts[64][0] - pts[0][0]
B = pts[68][0] - pts[64][0]
result.append(round(A / B, n))
A = pts[32][0] - pts[68][0]
B = pts[68][0] - pts[64][0]
result.append(round(A / B, n))
# 계산된 비율의 평균을 계산
average_ratio = sum(result) / len(result)
# 결과 반환
return result, average_ratio
#테스트 이미지
test_img_path = 'C:test.jpg 경로'
# 테스트 이미지 로드 및 얼굴 감지
test_img = cv2.imread(test_img_path)
test_img_gray = cv2.cvtColor(test_img, cv2.COLOR_BGR2RGB)
bounding_boxes, _ = detect_faces(test_img_gray) # bounding boxes: [x1, y1, x2, y2, confidence]
# 얼굴 랜드마크 감지
landmark = landmark_detection(test_img, bounding_boxes[0][:4], model_path)
# 랜드마크 시각적으로 표시
for p in landmark:
cv2.circle(test_img, (p[0], p[1]), 2, (255, 0, 0), -1)
# 황금 비율 계산 및 시각적으로 나타내기
result_list, result = calc_gr(landmark, bounding_boxes[0][:4])
cv2.putText(test_img, "golden ratio : " + str(round(result, 3)), (10, 20), cv2.FONT_HERSHEY_DUPLEX, 0.5, (255, 0, 0),
thickness=1, lineType=cv2.LINE_AA)
# 결과 이미지 저장
cv2.imwrite("../result.png", test_img)
# 결과 출력
print(f"황금 비율 결과 리스트: {result_list}, 황금 비율 결과 평균값: {result:.3f}")
# 결과 이미지 시각화
plt.imshow(cv2.cvtColor(test_img, cv2.COLOR_BGR2RGB))
plt.show()
3. 결과
황금비율이 1.61인데 보정된 사진이라 그런지 모르겠지만 매우 근접하게 결과가 나왔다
'파이썬' 카테고리의 다른 글
건물 영역 검출 - DeepLabV3+ (0) | 2024.04.16 |
---|---|
complex-YOLO 3D object Detection on Point Clouds (0) | 2024.04.01 |
YOLOv8 도로 표지판, 신호등 검출 (0) | 2024.03.17 |
YOLO v8을 이용한 마스크 검출 (0) | 2024.03.17 |
face dection-Retina face, Dlib (0) | 2024.02.24 |