[C++] OpenCV DNN 알고리즘으로 얼굴 인식하는 예제 [03]
[C++] OpenCV Haar Cascade로 얼굴, 눈 영역 찾기 예제 [02]
[C++] OpenCV란? 개념과 설치/세팅 방법 [01] ※ OpenCV란? OpenCV는 Open Source Computer Vision Library로, 이미지와 동영상 처리에 사용되는 라이브러리 입니다. C++, Python, Java 등 다양한 프로그래밍 언어를 지원
dev-drive.tistory.com
이전에 올렸던 Haar Cascade는 단순히 특징 분석을 통한 물체 감지였다면,
DNN 알고리즘은 딥러닝으로 학습된 모델을 통해 물체를 감지하기 때문에 더욱 높은 정확도를 기대할 수 있습니다.
※ DNN이란?
DNN(Deep Neural Network) 알고리즘은 인공 신경망의 일종으로,
입력층(input layer)과 출력층(output layer) 사이에 여러 개의 은닉층(hidden layer)을 추가하여 구성됩니다.
은닉층의 개수가 많아질수록 모델이 더 복잡해지며, 그만큼 높은 정확도를 기대할 수 있습니다.
각 은닉층은 여러 개의 뉴런(neuron)으로 구성되며,
각 뉴런은 입력값과 가중치(weight)를 곱한 후 활성화 함수(activation function)를 적용하여 출력값을 계산합니다.
DNN 알고리즘은 일반적으로 학습 데이터셋을 이용하여 가중치를 조정하는 방식으로 학습됩니다.
학습 데이터셋에 대한 입력값과 출력값을 제공하고, 모델은 입력값을 받아 출력값을 예측하게 됩니다.
그리고 예측값과 실제값의 차이를 계산하여 손실 함수(loss function)를 최소화하도록 가중치를 조정합니다.
이러한 과정을 여러 번 반복하면서 모델이 입력값과 출력값 사이의 관계를 파악하며, 예측 성능을 개선시킵니다.
DNN은 다양한 종류의 활성화 함수, 손실 함수, 최적화 알고리즘 등을 사용할 수 있으며,
이들을 조합하여 최적의 모델을 만들 수 있습니다.
DNN은 매우 복잡한 구조를 가지고 있기 때문에, 적절한 하이퍼파라미터(hyperparameter) 설정과
오버피팅(overfitting) 방지를 위한 정규화(regularization) 기법 등을 이용하여 학습을 안정화시키는 것이 중요합니다.
또한, DNN은 GPU 같은 병렬 처리 장치를 이용하여 빠르게 학습할 수 있으며,
대표적인 병렬 처리 장치로는 Nvidia의 CUDA가 있습니다.
하지만 모델을 직접 학습시키려면 많은 시간과 자원이 필요하기 때문에
특수한 목적이 아니라면 미리 학습되어 있는 모델을 다운받아 사용하시면 됩니다.
※ DNN 알고리즘이 적용된 Caffe 모델 다운로드
GitHub - keyurr2/face-detection: Face detection implementation with different methods and applications
Face detection implementation with different methods and applications - GitHub - keyurr2/face-detection: Face detection implementation with different methods and applications
github.com
정식 GitHub링크는 아니지만 C++코드에 적용할 수 있는 공개된 모델들이 많지 않아서
예제는 해당 모델로 진행하겠습니다.
Caffe는 오픈소스 딥러닝 프레임워크 중 하나이며,
TensorFlow, PyTorch, Darknet 등 다양한 프레임워크가 존재합니다.
위에 GitHub 들어가서 직접 받으셔도 되고 밑에 있는 모델 다운로드 하셔도 됩니다.
OpenCV DNN Caffe모델로 얼굴 영역 탐지하는 예제
※ 예제를 실행하기 전에 개발세팅이 되어 있지 않다면 아래 글을 참고하여 세팅 먼저 진행해주세요.
[C++] OpenCV란? 개념과 설치/세팅 방법 [01]
※ OpenCV란? OpenCV는 Open Source Computer Vision Library 약자로, 이미지와 동영상 처리에 사용되는 라이브러리 입니다. C++, Python, Java 등 다양한 프로그래밍 언어를 지원하며 이미지 프로세싱, 컴퓨터 비전
dev-drive.tistory.com
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace cv::dnn;
using namespace std;
// 얼굴 영역을 검출할 이미지 read
Mat img = imread("test.jpg");
// Caffe 모델 read
Net net = readNetFromCaffe("deploy.prototxt.txt", "res10_300x300_ssd_iter_140000.caffemodel");
// 이미지를 학습된 기준에 맞게 blob으로 변환
Mat imgBlob = blobFromImage(img, 1.0, Size(300, 300), Scalar(104, 177, 123));
net.setInput(imgBlob);
Mat netImg = net.forward();
// 검출된 얼굴 영역 표시
Mat detectImg(netImg.size[2], netImg.size[3], CV_32F, netImg.ptr<float>());
for (int i = 0; i < detectImg.rows; i++)
{
float confidence = detectImg.at<float>(i, 2);
if (confidence > 0.4) // 정확도 0.4 이하는 무시
{
int x1 = static_cast<int>(detectImg.at<float>(i, 3) * img.cols);
int y1 = static_cast<int>(detectImg.at<float>(i, 4) * img.rows);
int x2 = static_cast<int>(detectImg.at<float>(i, 5) * img.cols);
int y2 = static_cast<int>(detectImg.at<float>(i, 6) * img.rows);
// 얼굴영역 표시
rectangle(img, Point(x1, y1), Point(x2, y2), Scalar(0, 255, 0), 2);
// 정확도 표시
std::string label = format("%.2f", confidence);
putText(img, label, Point(x1, y1-10), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(50, 0, 255), 2);
}
}
imshow("Img", img);
waitKey(0);
이미지에서 얼굴 영역을 추출하는 간단한 예제입니다.
이미지를 blob으로 변경하는 이유는 학습된 모델과 동일한 크기와 형식으로 맞추기 위함입니다.
이 모델도 정확도가 엄청 높진 않지만 고화질의 이미지에서는 나쁘지 않은 정확도를 보입니다.
만약 net.forward(); 함수에서 vector subscript out of range 에러가 발생한다면 Release로 실행해보세요.
Debug에서 이 문제때문에 한참 고생하며 찾아봤는데 동일한 증상을 가지고 있는 사람들은 많았지만
적절한 해결법을 찾지 못했네요.
모델들이 대부분 파이썬을 통해 학습되었고 머신러닝 부분은 파이썬 언어가 많이 발달되어 있으며,
GitHub에서 머신러닝 관련 프로젝트를 찾아봐도 대부분 파이썬으로 이루어져 있습니다.
C++에서는 활용이 제한적이니 만약 파이썬도 능숙하게 다룰줄 안다면 파이썬으로 개발하는것을 추천드리고 싶네요.
※ 다음 챕터에서는 물체 인식/분류를 진행해보겠습니다.
[C++] OpenCV DNN 알고리즘으로 객체 인식/분류하는 예제 [04]
[C++] OpenCV DNN 알고리즘으로 얼굴 인식하는 예제 [03] [C++] OpenCV Haar Cascade로 얼굴, 눈 영역 찾기 예제 [02] [C++] OpenCV란? 개념과 설치/세팅 방법 [01] ※ OpenCV란? OpenCV는 Open Source Computer Vision Library로, 이
dev-drive.tistory.com