Programming/Qt

[도서 실습] Qt 5 and OpenCV 4 Computer Vision – The Facetious Application 02 (얼굴인식)

변화의 물결1 2024. 5. 3. 00:04

 

 

안녕하세요.

 

  이전 내용에서 얼굴을 찾아내는 프로그램을 위한 준비를 했다면 이번에는 얼굴을 찾아내는 코드를 추가해 봅니다. 이제 OpenCV 라이브러리를 이용해서 실시간으로 얼굴을 찾아는 것을 해볼 것입니다.

 

  얼굴을 인식을 위해서 OpenCV에서 제공해 주는 cascade classifiers 기술을 사용합니다. 이것은 얼굴인식뿐만 아니라 물체를 인식할 때도 사용되는 것입니다.

 우선 cascade classifier를 사용하기 전에 얼굴에 대한 학습을 진행해야 합니다. 어떤 것이 좋은 얼굴 사진이고 나쁜 사진인지 많은 데이터를 학습시켜 주어야 합니다. 학습시키는 과정도 복잡하기 때문에 여기서는 빼고 이미 만들어진 학습 데이터를 가지고 테스트해 볼 예정입니다.

 


 

1. 정면 얼굴 학습 데이터 준비

 

  - 이전 강좌 내용을 따라 OpenCV를 컴파일했다면 OpenCV가 설치된 경로에 아래와 같이 포함되어 있을 것입니다.

opencv\sources\\data\haarcascades\haarcascade_frontalface_default.xml

 

  이 학습된 데이터를 이용해서 얼굴인식을 해보도록 하겠습니다.

 

 

2. Facetious.pro 수정

 

  - 물체(얼굴)를 인식하기 위해서 라이브러리를 추가해 줍니다.   

 

LIBS += -Ld:/opencv/release/install/x64/mingw/bin \
     -lopencv_core453 \
     -lopencv_imgproc453 \
     -lopencv_videoio453 \
     -lopencv_video453 \
     -lopencv_imgcodecs453 \
     -lopencv_objdetect453

 

 

3. capture_thread.h 수정

 

  - CascadeClassifier를 사용하기 위해서 필요한 해더 파일, 변수와 함수를 선언해 줍니다.

 

 

#include "opencv2/objdetect.hpp"
//...
private:
    //...
    void detectFaces(cv::Mat &frame);
private:
    // face detection
    cv::CascadeClassifier *classifier;

 

 

4. capture_thread.cpp 수정

 

  - 카메라(웹캠)가 작동하면 run() 함수에서 CascadeClassifier 인스턴스를 학습된 데이터를 이용해서 생성하고, detectFaces 함수에 실시간 영상 프레임을 전달해서 처리하게 합니다. 그리고 카메라 종료되면 메모리에서 해제하고 변수를 초기화시킵니다.

 

(1) run() 함수 수정

 

  classifier = new cv::CascadeClassifier("OpenCV 설치하고 학습된 xml 파일이 있는 경로");
    while(running) {
        cap >> tmp_frame;
        if (tmp_frame.empty()) {
            break;
        }
        detectFaces(tmp_frame);
//...

} //while(running)

cap.release();
running = false;
delete classifier;
classifier = nullptr;

  

 

2) detectFaces() 함수 구현

 

  - 얼굴이 인식되면 화면에 표시해 주기 위한 사각 박스 좌표 변수를 만들어 줍니다. 그리고 detectMultiScale 함수를 이용해서 입력 영상 image에서 다양한 크기의 객체 사각형 영역을 검출합니다.

  - 전달받은 프레임을 먼저 grayscale 이미지로 변환합니다. 이유는 얼굴 인식하는 것과 RGB 색상은 상관이 없기 때문입니다.

 

  - 첫 번째 인자는 gray image이고, 두 번째는 얼굴 인식한 외각 좌표를 돌려주는 것(출력)이고, 세 번째 인자는 각 이미지 스케일에서 이미지 크기가 얼마나 축소되는지 지정하는 것으로, 단순히 카메라에 더 가깝기 때문에 하나의 얼굴이 다른 얼굴보다 크게 보일 때 발생하는 크기의 잘못된 인식을 보완하기 위해 만들어졌습니다. (검색 윈도우의 확대 비율 지정),

 

 네 번째 인자는 찾을 얼굴을 선언하기 전에 검출할 객체 영역에서 얼마나 많은 사각형이 중복되어 검출되어야 최종적으로 객체 영역으로 설정할지를 지정합니다. 기본값인 3으로 설정하면 검출된 사각형이 최소 세 개 이상 중첩되어야 최종적으로 객체 영역으로 판단합니다. 

 

void CaptureThread::detectFaces(cv::Mat &frame)
{
    vector<cv::Rect> faces;
    cv::Mat gray_frame;
    
    cv::cvtColor(frame, gray_frame, cv::COLOR_BGR2GRAY);
    classifier->detectMultiScale(gray_frame, faces, 1.3, 5);
    cv::Scalar color = cv::Scalar(0, 0, 255); // red

    for(size_t i = 0; i < faces.size(); i++) {
        cv::rectangle(frame, faces[i], color, 1);
    }
}

 

 

5. 실행 결과

 

  - 3번째 인자(ScaleFactor)는 1.1에서는 거의 검색하지 못했으며 2에 가까울수록 인식이 높아졌습니다. 그리고 2 이상일 경우 큰 차이를 느끼지 못했습니다.

  - 4번째 인자(Neighbors)는 1에 가까울수록 사각 박스가 얼굴이 아닌 곳도 잡았습니다. 그렇기 때문에 최소 3개 이상 중첩 검색하게 해 주어야 좋을 듯합니다.

 

  - 위의 결과는 OpenCV에서 주어진 학습 데이터로 진행을 한 것이고, 주변 환경, 테스트한 사진, 카메라 성능에 따라 달라질 수 있으므로 필요한 환경에 맞게 인자 값을 조절해야 할 것으로 보입니다.

  - 책에서는 HAAR과 LBP 알고리즘과 비교해주고 있는데 간단하게 말해서 LBP는 검색이 빠르긴 하지만 정확도가 HAAR 비해 낮다고 합니다.

- 테스트한 얼굴은 AI가 생성한 얼굴입니다.

 

 

 

 

 

감사합니다.

 

 

 

<참고사이트>

1. Qt에서 외부 프로그램 실행할 때 실행이 되고 안될 때

https://www.korone.net/bbs/board.php?bo_table=qt_qna&wr_id=22798

2. OBJECT DETECTION : FACE DETECTION USING HAAR CASCADE CLASSFIERS

https://www.bogotobogo.com/python/OpenCV_Python/python_opencv3_Image_Object_Detection_Face_Detection_Haar_Cascade_Classifiers.php

3. OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝

https://thebook.io/006939/ch13/02-07/

4. 100,000 가지 AI 생성 얼굴

https://pcwpower.tistory.com/37    

 

Facetious_day2.zip
0.13MB

반응형