라즈베리파이를 이용한 얼굴, 눈 인식 튜토리얼! ✨🤩
c++코드로 opencv 라이브러리를 이용하여 얼굴에서 눈을 인식하고 눈에 선글라스를 씌워보자.
라즈베리 파이(Raspberry Pi)는 싱글 보드 컴퓨터(Single-Board Computer, SBC)로, 영국의 Raspberry Pi Foundation에서 개발한 저렴한 가격의 컴퓨터라고 생각하면 된다.
라즈베리 파이의 주요 특징:
라즈베리 파이는 프로그래밍, 로봇 공학, 웹 서버, 미디어 스트리밍, 게임 개발, Internet of Things (IoT) 등 다양한 분야에서 활용가능하다.
OpenCV(Open Source Computer Vision Library)는 컴퓨터 비전 및 이미지 처리 작업을 위한 오픈 소스 라이브러리. OpenCV는 이미지 및 비디오 처리, 객체 감지, 얼굴 인식, 동작 추적 등 다양한 컴퓨터 비전 작업을 지원해준다. 따라서 OpenCV를 이용하면 간단히 얼굴 인식을 할 수 있다.
라즈베리 파이에서 OpenCV를 설치하는 방법:
라즈베리파이 터미널에 다음 명령어를 입력한다.
sudo apt update
sudo apt upgrade
OpenCV 설치를 위한 패키지 및 설정
sudo apt install libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev -y
sudo apt install libavcodec-dev libavformat-dev libswscale-dev libxvidcore-dev libx264-dev libxine2-dev -y
sudo apt install libv4l-dev v4l-utils -y
sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev -y
sudo apt install libgtk2.0-dev libgtk-3-dev -y
sudo apt install mesa-utils libgl1-mesa-dri libgtkgl2.0-dev libgtkglext1-dev -y
sudo apt install libatlas-base-dev gfortran libeigen3-dev -y
sudo apt install python2.7-dev python3-dev python-numpy python3-numpy -y
OpenCV 및 OpenCV Contrib 소스 코드 다운로드
mkdir opencv
cd opencv
wget -O opencv.zip https://github.com/opencv/opencv/archive/4.1.2.zip
wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/4.1.2.zip
unzip opencv.zip
unzip opencv_contrib.zip
cd opencv-4.1.2
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_TBB=OFF -D WITH_IPP=OFF -D WITH_1394=OFF -D BUILD_WITH_DEBUG_INFO=OFF -D BUILD_DOCS=OFF -D INSTALL_C_EXAMPLES=ON -D INSTALL_PYTHON_EXAMPLES=ON -D BUILD_EXAMPLES=OFF -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D ENABLE_NEON=ON -D ENABLE_VFPV3=ON -D WITH_QT=OFF -D WITH_GTK=ON -D WITH_OPENGL=ON -D OPENCV_ENABLE_NONFREE=ON -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-4.1.2/modules -D WITH_V4L=ON -D WITH_FFMPEG=ON -D WITH_XINE=ON -D ENABLE_PRECOMPILED_HEADERS=OFF -D BUILD_NEW_PYTHON_SUPPORT=ON -D OPENCV_GENERATE_PKGCONFIG=ON ../ -D WITH_OPENCL=ON
make
sudo make install
얼굴에서 눈을 인식하고 눈부분에 선글라스 이미지를 입혀보자.
라즈베리 파이의 카메라로부터 영상을 받아와서 얼굴과 눈을 인식하고 미리 설정한 sunglasses.png 이미지를 눈부분에 삽입하여 실시간으로 보여주는 코드를 c++로 작성하였다.
#include </opencv2/opencv.hpp>
#include </opencv2/highgui.hpp>
#include </opencv2/objdetect.hpp>
#include <iostream>
using namespace std;
using namespace cv;
// 한 프레임에서 얼굴과 눈 추출을 위한 함수
void detectAndDisplay(Mat frame);
// 얼굴 인식 학습데이터 저장 파일 이름
String face_cascade_name;
// 눈 인식 학습데이터 저장 파일 이름
String eyes_cascade_name;
// Cascade 분류를 통한 얼굴 인식 객체
CascadeClassifier face_cascade;
// Cascade 분류를 통한 눈 인식 객체
CascadeClassifier eyes_cascade;
// 결과를 보여줄 창의 이름
String window_name = "Face and eyes detection";
int main(int argc, char **argv)
{
int CAM_ID = -1;
Mat frame1;
// Cascade 기법을 통해 얼굴 인식을 위한 학습 결과 데이터 파일 (해당 경로에 xml 파일이 있어야함)
face_cascade_name = "/usr/local/share/opencv4/haarcascades/haarcascade_frontalface_alt.xml";
if (!face_cascade.load(face_cascade_name))
{
printf("Error! loading face cascade\n");
return -1;
}
// Cascade 기법을 통해 눈 인식을 위한 학습 결과 데이터 파일 (해당 경로에 xml 파일이 있어야함)
eyes_cascade_name = "/usr/local/share/opencv4/haarcascades/haarcascade_eye.xml";
if (!eyes_cascade.load(eyes_cascade_name))
{
printf("Error! loading eyes cascade \n");
return -1;
}
VideoCapture cap(CAM_ID); //
if (!cap.isOpened())
{
// 카메라 열렸는지 확인
printf("Can't open the CAM (%d)\n", CAM_ID);
return -1;
}
while (1)
{
// 카메라에서 이미지 얻어오기
cap >> frame1;
// 이미지의 정상 여부를 확인
if (frame1.empty())
{
printf(" Read frame error!");
break;
}
// 얼굴과 눈 검출 함수 호출
detectAndDisplay(frame1);
// 10ms 동안 키입력 대기
if (waitKey(10) >= 0)
break;
} // end while()
// 윈도우 증료
destroyWindow(window_name);
return 0;
}// end main()
void detectAndDisplay(Mat frame)
{
vector<Rect> faces;
vector<Rect> eyes;
Mat frame_gray;
Mat roi_gray;
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
for (size_t i = 0; i < faces.size(); i++)
{
rectangle(frame, faces[i], Scalar(0, 0, 255), 1, 8, 0);
roi_gray = frame_gray(faces[i]);
eyes_cascade.detectMultiScale(roi_gray, eyes, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
if (eyes.size() == 2)
{
int x, y, width, height;
if (eyes[0].x < eyes[1].x)
{
x = eyes[0].x;
y = eyes[0].y;
width = (eyes[1].x - eyes[0].x) * 2;
}
else
{
x = eyes[1].x;
y = eyes[1].y;
width = (eyes[0].x - eyes[1].x) * 2;
}
eyes[0].height > eyes[1].height ? height = eyes[0].height : height = eyes[1].height;
Mat sunclasses = imread("sunglasses.png");
Mat re_sunclasses;
resize(sunclasses, re_sunclasses, Size(width, height), 0, 0, INTER_LINEAR);
Mat re_sunclasses_gray;
cvtColor(re_sunclasses, re_sunclasses_gray, COLOR_BGR2GRAY);
Mat mask;
threshold(re_sunclasses_gray, mask, 50, 255, THRESH_BINARY_INV);
Mat roi(frame, Rect(faces[i].x + x, faces[i].y + y, width, height));
re_sunclasses.copyTo(roi, mask);
}
}
imshow(window_name, frame);
}
OpenCV의 CascadeClassifier를 사용하여 얼굴과 눈을 쉽게 인식할 수 있다.
1. 얼굴을 인식하고 인식된 얼굴 주변에 빨간색 사각형을 그린다.
2. 각 얼굴 영역에서 눈을 인식하고 두 개의 눈이 감지되면, 그 두 눈 사이에 선글라스 이미지를 삽입하여 실시간으로 출력한다.
구글에서 간단히 선글라스 이미지를 검색해 다운받아 sunglasses.png로 저장 후 소스코드가 위치한 폴더에 위치시켰다.
g++ main.cpp -o a.out $(pkg-configopencv4--libs--cflags)
./a.out
실행하면 카메라 모듈의 입력을 보여주는 창이 뜬다.
카메라에 얼굴을 가져다 대자 빨간색박스로 얼굴이 인식되며 눈이 인식되면 선글라스가 덮어 씌워진다.😎
일론 머스크 형님에게도 멋진 선글라스를 씌워보았다.
일론 형님에게는 선글라스가 살짝 작아보였다...ㅎㅎ
이 튜토리얼을 통해 라즈베리 파이를 사용하여 얼굴 인식을 구현하는 기초를 익힐 수 있었다. 작고 저렴한 라즈베리 파이를 이용해 이렇게 다양한 기능을 사용해보며 작지만 강한 친구라는 걸 알 수 있었고 왜 많은 사람들에게 각광받는지 이해가 갔다.👍