1.介紹
人臉識別是圖像處理非常重要的應用之一。本文這是一個簡單的人臉識別程序,運用OpenCV3中自帶的模型:(需要模型文件的私信我喔!)
haarcascade_frontalface_alt.xml
haarcascade_eye_tree_eyeglasses.xml
2.幾句牢騷話
人臉識別技術的衡量維度太多,但從技術比較,比如圖像比對級的1:1,1:N,N:N。衡量的標準和維度都不同。比如算法精確度上,國內國外的人臉識別技術大多數在開源OpenCV等開源庫上進行新規則添加(深度學習進行疊層運算),公司之間的識別正確率差異僅僅在小數點上,99.6%-99.7%提升意義不大,如果說就此稱王稱霸就說達到世界一流,就要被內行笑話了。基本上國內每家公司都會說自己的人臉識別算法牛,真正表達的是缺乏對底層技術的敬畏。
3.C++的人臉識別實現
//--------------------------------------【程序說明】-------------------------------------------
// 程序描述:人臉識別
// 測試所用作業系統: Windows 10 64bit
// 測試所用IDE版本:Visual Studio 2017
// 測試所用OpenCV版本: 3.4
// 2020年3月 Revised by @DL小寶
//------------------------------------------------------------------------------------------------
/**
* @file ObjectDetection.cpp
* @author A. Huaman ( based in the classic facedetect.cpp in samples/c )
* @brief A simplified version of facedetect.cpp, show how to load a cascade classifier and how to find objects (Face + eyes) in a video stream
*/
//---------------------------------【頭文件、命名空間包含部分】----------------------------
// 描述:包含程序所使用的頭文件和命名空間
//-------------------------------------------------------------------------------------------------
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
void detectAndDisplay(Mat frame);
//--------------------------------【全局變量聲明】----------------------------------------------
// 描述:聲明全局變量
//-------------------------------------------------------------------------------------------------
//注意,需要把"haarcascade_frontalface_alt.xml"和"haarcascade_eye_tree_eyeglasses.xml"這兩個文件複製到工程路徑下
String face_cascade_name = "haarcascade_frontalface_alt.xml";
String eyes_cascade_name = "haarcascade_eye_tree_eyeglasses.xml";
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
string window_name = "Capture - Face detection";
RNG rng(12345);
//--------------------------------【help( )函數】----------------------------------------------
// 描述:輸出幫助信息
//-------------------------------------------------------------------------------------------------
static void ShowHelpText()
{
//輸出歡迎信息和OpenCV版本
cout << "\n\n\t\t\t 當前使用的OpenCV版本為:" << CV_VERSION
<< "\n\n ----------------------------------------------------------------------------";
}
//-----------------------------------【main( )函數】--------------------------------------------
// 描述:控制台應用程式的入口函數,我們的程序從這裡開始
//-------------------------------------------------------------------------------------------------
int main(void)
{
VideoCapture capture;
Mat frame;
//-- 1. 加載級聯(cascades)
if (!face_cascade.load(face_cascade_name)) { printf("--(!)Error loading\n"); return -1; };
if (!eyes_cascade.load(eyes_cascade_name)) { printf("--(!)Error loading\n"); return -1; };
//-- 2. 讀取視頻
capture.open(0);
ShowHelpText();
if (capture.isOpened())
{
for (;;)
{
capture >> frame;
//-- 3. 對當前幀使用分類器(Apply the classifier to the frame)
if (!frame.empty())
{
detectAndDisplay(frame);
}
else
{
printf(" --(!) No captured frame -- Break!"); break;
}
int c = waitKey(10);
if ((char)c == 'c') { break; }
}
}
return 0;
}
void detectAndDisplay(Mat frame)
{
std::vector<Rect> faces;
Mat frame_gray;
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
//-- 人臉檢測
//此句代碼的OpenCV2版為:
//face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
//此句代碼的OpenCV3版為:
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++)
{
Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2);
ellipse(frame, center, Size(faces[i].width / 2, faces[i].height / 2), 0, 0, 360, Scalar(255, 0, 255), 2, 8, 0);
Mat faceROI = frame_gray(faces[i]);
std::vector<Rect> eyes;
//-- 在臉中檢測眼睛
//此句代碼的OpenCV2版為:
// eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, Size(30, 30) );
//此句代碼的OpenCV3版為:
eyes_cascade.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
for (size_t j = 0; j < eyes.size(); j++)
{
Point eye_center(faces[i].x + eyes[j].x + eyes[j].width / 2, faces[i].y + eyes[j].y + eyes[j].height / 2);
int radius = cvRound((eyes[j].width + eyes[j].height)*0.25);
circle(frame, eye_center, radius, Scalar(255, 0, 0), 3, 8, 0);
}
}
//-- 顯示最終效果圖
imshow(window_name, frame);
}