OpenCV를 활용하면 정지 이미지(사진) 속에서 사람의 얼굴을 쉽게 검출할 수 있습니다. 얼굴 검출을 위해서는 detectMultiScale() 함수를 사용합니다. 이 함수는 Haar Cascade 분류기와 함께 동작하여 이미지 내의 얼굴 영역을 찾아냅니다.
dectectMultiScale() 함수 기본 문법
detectMultiScale(source matrix, vector, searchScaleFactor, minNeighbours, flags, minfeatureSize)
함수의 인자(argument) 값을 조절하면 검출 성능과 속도를 자유롭게 튜닝할 수 있습니다. 각 매개변수가 어떤 역할을 하는지 하나씩 살펴보겠습니다.
1. 소스 행렬(Source Matrix)
얼굴을 검출할 대상이 되는 행렬입니다. 정지 사진을 다룰 때는 imread()로 불러온 이미지가 저장된 Mat 객체가 해당됩니다.
2. 벡터(Vector)
검출된 얼굴의 위치 정보를 저장할 Rect 타입의 벡터입니다. OpenCV에서 사각형(Rect)은 벡터 형태로 정의되며, 검출 결과가 여러 개일 수 있으므로 반드시 vector<Rect>로 선언해야 합니다.
3. searchScaleFactor (탐색 배율 계수)
함수가 여러 크기의 얼굴을 얼마나 세밀하게 탐색할지 결정하는 값입니다. 일반적으로 1.1을 사용합니다. 1.2처럼 더 큰 값을 지정하면 검출 속도는 빨라지지만, 작은 얼굴을 놓칠 가능성이 커집니다.
4. minNeighbours (최소 이웃 수)
검출기의 신뢰도(confidence level)를 조절하는 매개변수입니다. 값이 클수록 오탐(false positive)이 줄어들어 신뢰도가 높아지지만 처리 속도가 느려지고, 값이 작을수록 빠르지만 잘못된 검출이 늘어날 수 있습니다. 보통 3~4 사이의 값을 사용합니다.
5. flags (플래그)
기본값으로 설정하면 이미지 내 모든 얼굴을 검출합니다. 플래그에 따라 동작 방식을 바꿀 수 있습니다.
- CASCADE_FIND_BIGGEST_OBJECT: 가장 큰 얼굴 하나만 검출합니다. 처리 속도가 빨라집니다.
- CASCADE_SCALE_IMAGE: 이미지 스케일 단위로 탐색하여 여러 개의 얼굴을 검출할 수 있습니다.
6. minFeatureSize (최소 특징 크기)
검출할 얼굴의 최소 크기를 지정합니다. 멀리 있는 작은 얼굴까지 찾으려면 작은 값을, 카메라에 가까운 큰 얼굴만 찾으면 되는 경우에는 큰 값을 사용합니다. 일반적인 거리에서는 (20 x 20) 또는 (30 x 30) 픽셀 크기가 적당합니다.
실제 예제에서는 detectMultiScale() 함수를 다음과 같이 호출합니다.
faceDetector.detectMultiScale(image_with_humanface, faces, 1.1, 4, CASCADE_SCALE_IMAGE, Size(20, 20));
전체 예제 코드
다음 코드는 OpenCV에서 정지 사진 속 사람 얼굴을 검출하고, 검출된 얼굴 주위에 사각형을 그려 화면에 표시하는 전체 과정을 보여줍니다.
#include<iostream>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
//rectangle() 함수의 정의가 포함된 헤더//
#include<opencv2/objdetect/objdetect.hpp>
//CascadeClassifier 클래스의 정의가 포함된 헤더//
#include<string>
using namespace std;
using namespace cv;
int main(int argc, char** argv) {
Mat image_with_humanface;//얼굴이 포함된 이미지를 불러올 행렬 선언//
image_with_humanface = imread("friends.jpg");//사람 얼굴이 담긴 이미지 로드//
namedWindow("Face Detection");//결과를 표시할 윈도우 생성//
string trained_classifier_location = "C:/opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml";//학습된 XML 분류기 파일 경로를 문자열로 지정//
CascadeClassifier faceDetector;//CascadeClassifier 클래스의 'faceDetector' 객체 선언//
faceDetector.load(trained_classifier_location);//XML 학습 분류기를 객체에 로드//
vector<Rect>faces;//검출된 얼굴을 저장할 Rect 타입 벡터 선언//
vector<Rect>boundary;//경계 정보용 Rect 타입 벡터 선언//
faceDetector.detectMultiScale(image_with_humanface, faces, 1.1, 4, CASCADE_SCALE_IMAGE, Size(20, 20));//'image_with_humanface' 행렬에서 얼굴 검출//
for (size_t i = 0; i < faces.size(); i++){ //검출된 얼굴 주위에 사각형을 그리는 반복문//
Mat faceROI = image_with_humanface(faces[i]);//얼굴 영역을 별도의 행렬에 저장//
int x = faces[i].x;//얼굴 사각형 시작점의 x 좌표(행 값) 획득//
int y = faces[i].y;//얼굴 사각형 시작점의 y 좌표(열 값) 획득//
int h = y + faces[i].height;//사각형의 높이 계산//
int w = x + faces[i].width;//사각형의 너비 계산//
rectangle(image_with_humanface, Point(x, y), Point(w, h), Scalar(255, 0, 255), 2, 8, 0);//얼굴 주위에 사각형 그리기//
}
imshow("Face Detection", image_with_humanface);//검출된 얼굴 화면에 표시//
waitKey(0);//키 입력이 있을 때까지 프로그램 대기//
return 0;
}실행 결과
위 코드를 실행하면 입력 이미지에서 검출된 모든 얼굴 위치에 마젠타색(magenta) 사각형이 그려진 결과 창이 나타납니다. 분류기 파일 경로와 이미지 파일명만 환경에 맞게 수정하면 누구나 손쉽게 얼굴 검출 프로그램을 구현할 수 있습니다.