OpenCV 人臉識別

本篇介紹圖像處理與模式識別中最熱門的一個領域——人臉檢測(人臉識別)。人臉檢測可以說是學術界的寵兒,在不少EISCI高級別論文都能看到它的身影。甚至很多高校學生的畢業設計都會涉及到人臉檢測。當然人臉檢測的巨大實用價值也讓很多公司紛紛關注,很多公司都擁有這方面的專利或是開發商業產品出售。

    OpenCV中,人臉檢測也是其熱門應用之一。在OpenCV特徵檢測專題就詳細介紹了人臉檢測的原理——通過Haar特徵來識別是否爲人臉。Haar特徵檢測原理與Haar特徵分類器的訓練放到下一篇《【OpenCV入門指南】第十四篇  Haartraining》來講,本篇主要介紹如何在OpenCV中使用Haar特徵分類器來對圖像中的人臉進行檢測和識別。下面將分成五步來詳細示範如何在OpenCV中進行人臉識別:

    一.人臉的Haar特徵分類器是什麼

    二.在哪找人臉的Haar特徵分類器

    三.怎麼用人臉的Haar特徵分類器

    四.人臉識別示例代碼

    五.人臉識別程序運行結果

 

一.人臉的Haar特徵分類器是什麼

人臉的Haar特徵分類器就是一個XML文件,該文件中會描述人臉的Haar特徵值。當然Haar特徵的用途可不止可以用來描述人臉這一種,用來描述眼睛,嘴脣或是其它物體也是可以的。

 

二.在哪找人臉的Haar特徵分類器

OpenCV有已經自帶了人臉的Haar特徵分類器。OpenCV安裝目錄中的\data\ haarcascades目錄下的haarcascade_frontalface_alt.xmlhaarcascade_frontalface_alt2.xml都是用來檢測人臉的Haar分類器。這個haarcascades目錄下還有人的全身,眼睛,嘴脣的Haar分類器。讀者可以仿照本方的例子來試驗下效果看看。

 

三.怎麼用人臉的Haar特徵分類器

使用人臉的Haar特徵分類器非常之簡單,直接使用cvHaarDetectObjects。下面來看看這個函數的介紹:

函數功能:檢測圖像中的目錄

函數原型:

CVAPI(CvSeq*) cvHaarDetectObjects(

  const CvArrimage,

  CvHaarClassifierCascadecascade,

  CvMemStoragestorage,

  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入門指南】第八篇灰度直方圖》。


  1. <pre class="cpp" name="code">// 編譯前請配置好VS2008的編譯環境  

  2. // 詳見《【OpenCV入門指南】第一篇 安裝OpenCV》  

  3. // 地址: http://blog.csdn.net/morewindows/article/details/8225783  

  4.   

  5. // 本文配套博客文章地址:  

  6. // http://blog.csdn.net/morewindows/article/details/8426318  

  7.   

  8. // Haar特徵檢測 - 人臉識別  

  9. //By MoreWindows (http://blog.csdn.net/MoreWindows)  

  10. #include <opencv2/opencv.hpp>  

  11. #include <cstdio>  

  12. #include <cstdlib>  

  13. #include <Windows.h>  

  14. using namespace std;  

  15. int main()  

  16. {  

  17.     // 加載Haar特徵檢測分類器  

  18.     // haarcascade_frontalface_alt.xml系OpenCV自帶的分類器 下面是我機器上的文件路徑  

  19.     const char *pstrCascadeFileName = "G:\\OpenCV\\opencv\\data\\haarcascades\\haarcascade_frontalface_alt.xml";  

  20.     CvHaarClassifierCascade *pHaarCascade = NULL;  

  21.     pHaarCascade = (CvHaarClassifierCascade*)cvLoad(pstrCascadeFileName);  

  22.   

  23.     // 載入圖像  

  24.     const char *pstrImageName = "101.jpg";  

  25.     IplImage *pSrcImage = cvLoadImage(pstrImageName, CV_LOAD_IMAGE_UNCHANGED);  

  26.       

  27.     IplImage *pGrayImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);  

  28.     cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY);  

  29.   

  30.     // 人臉識別與標記  

  31.     if (pHaarCascade != NULL)  

  32.     {         

  33.         CvScalar FaceCirclecolors[] =   

  34.         {  

  35.             {{0, 0, 255}},  

  36.             {{0, 128, 255}},  

  37.             {{0, 255, 255}},  

  38.             {{0, 255, 0}},  

  39.             {{255, 128, 0}},  

  40.             {{255, 255, 0}},  

  41.             {{255, 0, 0}},  

  42.             {{255, 0, 255}}  

  43.         };  

  44.   

  45.         CvMemStorage *pcvMStorage = cvCreateMemStorage(0);  

  46.         cvClearMemStorage(pcvMStorage);  

  47.         // 識別  

  48.         DWORD dwTimeBegin, dwTimeEnd;  

  49.         dwTimeBegin = GetTickCount();  

  50.         CvSeq *pcvSeqFaces = cvHaarDetectObjects(pGrayImage, pHaarCascade, pcvMStorage);  

  51.         dwTimeEnd = GetTickCount();  

  52.   

  53.         printf("人臉個數: %d   識別用時: %d ms\n", pcvSeqFaces->total, dwTimeEnd - dwTimeBegin);  

  54.           

  55.         // 標記  

  56.         for(int i = 0; i <pcvSeqFaces->total; i++)  

  57.         {  

  58.             CvRect* r = (CvRect*)cvGetSeqElem(pcvSeqFaces, i);  

  59.             CvPoint center;  

  60.             int radius;  

  61.             center.x = cvRound((r->x + r->width * 0.5));  

  62.             center.y = cvRound((r->y + r->height * 0.5));  

  63.             radius = cvRound((r->width + r->height) * 0.25);  

  64.             cvCircle(pSrcImage, center, radius, FaceCirclecolors[i % 8], 2);  

  65.         }  

  66.         cvReleaseMemStorage(&pcvMStorage);  

  67.     }  

  68.       

  69.     const char *pstrWindowsTitle = "人臉識別 (http://blog.csdn.net/MoreWindows)";  

  70.     cvNamedWindow(pstrWindowsTitle, CV_WINDOW_AUTOSIZE);  

  71.     cvShowImage(pstrWindowsTitle, pSrcImage);  

  72.   

  73.     cvWaitKey(0);  

  74.   

  75.     cvDestroyWindow(pstrWindowsTitle);  

  76.     cvReleaseImage(&pSrcImage);   

  77.     cvReleaseImage(&pGrayImage);  

  78.     return 0;  

  79. }</pre><br>  

五.人臉識別程序運行結果

運行結果一(單人正面):

這張圖的干擾太少,換張干擾大點的圖來試試。

 

運行結果二(單人側面):

呵呵,左邊那個人眼睛被擋住了,因此普通的人臉檢測肯定難以識別的。

 

運行結果三(多人):

效果還不錯。當然商業級產品的準確度,性能,效率肯定會比OpenCV自帶的分類器高的多。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章