본문 바로가기
OpenCV

[C++] OpenCV Haar Cascade로 얼굴, 눈 영역 찾기 예제 [02]

by dev_drive 2023. 3. 8.
반응형

 

 

[C++] OpenCV란? 개념과 설치/세팅 방법 [01]

※ OpenCV란? OpenCV는 Open Source Computer Vision Library로, 이미지와 동영상 처리에 사용되는 라이브러리 입니다. C++, Python, Java 등 다양한 프로그래밍 언어를 지원하며 이미지 프로세싱, 컴퓨터 비전 및

dev-drive.tistory.com

 


※ Haar Cascade란?

Haar Cascade는 이미지 분류 및 객체 탐지를 위한 기술 중 하나로, 컴퓨터 비전 분야에서 자주 사용됩니다.

 

이 기술은 인공신경망이나 딥러닝을 사용하지 않고,

이미지에서 특정 패턴을 탐지해서 이미지를 분류하거나 객체를 탐지합니다.

 

딥러닝이 적용된 기술이 아니기 때문에 속도는 빠를 수 있어도 정확도가 낮은 편이고

엉뚱한 영역을 탐지하는 경우도 많지만

영역이 명확히 구분되어 있는 이미지에서는 사용해볼 수 있는 기술입니다. 

 

 

 

※ Haar Cascade의 물체 탐지 방법

Haar Cascade는 물체를 탐지하기 위해 다양한 도형의 형태를 정해두고 이미지를 해당 도형에 맞춰서

픽셀 값들의 밝기 차이를 계산하여 이미지 내의 특정 구간이 해당 패턴과 일치하는지 검사합니다. 

# 특징을 찾아내기 위한 도형의 형태

 

# Haar Cascade로 얼굴의 특정 부분을 감지

 

Haar Cascade로 얼굴 영역 감지가 가능한 이유는 사람의 얼굴에는 공통적으로 밝기 차이가 존재하기 때문입니다.

예를들어 위 사진처럼 눈과 광대 부분, 눈과 코 부분은 밝기 차이가 존재합니다.

 

하지만 단순히 이런 특징만 가지고 검사하기 때문에 옆모습이나 얼굴이 대각선으로 눕혀져 있는 경우 등에서는

얼굴 영역을 찾지 못해 누락될 확률이 높고

얼굴이 아니더라도 저런 패턴을 가진 부분을 얼굴로 잘못 인식 하는 경우도 종종 있습니다. 

 

 

 

※ Haar Cascade 식별용 xml 다운로드

 

GitHub - opencv/opencv: Open Source Computer Vision Library

Open Source Computer Vision Library. Contribute to opencv/opencv development by creating an account on GitHub.

github.com

위 GitHub 링크에서 식별용 xml을 다운로드 받을 수 있습니다.

 

xml 이름으로 대충 추측할 수 있지만 얼굴, 몸 전체, 눈, 상체 등을 구분할 수 있습니다. 

 

예제에서는 얼굴 영역 추출에는 haarcascade_frontalface_default.xml

눈 영역 추출에는 haarcascade_eye.xml 를 사용하겠습니다. 

 

현재 기준으로 두 모델 모두 10년 전에 마지막으로 업데이트가 된걸 보면

엄청 오래된 기술이라는 것을 확인할 수 있습니다. 

 

 

 

 

OpenCV C++ Haar Cascade 얼굴, 눈 영역 탐지 예제

 

※ 예제를 실행하기 전에 개발세팅이 되어 있지 않다면 이전 글을 참고하여 세팅 먼저 진행해주세요.

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;


Mat img = imread("test.jpg");			// 이미지 read

Mat grayImg;
cvtColor(img, grayImg, COLOR_BGR2GRAY);		// 정확도를 높히기 위해 gray 이미지로 변경

std::vector<Rect> faceRect, eyeRect;
CascadeClassifier face, eye;

face.load("haarcascade_frontalface_default.xml");	// 얼굴 탐지 cascade load
if (!face.empty())
	face.detectMultiScale(grayImg, faceRect, 1.05, 10, 0, Size(50, 50));

eye.load("haarcascade_eye.xml");		// 눈 탐지 cascade load
if (!eye.empty())
	eye.detectMultiScale(grayImg, eyeRect, 1.05, 5, 0, Size(15, 15));

for (int i = 0; i < faceRect.size(); i++)
	rectangle(img, Rect(faceRect[i]), Scalar(50, 0, 200), 2);	// 얼굴 영역 그리기

for (int i = 0; i < eyeRect.size(); i++)
	rectangle(img, Rect(eyeRect[i]), Scalar(200, 0, 50), 2);	// 눈 영역 그리기

imshow("img_detect", img);			// 이미지 show
waitKey(0);

이미지 출처=세계일보

이미지에서 얼굴과 눈 영역을 추출하는 간단한 예제입니다. 

 

여기서 핵심은 detectMultiScale() 함수인데 함수의 원형은 다음과 같습니다.

 void detectMultiScale(InputArray image,	// 입력 이미지
    std::vector<Rect>& objects,			// 추출된 영역 
    double scaleFactor = 1.1,			// 이미지 배율 축소 정도
    int minNeighbors = 3, 			// 도형의 이웃 수 
    int flags = 0,				// 플래그
    Size minSize = Size(),			// 추출할 영역의 최소 크기 (해당 크기 이하는 무시)
    Size maxSize = Size() 			// 추출할 영역의 최대 크기 (해당 크기 이상는 무시)
);

 

여기서 scaleFactor와 minNeighbors 둘 다 물체 감지 도형에 대한 값이고 이 값에 따라 결과가 달라지는데

파라미터 설명을 읽어봐도 이해하기 어려워서 찾아보다가

StackOverflow에 그나마 이해하기 쉽게 설명해준 내용이 있어서 가져왔습니다.

 

 

scaleFactor 

이미지 감지를 위한 도형의 크기 비율 설정

즉, 크기가 작아질 수록 모델과 일치하는 영역을 탐지할 확률이 높아지지만 속도는 느려지고

크기가 커질수록 탐지할 확률은 줄어들지만 속도는 빨라집니다.  

 

 

minNeighbors

이미지 감지를 위한 도형이 유지 해야하는 이웃의 수

즉, 값이 높을수록 탐지하는 개수가 줄어들지만 품질은 높아지며

값이 낮을수록 많은 영역을 탐지하지만 품질이 낮아집니다.

 

아래 사진을 보면 해당 파라미터에 대해 더 쉽게 이해 가능합니다.

minNeighbors를 0으로 설정한 경우

 

minNeighbors를 1로 설정한 경우

 

목적에 따라 적절한 값을 찾아서 설정하시면 되고 detectMultiScale 오버로드 함수 중 

탐지된 영역의 정확도인 levelWeights값도 출력해주는 함수가 있으므로

필요한 경우 해당 함수를 사용하여 낮은 정확도의 탐지 영역은 무시하는 방법으로 사용하면

조금 더 정확도를 높일 수 있습니다.

 

 

※ 다음 챕터에서는 딥러닝으로 학습된 모델을 통해 얼굴을 인식하는 방법에 대해 알아보겠습니다.

 

[C++] OpenCV DNN 알고리즘으로 얼굴 인식하는 예제 [03]

[C++] OpenCV Haar Cascade로 얼굴, 눈 영역 찾기 예제 [02] [C++] OpenCV란? 개념과 설치/세팅 방법 [01] ※ OpenCV란? OpenCV는 Open Source Computer Vision Library로, 이미지와 동영상 처리에 사용되는 라이브러리 입니다

dev-drive.tistory.com

 

반응형

댓글