如何在一副圖片中檢測到人臉,這涉及到電腦圖形學中一些非常複雜的計算,如果這些計算都靠程式員自己來編程,那麼工作量就相當大。OpenCV全稱是Open Computer Vision,是指開放的電腦視覺資原始碼,它具有:統一的結構和功能定義、強大的映像和矩陣運算能力、方便靈活的介面等特點,是電腦視覺、影像處理和模式識別等方面進行二次開發的理想工具。它可以在各種版本的Windows下運行,也可以在Linux下運行。OpenCV的原始碼是用C和C++所編寫且完全開放的,因此具有很好的可移植性,在Microsoft
Visual C++ 6.0、Microsoft Visual Studio 2003及Borland C++ BuilderX等環境下均可方便地使用OpenCV所提供的庫來進行實際開發。本程式以Visual C++ 2005作為開發環境來介紹。
一、OpenCV在Visual C++ 2005下的安裝與配置
1.OpenCV安裝
首先到OpenCV的官方網站(http://sourceforge.net/projects/opencvlibrary)下載OpenCV並進行安裝,安裝過程很簡單,只要按照安裝嚮導一步一步進行即可。
2.對Visual C++ 2005進行全域設定
1)開啟Visual C++ 2005,選擇“Tools(工具) | Options(選項)”功能表項目,彈出1所示的對話方塊。
2)在左側列表框中選擇“Projects and Solutions(項目和解決問題方案) | VC++ Directories(VC++目錄)”。
3)在“Show directories for(顯示以下內容的目錄)”下拉式清單方塊中選擇“Library Files(庫檔案)”。
4)在右側庫檔案清單框中定位並添加“< OpenCV 安裝目錄>OpenCVlib” 。
5)在“Show directories for(顯示以下內容的目錄)”下拉式清單方塊中選擇“Include Files(包含檔案)”,並在右側列表框中定位並添加以下路徑:
< OpenCV 安裝目錄>OpenCVcxcoreinclude
< OpenCV 安裝目錄>OpenCVcvinclude
< OpenCV 安裝目錄>OpenCVcvauxinclude
< OpenCV 安裝目錄>OpenCVmlinclude
< OpenCV 安裝目錄>OpenCVotherlibshighgui
< OpenCV 安裝目錄>OpenCVotherlibscvcaminclude
< OpenCV 安裝目錄>OpenCVMicrosoft Platform SDKInclude
⑥單擊OK(確定)按鈕儲存配置。
3.對Visual C++ 2005項目進行設定
建立一個項目後,需要設定項目所需的連結庫。選擇“Project(項目) | Properties(屬性)”功能表項目,彈出2所示的對話方塊,在左側的列表框中選擇“Configuration Properties(配置屬性) | Linker(連結器) | Input(輸入)”,在右側列表框中選擇“Additional Dependencies(附加依賴項)”,在其右側的文字框中輸入“cxcore.lib cv.lib ml.lib highgui.lib cvaux.lib”等需要的庫(用空格分隔)。
二、臉部偵測程式的開發
臉部偵測是一個非常先進的問題,它是人臉研究的一個主要方向,其任務是對於一幅給定的映像,採用一定的策略對其進行搜尋,以確定其中是否含有人臉、含有多少個人臉,以及所含人臉的位置、大小和姿態。臉部偵測的演算法很多,Adaboost演算法是其中的一種,Adaboost演算法雖然十分複雜,但應用OpenCV提供的函數和分類器進行臉部偵測將是十分容易。
1.利用OpenCV進行臉部偵測
臉部偵測程式主要完成3部分功能,即載入分類器、載入待檢測圖象以及檢測並標示。本程式使用OpenCV中提供的“haarcascade_frontalface_alt.xml”檔案儲存體的目標檢測分類,用cvLoad函數載入後,進行強制類型轉換。OpenCV中提供的用於檢測映像中目標的函數是cvHaarDetectObjects,該函數使用指標對某目標物體(如人臉)訓練的級聯分類器在圖象中找到包含目標物體的矩形地區,並將這些地區作為一序列的矩形框返回。分類器在使用後需要被顯式釋放,所用的函數為cvReleaseHaarClassifierCascade。這些函數原型請參看有關OpenCV手冊。
2.程式實現
1)建立一個Visual C++ MFC項目,取名為“FaceDetection”,選擇應用程式類型為“單文檔”。將菜單中多餘的項去掉,並添加一項“臉部偵測”,其ID為“ID_FaceDetected”,並產生該功能表項目的訊息映射函數。
2)在“FaceDetectionView.h”標頭檔中添加以下灰底色部分程式碼:
//南京森林公安高等專科學校 江林升// FaceDetectionView.h : CFaceDetectionView 類的介面#pragma once#include "cv.h"#include "highgui.h"class CFaceDetectionView : public CView{protected: // 僅從序列化建立 CFaceDetectionView(); DECLARE_DYNCREATE(CFaceDetectionView)// 屬性public: CFaceDetectionDoc* GetDocument() const; CvHaarClassifierCascade* cascade;//特徵器分類 CvMemStorage* storage; void detect_and_draw( IplImage* img ); IplImage* src; //載入的映像
3)在“FaceDetectionView.cpp”檔案中添加以下灰底色部分程式碼:
// FaceDetectionView.cpp : CFaceDetectionView 類的實現#include "stdafx.h"#include "FaceDetection.h"#include "FaceDetectionDoc.h"#include "FaceDetectionView.h"#include <string>#ifdef _DEBUG#define new DEBUG_NEW#endif// CFaceDetectionViewIMPLEMENT_DYNCREATE(CFaceDetectionView, CView)BEGIN_MESSAGE_MAP(CFaceDetectionView, CView) ON_COMMAND(ID_FaceDetected, &CFaceDetectionView::OnFacedetected)END_MESSAGE_MAP()// CFaceDetectionView 構造/析構const char* cascade_name ="haarcascade_frontalface_alt.xml";//分類器的名稱// CFaceDetectionView 訊息處理常式void CFaceDetectionView::OnFacedetected() //臉部偵測菜單響應事件{ // TODO: 在此添加命令處理常式代碼 CString fileName; //開啟檔案交談視窗 CFileDialog OpenDlg( TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR, L"影像檔格式JPG file format (*.jpg)|*.jpg|(*.bmp) |*.bmp|", NULL); //從檔案交談視窗中開啟映像 if(OpenDlg.DoModal()!=IDOK) return; //獲得檔案名稱 fileName = OpenDlg.GetPathName(); //必要的類型轉換 std::string tempName = (LPCSTR)CStringA(fileName); const char* tmp = tempName.c_str(); //開啟檔案,若失敗則返回 if( (src = cvLoadImage(tmp, CV_LOAD_IMAGE_ANYCOLOR)) == 0 ) return; //載入(分類器層疊)訓練庫 cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 ); //載入不成功則顯示錯誤訊息,並退出 if(cascade) { storage = cvCreateMemStorage(0); cvNamedWindow( "臉部偵測", CV_WINDOW_AUTOSIZE ); //建立視窗 //如果圖片存在則分析並顯示結果,否則退出程式 if(src) detect_and_draw(src); //調用人臉檢與標示事件 cvReleaseImage(&src); cvReleaseMemStorage( &storage ); } else { &, nbsp; AfxMessageBox(L"無法載入分類器,請確認後重試!"); } cvReleaseHaarClassifierCascade( &cascade );}void CFaceDetectionView::detect_and_draw(IplImage *img) //人臉檢與標示事件{ static CvScalar color[] = {0,0,255};//用於設定標示映像中人臉的顏色 double scale = 1.3; IplImage* gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 ); IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale),cvRound (img->height/scale)),8,1 ); int i; cvCvtColor( img, gray, CV_BGR2GRAY ); cvResize( gray, small_img, CV_INTER_LINEAR ); cvEqualizeHist( small_img, small_img ); cvClearMemStorage( storage ); if( cascade ) { //檢測人臉 CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage, 1.1, 2, 0, cvSize(30, 30) ); for( i = 0; i < (faces ? faces->total : 0); i++ ) { CvRect* r = (CvRect*)cvGetSeqElem( faces, i ); CvPoint center; int radius; center.x = cvRound((r->x + r->width*0.5)*scale); center.y = cvRound((r->y + r->height*0.5)*scale); radius = cvRound((r->width + r->height)*0.25*scale); cvCircle( img, center, radius, color[0], 3, 8, 0 ); } } cvShowImage( "臉部偵測", img ); cvReleaseImage( &gray ); cvReleaseImage( &small_img );}
需要注意的是,本程式運行時應將分類器檔案置於程式目錄下,如果啟動並執行是產生的EXE檔案,則應將分類器檔案與該EXE檔案放在同一個目錄下。
三、程式運行結果
運行該程式,選擇臉部偵測功能表項目,彈出檔案開啟對話方塊,選擇要檢測的影像檔,程式就會將檢測到的人臉用圓圈標示出來,3所示。本程式能順利檢測出大部分人臉,但由於光照、遮擋和傾斜等原因,部分人臉不能正確檢測,另外,也有一些非人臉部分由於具有人臉的某些特徵,也被當成了人臉,這些都是本程式需要改進的部分。