本篇介紹圖像處理與模式識別中最熱門的一個領域——人臉檢測(人臉識別)。人臉檢測能夠說是學術界的寵兒,在很多EI,SCI高級別論文都能看到它的身影。甚至不少高校學生的畢業設計都會涉及到人臉檢測。固然人臉檢測的巨大實用價值也讓不少公司紛紛關注,不少公司都擁有這方面的專利或是開發商業產品出售。php
在OpenCV中,人臉檢測也是其熱門應用之一。在OpenCV的特徵檢測專題就詳細介紹了人臉檢測的原理——經過Haar特徵來識別是否爲人臉。Haar特徵檢測原理與Haar特徵分類器的訓練放到下一篇《【OpenCV入門指南】第十四篇 Haartraining》來說,本篇主要介紹如何在OpenCV中使用Haar特徵分類器來對圖像中的人臉進行檢測和識別。下面將分紅五步來詳細示範如何在OpenCV中進行人臉識別:ios
一.人臉的Haar特徵分類器是什麼windows
二.在哪找人臉的Haar特徵分類器ide
三.怎麼用人臉的Haar特徵分類器函數
四.人臉識別示例代碼ui
五.人臉識別程序運行結果spa
人臉的Haar特徵分類器就是一個XML文件,該文件中會描述人臉的Haar特徵值。固然Haar特徵的用途可不止能夠用來描述人臉這一種,用來描述眼睛,嘴脣或是其它物體也是能夠的。.net
OpenCV有已經自帶了人臉的Haar特徵分類器。OpenCV安裝目錄中的\data\ haarcascades目錄下的haarcascade_frontalface_alt.xml與haarcascade_frontalface_alt2.xml都是用來檢測人臉的Haar分類器。這個haarcascades目錄下還有人的全身,眼睛,嘴脣的Haar分類器。讀者能夠仿照本方的例子來試驗下效果看看。設計
使用人臉的Haar特徵分類器很是之簡單,直接使用cvHaarDetectObjects。下面來看看這個函數的介紹:3d
函數功能:檢測圖像中的目錄
函數原型:
CVAPI(CvSeq*) cvHaarDetectObjects(
const CvArr* image,
CvHaarClassifierCascade* cascade,
CvMemStorage* storage,
double scale_factor CV_DEFAULT(1.1),
int min_neighbors CV_DEFAULT(3),
int flags CV_DEFAULT(0),
CvSize min_size CV_DEFAULT(cvSize(0,0)),
CvSize max_size CV_DEFAULT(cvSize(0,0))
);
函數說明:
第一個參數表示輸入圖像,儘可能使用灰度圖以加快檢測速度。
第二個參數表示Haar特徵分類器,能夠用cvLoad()函數來從磁盤中加載xml文件做爲Haar特徵分類器。
第三個參數爲CvMemStorage類型,你們應該很熟悉這個CvMemStorage類型了,《OpenCV入門指南》中不少文章都介紹過了。
第四個參數表示在先後兩次相繼的掃描中,搜索窗口的比例係數。默認爲1.1即每次搜索窗口依次擴大10%
第五個參數表示構成檢測目標的相鄰矩形的最小個數(默認爲3個)。若是組成檢測目標的小矩形的個數和小於 min_neighbors - 1 都會被排除。若是min_neighbors 爲 0, 則函數不作任何操做就返回全部的被檢候選矩形框,這種設定值通常用在用戶自定義對檢測結果的組合程序上。
第六個參數要麼使用默認值,要麼使用CV_HAAR_DO_CANNY_PRUNING,若是設置爲CV_HAAR_DO_CANNY_PRUNING,那麼函數將會使用Canny邊緣檢測來排除邊緣過多或過少的區域,所以這些區域一般不會是人臉所在區域。
第七個,第八個參數表示檢測窗口的最小值和最大值,通常設置爲默認便可。
函數返回值:
函數將返回CvSeq對象,該對象包含一系列CvRect表示檢測到的人臉矩形。
下面給出一個完整的示例代碼,代碼中的GetTickCount能夠參閱《Windows 各類計時函數總結》,cvEqualizeHist能夠參閱《【OpenCV入門指南】第八篇灰度直方圖》。
// FaceDetect.cpp : 定義控制檯應用程序的入口點。 // 本文配套博客文章地址: http://blog.csdn.net/morewindows/article/details/8426318 #include "stdafx.h" #include <iostream> #include <opencv2/core/core.hpp> //cvGetSize cvCreateImage #include <opencv2/highgui/highgui.hpp> #include <opencv2/opencv.hpp> //cvResize cvInitMatHeader cvGetMinMaxHistValue cvCvtColor #include <opencv2/imgproc/imgproc.hpp> #include <Windows.h> //DWORD GetTickCount() #ifdef _DEBUG #pragma comment(lib, "opencv_core244d") #pragma comment(lib, "opencv_highgui244d") #pragma comment(lib, "opencv_imgproc244d") //cvResize #pragma comment(lib, "opencv_objdetect244d") //cvHaarDetectObjects #else #pragma comment(lib, "opencv_core244") #pragma comment(lib, "opencv_highgui244") #pragma comment(lib, "opencv_imgproc244") //cvResize #pragma comment(lib, "opencv_objdetect244") //cvHaarDetectObjects #endif using namespace std; int main() { // 加載Haar特徵檢測分類器 // haarcascade_frontalface_alt.xml系OpenCV自帶的分類器 下面是我機器上的文件路徑 const char *pstrCascadeFileName = "G:\\Software\\openCV\\opencv\\data\\haarcascades\\haarcascade_frontalface_alt.xml"; CvHaarClassifierCascade *pHaarCascade = NULL; pHaarCascade = (CvHaarClassifierCascade*)cvLoad(pstrCascadeFileName); // 載入圖像 const char *pstrImageName = "./images/linzhiling.jpg"; //const char *pstrImageName = "./images/liuyifei.jpg"; //const char *pstrImageName = "./images/unknown.jpg"; IplImage *pSrcImage = cvLoadImage(pstrImageName, CV_LOAD_IMAGE_UNCHANGED); IplImage *pGrayImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1); cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY); // 人臉識別與標記 if (pHaarCascade != NULL) { CvScalar FaceCirclecolors[] = { {{0, 0, 255}}, {{0, 128, 255}}, {{0, 255, 255}}, {{0, 255, 0}}, {{255, 128, 0}}, {{255, 255, 0}}, {{255, 0, 0}}, {{255, 0, 255}} }; CvMemStorage *pcvMStorage = cvCreateMemStorage(0); cvClearMemStorage(pcvMStorage); // 識別 DWORD dwTimeBegin, dwTimeEnd; dwTimeBegin = GetTickCount(); //函數將返回CvSeq對象,該對象包含一系列CvRect表示檢測到的人臉矩形 //第一個參數表示輸入圖像,儘可能使用灰度圖以加快檢測速度 //第二個參數表示Haar特徵分類器,能夠用cvLoad()函數來從磁盤中加載xml文件做爲Haar特徵分類器 //第三個參數爲CvMemStorage類型 //第四個參數表示在先後兩次相繼的掃描中,搜索窗口的比例係數。默認爲1.1即每次搜索窗口依次擴大10% //第五個參數表示構成檢測目標的相鄰矩形的最小個數(默認爲3個)。若是組成檢測目標的小矩形的個數和小於 min_neighbors - 1 都會被排除。 //若是min_neighbors 爲 0, 則函數不作任何操做就返回全部的被檢候選矩形框,這種設定值通常用在用戶自定義對檢測結果的組合程序上 //第六個參數要麼使用默認值,要麼使用CV_HAAR_DO_CANNY_PRUNING,若是設置爲CV_HAAR_DO_CANNY_PRUNING,那麼函數將會使用Canny邊緣檢測 //來排除邊緣過多或過少的區域,所以這些區域一般不會是人臉所在區域 //第七個,第八個參數表示檢測窗口的最小值和最大值,通常設置爲默認便可 CvSeq *pcvSeqFaces = cvHaarDetectObjects(pGrayImage, pHaarCascade, pcvMStorage); dwTimeEnd = GetTickCount(); printf("人臉個數: %d 識別用時: %d ms\n", pcvSeqFaces->total, dwTimeEnd - dwTimeBegin); // 標記 for(int i = 0; i <pcvSeqFaces->total; i++) { CvRect* r = (CvRect*)cvGetSeqElem(pcvSeqFaces, i); //用圓形畫出臉部部分 CvPoint center; int radius; center.x = cvRound((r->x + r->width * 0.5)); center.y = cvRound((r->y + r->height * 0.5)); radius = cvRound((r->width + r->height) * 0.25); cvCircle(pSrcImage, center, radius, FaceCirclecolors[i % 8], 2); //用矩形畫出臉部部分 /* CvPoint startPoint,endPoint; startPoint.x = cvRound(r->x); startPoint.y = cvRound(r->y); endPoint.x = cvRound(r->x + r->width); endPoint.y = cvRound(r->x + r->height); cvRectangle(pSrcImage,startPoint,endPoint,FaceCirclecolors[i % 8]); */ } cvReleaseMemStorage(&pcvMStorage); } const char *pstrWindowsTitle = "人臉識別"; cvNamedWindow(pstrWindowsTitle, CV_WINDOW_AUTOSIZE); cvShowImage(pstrWindowsTitle, pSrcImage); cvWaitKey(0); cvDestroyWindow(pstrWindowsTitle); cvReleaseImage(&pSrcImage); cvReleaseImage(&pGrayImage); return 0; }
運行結果一(單人正面):
這張圖的干擾太少,換張干擾大點的圖來試試。
運行結果二:
運行結果三(多人):
本文轉自:http://blog.csdn.net/morewindows/article/details/8426318