face dection-Retina face, Dlib
2024. 2. 24. 21:47ㆍ파이썬
0. RetinaFace, Dlib
1.알고리즘 및 기술
RetinaFace:
- RetinaFace는 신경망 기반의 딥러닝 얼굴 검출 알고리즘입니다. 이 알고리즘은 얼굴의 다양한 측면에서 정확한 검출을 수행할 수 있도록 설계되었습니다. RetinaFace는 다양한 크기와 해상도의 얼굴을 효과적으로 처리할 수 있으며, 다양한 각도 및 비율에 대응할 수 있는 특징을 가지고 있습니다.
dlib:
- dlib은 기존의 컴퓨터 비전 및 머신 러닝 기술을 사용한 라이브러리로, HOG (Histogram of Oriented Gradients)와 SVM (Support Vector Machines) 등을 기반으로 하는 얼굴 검출 알고리즘을 제공합니다. dlib은 다양한 이미지 처리 작업에 사용될 수 있지만, 최근 딥러닝 기술이 주목받으면서 얼굴 검출에서는 더 성능이 뛰어난 딥러닝 기반의 방법들이 등장하였습니다.
2. 성능 및 정확도
RetinaFace:
- 딥러닝을 기반으로 하고 있어서 대량의 데이터에서 학습하며, 얼굴 검출 정확도에서 일반적으로 뛰어난 성능을 보입니다.
dlib:
- 전통적인 방식을 기반으로 하고 있어서 얼굴 검출에 있어서는 딥러닝 방법들과 비교했을 때 상대적으로 성능이 낮을 수 있습니다.
2. 사용 용도
RetinaFace:
- 딥러닝 기반의 고성능 얼굴 검출을 필요로 하는 다양한 응용 분야에서 사용됩니다.
dlib:
- 경량화된 얼굴 검출이 필요한 경우나, 단순한 얼굴 검출이외에도 얼굴 랜드마크 검출 및 얼굴 인식과 같은 다양한 작업에서 사용됩니다.
1. 사전 준비(vscode)
pip install virtualenv #vscode에서 가상환경 설정을 위한 virtualenv 설치
virtualenv q --python=python3.8.8 #가상환경 이름 q 파이썬 버전3.8
#Scripts 폴더 들어가서 activate (가상환경 활성화)
pip install torch==1.7.1+cu110 torchvision==0.8.2+cu110 -f https://download.pytorch.org/whl/torch_stable.html #pytorch
pip install opencv-python
pip install matplotlib
pip install python-time
pip install dlib
2. 데이터 학습(구글 코랩)
위 링크에서 데이터 셋 사용
from google.colab import drive #내 드라이브에 마운트
drive.mount('/content/drive')
!git clone https://github.com/biubug6/Pytorch_Retinaface.git
%cd /content/drive/MyDrive/facedection/Pytorch_Retinaface #경로 변경
!CUDA_VISIBLE_DEVICES=0 python train.py --network mobile0.25 --training_dataset /content/drive/MyDrive/facedection/data/widerface/train/label.txt
#학습 시작
실행 시 위 사진과 같이 나오면서 학습이 된다.
- Epoch: 1/250: 현재 훈련 중인 epoch 수 및 총 epoch 수입니다. 이것은 전체 데이터셋을 한 번 훈련하는 것을 의미 (너무 높게 잡게 되면 과적합(overfitting)이 발생하거나 자원소모가 커져서 적당한 값을 잡는게 좋음)
- Epochiter: 176/403: 현재 epoch에서의 iteration 수 및 총 iteration 수입니다. Iteration은 모델이 데이터셋의 일부를 사용해 가중치를 업데이트하는 훈련 단계
- Iter: 176/100750: 전체 훈련 과정에서의 iteration 수 및 총 iteration 수입니다. 이는 모든 epoch에 대한 총 iteration 수
- Loc: 2.2532 Cla: 2.8038 Landm: 8.7638: 현재 iteration에서의 손실(loss). Loc은 위치(바운딩 박스 예측), Cla는 클래스 분류, Landm은 랜드마크(landmark) 예측 손실 (Loc, Cla, Landm 모두 낮을수록 좋음)
- LR: 0.00100000: 현재 학습률(learning rate). 학습률은 모델의 가중치를 업데이트하는 정도
- Batchtime: 0.2994 s: 현재 iteration에 걸린 시간. 즉, 한 iteration을 완료하는 데 걸린 시간
- ETA: 8:21:51: 훈련이 완료될 예상 소요 시간(estimated time of arrival)
3. 코딩(RetinaFace)
cd c:\RetinaFace root 경로
# 필요한 라이브러리 및 모듈 불러오기
import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
import time
import torch
from models.retinaface import RetinaFace
from data import cfg_mnet, cfg_re50
from layers.functions.prior_box import PriorBox
from utils.nms.py_cpu_nms import py_cpu_nms
from utils.box_utils import decode, decode_landm
# 모델의 가중치 파일 경로 설정
weight_path = "C:weight 파일 위치 및 이름"
# 사용할 모델의 설정 선택 (mobile0.25 또는 resnet50)
cfg = cfg_mnet # mobile0.25 (cfg_mnet) or resnet50 (cfg_re50)
# 이미지 리사이즈 비율 설정
resize = 1
# 얼굴을 감지할 때 사용할 최소 신뢰도 임계값 설정(높게 할수록 신뢰도는 높아지지만 놓치는 경우 발생)
confidence_threshold = 0.02
# 최대로 추출할 상위 K개의 박스 수
top_k = 5000
# 비최대 억제(NMS)를 위한 임계값 설정(높이면 정확도는 올라가지만 작은 것들 검출가능성 낮아짐)
nms_threshold = 0.4 #(박스들이 겹치는 부분이 40%이상일때 중복으로 간주하고 하나 제거)
# 최종 결과로 남길 최상위 K개의 박스 수
keep_top_k = 750
# 시각화 임계값 설정
vis_thres = 0.6
# 모델을 실행할 장치 설정 (CPU 또는 CUDA)
device = "cpu" # cpu or cuda
# RetinaFace 모델 불러오기
model = RetinaFace(cfg, phase='test').to(device)
model.load_state_dict(torch.load(weight_path, map_location=device))
model.eval()
print("Model Loaded!")
# RetinaFace 함수 정의
def retinaface_inf(test_img, model):
img = np.float32(test_img)
im_height, im_width, _ = img.shape
# 이미지 스케일 설정 및 RGB 평균값 빼기
scale = torch.Tensor([img.shape[1], img.shape[0], img.shape[1], img.shape[0]])
img -= (104, 117, 123)
img = img.transpose(2, 0, 1)
img = torch.from_numpy(img).unsqueeze(0)
img = img.to(device)
scale = scale.to(device)
# 모델 실행 시간 측정 시작
tic = time.time()
loc, conf, landms = model(img) # forward pass
# Prior Box 생성 및 변환
priorbox = PriorBox(cfg, image_size=(im_height, im_width))
priors = priorbox.forward()
priors = priors.to(device)
prior_data = priors.data
boxes = decode(loc.data.squeeze(0), prior_data, cfg['variance'])
boxes = boxes * scale / resize
boxes = boxes.cpu().numpy()
scores = conf.squeeze(0).data.cpu().numpy()[:, 1]
# 낮은 신뢰도의 박스 제거
inds = np.where(scores > confidence_threshold)[0]
boxes = boxes[inds]
scores = scores[inds]
# 상위 K개의 박스 유지
order = scores.argsort()[::-1][:top_k]
boxes = boxes[order]
scores = scores[order]
# 비최대 억제(NMS) 수행
dets = np.hstack((boxes, scores[:, np.newaxis])).astype(np.float32, copy=False)
keep = py_cpu_nms(dets, nms_threshold)
dets = dets[keep, :]
# 최상위 K개의 박스 유지 (빠른 NMS)
dets = dets[:keep_top_k, :]
# 프레임 속도(fps) 계산
fps_ = round(1 / (time.time() - tic), 2)
# 시각적으로 결과 표시
for b in dets:
if b[4] < vis_thres:
continue
b = list(map(int, b))
cv2.rectangle(test_img, (b[0], b[1]), (b[2], b[3]), (0, 0, 255), 4)
cv2.putText(test_img, "retinaface", (410, 70), cv2.FONT_HERSHEY_DUPLEX, 1.5, (255, 0, 0), thickness=3,
lineType=cv2.LINE_AA)
cv2.putText(test_img, "fps : " + str(fps_), (5, 70), cv2.FONT_HERSHEY_DUPLEX, 1.5, (0, 0, 255), thickness=3,
lineType=cv2.LINE_AA)
return test_img
# 테스트 이미지 불러오기
test_path = 'C:/Users/coghk/Desktop/vision/q/bts.jpg'
test_img = cv2.imread(test_path)
# RetinaFace 함수를 사용하여 이미지에 얼굴 감지 결과 적용
retina_img = retinaface_inf(test_img, model)
# 결과 이미지 시각화
plt.imshow(cv2.cvtColor(test_img, cv2.COLOR_BGR2RGB))
plt.show()
3. Dlib
# dlib의 얼굴 감지기 생성
face_detector = dlib.get_frontal_face_detector()
# dlib 얼굴 감지 함수 정의
def dlib_inf(test_img, face_detector):
img = np.float32(test_img)
im_height, im_width, _ = img.shape
# 현재 프레임에서 얼굴을 검출하고 수행 시간 측정 시작
tic = time.time()
face_detection = face_detector(test_img)
fps_ = round(1/(time.time() - tic), 2)
# 검출된 얼굴에 대한 정보를 사용하여 시각적으로 결과 표시
for f in face_detection:
cv2.rectangle(test_img, (f.left(), f.top()), (f.right(), f.bottom()), (0,0,255), 4)
# 결과 이미지에 "dlib"과 fps 정보를 텍스트로 표시
cv2.putText(test_img, "dlib", (480,70), cv2.FONT_HERSHEY_DUPLEX, 1.5, (255,0,0), thickness=3, lineType=cv2.LINE_AA)
cv2.putText(test_img, "fps : "+str(fps_), (5,70), cv2.FONT_HERSHEY_DUPLEX, 1.5, (0,0,255), thickness=3, lineType=cv2.LINE_AA)
return test_img
# 테스트 이미지 불러오기
test_path = 'C:/Users/coghk/Desktop/vision/q/bts.jpg'
test_img = cv2.imread(test_path)
# dlib_inf 함수를 사용하여 이미지에 얼굴 감지 결과 적용
dlib_img = dlib_inf(test_img, face_detector)
# 결과 이미지 시각화
plt.imshow(cv2.cvtColor(test_img, cv2.COLOR_BGR2RGB))
plt.show()
4. 결론
둘다 cpu환경에서 돌렸을때 RetinaFace가 Dlib보다 얼굴영역이 더 정확하게 나왔다.
그러나 속도 면에서는 Dlib가 빨랐다
GPU사용 환경에선 RetinaFace가 훨씬 빠르고 정확했다.
GPU사용이 가능하면 RetinaFace를 쓰는 것이 좋다.
5. 부록
1. NMS
비최대 억제(Non-Maximum Suppression, NMS)는 객체 검출에서 중복된 박스를 제거하는 기술입니다. 객체 검출 알고리즘은 이미지에서 여러 위치에서 여러 크기의 박스를 생성할 수 있습니다. 이러한 다양한 박스들 중에서 최적의 박스를 선택하고 중복을 제거하기 위해 NMS가 사용됩니다.
NMS의 주요 아이디어는 다음과 같습니다:
- 박스 신뢰도 정렬: 모든 박스를 해당하는 객체일 확률 또는 신뢰도에 따라 내림차순으로 정렬합니다.
- 가장 신뢰도가 높은 박스 선택: 가장 신뢰도가 높은 박스를 최종 결과로 선택하고 유지합니다.
- IoU(Intersection over Union) 기준으로 박스 제거: 선택한 박스와 나머지 박스 간의 IoU를 계산합니다. IoU가 특정 임계값을 넘는다면, 해당 박스는 중복으로 간주되어 제거됩니다.
- 반복: 나머지 박스에 대해서 위의 과정을 반복합니다.
이러한 과정을 통해 겹치는 박스 중에서 가장 신뢰도가 높은 박스만을 최종 결과로 선택하게 됩니다. NMS를 사용하면 최종 검출 결과가 간결하고 중복이 줄어들어 더 나은 검출 성능을 얻을 수 있습니다. NMS는 주로 객체 검출 분야에서 다양한 알고리즘에서 적용되는 중요한 기술 중 하나입니다.
'파이썬' 카테고리의 다른 글
건물 영역 검출 - 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 |
facelandmark - 황금 비율 측정(PFLD) (0) | 2024.02.25 |