iBetter Books
수정

검출기를 일곱 가지나 만나 봤습니다. 이제 흩어진 인상을 하나의 표로 모을 차례입니다. "정확한 게 좋다"는 막연한 느낌 대신, 같은 사진으로 직접 시간을 재 보고 각 검출기가 어느 상황에 맞는지를 숫자와 함께 정리합니다. 이 장을 마치면 새 프로젝트에서 "무엇을 쓸지"를 근거를 가지고 고를 수 있게 됩니다.

무엇을 비교하는가

검출기를 고를 때 따지는 기준은 크게 셋입니다.

  • 정확도: 얼마나 잘 잡는가. 특히 옆얼굴·작은 얼굴·가려진 얼굴 같은 어려운 경우.
  • 속도: 한 장(또는 한 프레임)을 처리하는 데 걸리는 시간. 실시간 가능 여부를 가른다.
  • 자원: 메모리 사용량과 GPU 필요 여부. 라즈베리파이 같은 작은 기기에서 중요하다.

이 셋은 보통 맞바꿈 관계입니다. 정확도를 높이면 느려지고 자원을 더 먹습니다. "최고의 검출기"는 없고, "내 상황에 맞는 검출기"가 있을 뿐입니다.

속도를 직접 재는 코드

같은 이미지를 여러 번 검출해 평균 시간을 재는 간단한 벤치마크입니다. 검출기마다 호출 방식이 다르므로, 각 검출 함수를 같은 형태로 감싸 비교합니다. 다음 내용을 benchmark.py로 저장합니다.

# 파일: benchmark.py"""여러 검출기의 평균 처리 시간을 같은 이미지로 비교한다."""import osimport sysimport globimport timeimport cv2def frontalface_cascade():   # 02장에서 설명한 conda·pip 양쪽 호환 경로 찾기    name = "haarcascade_frontalface_default.xml"    if hasattr(cv2, "data"):        p = os.path.join(cv2.data.haarcascades, name)        if os.path.exists(p):            return p    return glob.glob(os.path.join(sys.prefix, "share", "opencv*", "haarcascades", name))[0]img = cv2.imread("sample.jpg")gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)def bench(name, fn, repeat=20):    fn()   # 첫 호출은 모델 로딩 등 워밍업이므로 측정에서 제외    start = time.perf_counter()    for _ in range(repeat):        fn()    avg_ms = (time.perf_counter() - start) / repeat * 1000    print(f"  {name:14s} 평균 {avg_ms:7.1f} ms")# 1) Haarhaar = cv2.CascadeClassifier(frontalface_cascade())bench("Haar", lambda: haar.detectMultiScale(gray, 1.1, 5))# 2) dlib HOGimport dlibhog = dlib.get_frontal_face_detector()rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)bench("dlib HOG", lambda: hog(rgb, 1))# 3) YuNet (모델 파일 필요)h, w = img.shape[:2]yunet = cv2.FaceDetectorYN.create(    "face_detection_yunet_2023mar.onnx", "", (w, h), 0.9, 0.3, 5000)yunet.setInputSize((w, h))bench("YuNet", lambda: yunet.detect(img))# 같은 방식으로 MediaPipe·MTCNN·RetinaFace·YOLO도 추가해 비교할 수 있다

bench 함수에서 첫 호출을 따로 떼어 워밍업으로 버리는 점이 중요합니다. 딥러닝 검출기는 첫 호출에서 모델을 메모리에 올리느라 유독 오래 걸리므로, 이를 측정에 넣으면 결과가 왜곡됩니다.

한눈에 보는 검출기 비교

직접 재 보면 기기마다 절대 시간은 다르지만, 검출기 사이의 상대적 경향은 대체로 일정합니다. CPU 환경(GPU 미사용) 기준의 일반적인 경향을 정리하면 다음과 같습니다.

검출기 정확도 속도(CPU) 옆·작은 얼굴 랜드마크 추가 설치
Haar 낮음 매우 빠름 약함 없음 불필요(내장)
dlib HOG 보통 빠름 약함 없음 dlib
OpenCV DNN(SSD) 보통 보통 보통 없음 모델 파일
YuNet 높음 빠름 보통~좋음 5점 불필요(내장)
MediaPipe 보통~높음 매우 빠름 보통 키포인트 mediapipe
MTCNN 높음 느림 좋음 5점 mtcnn
RetinaFace 매우 높음 매우 느림 매우 좋음 5점 retina-face
YOLO-face 높음 빠름(GPU 시 매우 빠름) 좋음 5점(가중치별) ultralytics

검출기별 결과 비교 패널

이 표에서 두 가지 경향이 보입니다. 첫째, 내장이면서 균형이 좋은 YuNet이 "무난한 첫 선택"으로 두드러집니다. 둘째, RetinaFace는 정확도 최강이지만 CPU에서는 실시간이 어렵습니다.

상황별 추천

상황 추천 검출기 이유
라즈베리파이, 정면 한 명 Haar / MediaPipe 가장 가볍고 빠름
일반 데스크톱, 균형 YuNet 내장, 정확도·속도 균형, 랜드마크
실시간 웹캠 다인원 MediaPipe / YOLO-face 빠른 다중 검출
정확도 최우선(등록·검색 앞단) RetinaFace / MTCNN 어려운 얼굴까지 검출
GPU 보유, 속도+정확도 YOLO-face GPU 가속으로 둘 다 확보

실무 팁. 벤치마크는 반드시 "내 실제 데이터"로 하세요. 위 경향은 일반적인 사진 기준이고, 여러분의 환경(조명, 카메라 해상도, 얼굴 크기, 마스크 착용 여부)에 따라 순위가 바뀔 수 있습니다. 후보를 두세 개로 좁힌 뒤, 실제 운영 환경과 비슷한 사진 수십 장으로 정확도와 시간을 직접 재 보는 것이 가장 확실합니다.

이 장에서 기억할 것

검출기는 정확도·속도·자원의 맞바꿈 위에 놓여 있어 "최고"가 아니라 "상황에 맞는" 선택이 정답입니다. time.perf_counter로 워밍업을 뺀 평균 시간을 직접 재 보면 검출기 간 상대 경향을 확인할 수 있고, 균형이 필요하면 내장 YuNet, 정확도가 최우선이면 RetinaFace, 실시간 다인원이면 MediaPipe나 YOLO-face가 무난합니다. 다음 장에서는 지금까지 배운 것을 모아, 웹캠에서 여러 얼굴을 실시간으로 검출하는 작은 실습으로 PART 02를 마무리합니다.