임도현의 성장
OpenCV 얼굴인식(Face Detection) 사용해보기 본문
📻OpenCV 란?
Open Source Computer Vision의 약자로 영상 처리에 사용할 수 있는 오픈 소스 라이브러리입니다. OpenCV는 이미지와 비디오 처리, 물체 추적, 얼굴 인식, 패턴 인식 등 다양한 컴퓨터 비전 기술을 구현하는 데 필요한 강력한 도구들을 제공합니다. OpenCV는 C++로 개발되었으며, Python, Java, 그리고 여러 다른 언어 바인딩을 통해 다양한 플랫폼에서 사용할 수 있습니다.
😰 컴퓨터 비전이란?
컴퓨터 비전(Computer Vision, CV)은 인간의 시각적 능력을 모방하여 이미지를 분석하고 해석하며, 이를 바탕으로 "의사 결정을 내리는 인공지능(AI) 기술입니다." 컴퓨터 비전을 활용하면 이미지, 패턴, 객체를 감지하고 인식할 수 있습니다. 이 기술은 자율주행차, 의료 영상 분석, 온라인 쇼핑 등 다양한 분야에서 핵심적인 역할을 수행하고 있습니다.
📚얼굴 인식을 어떻게 할까?
OpenCV가 이미지만 보고 얼굴을 인식하는 원리는 "머신 러닝"과 "패턴 인식" 기술을 기반으로 합니다. 가장 일반적으로 사용되는 얼굴 인식 방법은 Haar Cascade Classifier입니다.
🍪Haar Cascade Classifier란?
Haar Cascade Classifier는 Haar 특징(Haar Features)와 기계 학습 알고리즘을 활용한 얼굴 검출 알고리즘입니다.
- Haar 특징(Haar Features) : Haar 특징은 기본적으로 이미지 내에서 특정 부분의 명도 차이를 나타내는 특징입니다. 이 특징들은 주로 사각형 형태로 나누어지고, 각 사각형의 밝기 차이를 비교하여 이미지의 패턴을 인식합니다.
- Cascade Classifier : 이미지에서 큰 특징을 찾고, 이후 단계에서 점점 더 작은 특징을 찾아가며 얼굴을 정확히 인식합니다.
즉 Haar Cascade Classifier는모델 이 수많은 얼굴을 학습하여 빠르게 얼굴의 특징, 눈, 코, 입의 배치 및 밝기 차이 등을 찾아 얼굴을 인식 할 수 있는것입니다.
🌐OpenCV 샘플 확인
https://github.com/opencv/opencv/blob/4.x/samples/java/eclipse/HelloCV/src/Main.java
OpenCV 설치를 하고 깃허브에서 샘플을 찾아 실행 보면 응답 값을 확인 할 수 있다. native library로 dll 파일을 연결해두지 않았으면 loadLibrary가 파일을 찾지 못해 에러가 난다.
public class Main {
public static void main(String[] args) {
System.out.println("Welcome to OpenCV " + Core.VERSION);
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat m = Mat.eye(3, 3, CvType.CV_8UC1);
System.out.println("m = " + m.dump());
}
}
결과 값 :
Welcome to OpenCV 4.5.5
m = [ 1, 0, 0;
0, 1, 0;
0, 0, 1]
🚨예제 코드
face detection을 java로 사용하는 코드는 아래 사이트를 참고 하였다.
https://www.tutorialspoint.com/opencv/opencv_face_detection_in_picture.htm
OpenCV의 네이티브 라이브러리를 시스템에 로드하여 Java에서 OpenCV의 기능을 사용할 수 있도록 합니다.
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Imgcodecs.imread() 메서드 는 이미지 읽기 함수입니다. 주어진 파일 경로에 있는 이미지를 메모리 상에서 Mat 객체로 불러옵니다. Mat 객체는 OpenCV에서 이미지를 다루는 핵심 클래스로 행렬(Matrix) 을 기반으로 이미지를 2차원 행렬 형태로 저장하고 처리하는 역할을 합니다.
Mat image = Imgcodecs.imread(IMAGE_PATH);
if (image.empty()) {
System.out.println("이미지를 로드할 수 없습니다.");
return;
}
CascadeClassifier는 객체 검출을 위한 핵심 클래스입니다. CascadeClassifier 객체를 생성하고 CASCADE_PATH에 지정된 Haar Cascade XML 파일 또는 LBP Cascade XML 파일을 읽도록합니다. 저 같은 경우는 LBP로 설정 하였습니다.
CascadeClassifier faceCascade = new CascadeClassifier(CASCADE_PATH);
if (faceCascade.empty()) {
System.out.println("Haar Cascade 파일을 로드할 수 없습니다.");
return;
} else {
System.out.println("Haar Cascade 파일이 정상적으로 로드되었습니다.");
}
Mat 객체 생성 후 Imgproc.cvtColor() 메서드를 활용하여 색상 공간 변환을합니다.
- 첫 번째 파라미터 image 변환할 원본 이미지를 넣습니다. 일반적으로 원본 이미지는 컬러 BGR 형식입니다.
- 두 번째 파라미터 grayImage 변환된 이미지를 저장할 Mat객체
- 세 번째 파라미터 Imgproc.COLOR_BGR2GRAY 색상 변환의 종류를 지정하는 인자입니다. COLOR_BGR2GRAY는 BGR 색상 공간에서 Grayscale (그레이스케일) 색상 공간으로 변환하는 설정입니다.
Mat grayImage = new Mat();
Imgproc.cvtColor(image, grayImage, Imgproc.COLOR_BGR2GRAY);
MatOfRect는 OpenCV에서 직사각형(Rect) 영역을 여러 개 저장할 수 있는 행렬(Matrix) 형식의 클래스입니다. 얼굴 인식처럼 여러 개의 객체를 동시에 검출할 때, 검출된 각 객체의 위치를 Rect 객체로 나타냅니다. 즉 Rect 객체를 여러 개 저장하는 역할을 하며, 얼굴 검출에서 여러 개의 얼굴을 찾을 때 사용됩니다.
MatOfRect faces = new MatOfRect();
detectMultiScale() 메서드는 얼굴이나 다른 객체를 다양한 크기에서 인식하는 데 사용됩니다.
- 첫 번째 파라미터 : 검출할 입력 이미지로 Grayscale (그레이스케일)로 하여야 더 빠르게 처리 할 수 있음
- 두 번째 파라미터 : detectMultiScale() 메서드가 찾은 얼굴의 위치와 크기를 기억하는 MatOfRect객체에 저장
- 세 번째 파라미터 : 스케일 팩터는 이미지에서 얼굴을 검출할 때 이미지 크기를 조정하는 비율입니다. 예를 들어, 1.1을 사용하면 이미지 크기를 1.1배씩 줄여가며 얼굴을 찾고, 검출된 얼굴을 기반으로 다시 다른 크기의 이미지에서 얼굴을 찾습니다.
- 네 번째 파라미터 : 최소 이웃은 얼굴로 인식된 후보 영역이 최소한 몇 개의 인접 영역과 겹쳐야 얼굴로 인식할지를 결정하는 값입니다. 값이 높을수록 더 정확하지만 얼굴을 놓칠 수 있고, 너무 낮으면 잘못된 얼굴을 검출할 수 있습니다.
- 다섯 번째 파라미터 : 플래그 특별한 의미가 없으며 기본값인 0 을 사용하여 검출합니다.
- 여섯 번째 파라미터 : 최소 크기는 검출할 얼굴의 최소 크기를 지정합니다. 얼굴이 최소한 30x30 크기 이상이어야 검출되도록 설정
- 일곱 번째 파라미터 : 최대 크기는 검출할 얼굴의 최대 크기를 지정하는 값입니다. 저는 최대 크기를 설정하지 않아서 기본값인 이미지 크기를 사용합니다.
faceCascade.detectMultiScale(grayImage, faces, 1.1, 3, 0, new Size(30, 30), new Size());
MatOfRect객체에 저장된 찾은 얼굴 수를 보여주는 로그입니다.
System.out.println("찾은 얼굴 수: " + faces.toArray().length);
얼굴 인식 후 이미지에 사각형을 그리는 부분입니다. Imgproc.rectangle() 메서드는 이미지에 직사각형을 그리는 OpenCV 함수입니다.
- 첫 번째 파라미터 : 직사각형을 그릴 대상 이미지입니다.
- 두 번째 파라미터 : 직사각형의 좌측 상단 좌표입니다.
- 세 번째 파라미터 : 직사각형의 우측 하단 좌표입니다.
- 네 번째 파라미터 : 직사각형의 색상입니다. OpenCV에서 BGR 색상을 사용합니다.
- 다섯 번째 파라미터 : 직사각형의 선 두깨입니다.
for (Rect face : faces.toArray()) {
Imgproc.rectangle(image, face.tl(), face.br(), new Scalar(0, 0, 255), 2);
}
Imgcodecs.imwrite() 는 OpenCV의 이미지 파일을 저장하는 함수입니다.
Imgcodecs.imwrite("C:/Users/User/eclipse-workspace/Opencv/src/images/output_image.jpg", image);
System.out.println("얼굴 인식이 완료되었습니다.");
🥳얼굴 인식 과정
- 이미지 전처리 (그레이스케일 변환)
- Haar Cascade 분류기 로딩
- 얼굴 검출 (DetectMultiScale)
- 검출된 얼굴 영역 표시
🚀전체 소스 코드
public class Main {
public static void main(String[] args) {
System.out.println("Welcome to OpenCV " + Core.VERSION);
// OpenCV 라이브러리 로드
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
String imagePath = "이미지 경로";
String cascadePath = "LBP Cascade XML 경로";
CascadeClassifier faceCascade = new CascadeClassifier(cascadePath);
if (faceCascade.empty()) {
System.out.println("Haar Cascade 파일을 로드할 수 없습니다.");
return;
} else {
System.out.println("Haar Cascade 파일이 정상적으로 로드되었습니다.");
}
Mat grayImage = new Mat();
Imgproc.cvtColor(image, grayImage, Imgproc.COLOR_BGR2GRAY);
MatOfRect faces = new MatOfRect(); // MatOfRect 객체로 얼굴 위치 저장
faceCascade.detectMultiScale(grayImage, faces, 1.1, 3, 0, new Size(30, 30), new Size());
System.out.println("찾은 얼굴 수: " + faces.toArray().length);
for (Rect face : faces.toArray()) {
Imgproc.rectangle(image, face.tl(), face.br(), new Scalar(0, 0, 255), 2);
}
Imgcodecs.imwrite("이미지 저장 경로", image);
System.out.println("얼굴 인식이 완료되었습니다.");
}
}
🏆실행 결과
프로그램을 실행시키면 주어진 이미지 파일에서 얼굴을 자동으로 인식하여 인식된 얼굴 위치에 빨간색 사각형을 그린 후, 결과 이미지를 저장하는 라이브러리를 사용해 보았습니다. 이제 이 방식을 기반으로 다양한 프로젝트에 활용할 수 있을거 같습니다.