基於開源專案OpenCV的人臉識別Demo版整理(不僅可以識別人臉,還可以識別眼睛鼻子嘴等)
最近對人臉識別的程式非常感興趣,但是苦於沒有選修多媒體方向,看了幾篇關於人臉識別的論文,大概也沒看懂多少,什麼灰度處理啊,切割識別啊,雲裡霧裡,傻傻看不明白啊。各種苦惱。
於是就在網上找找,看有木有神馬開原始碼啊,要是有個現成的原始碼就更好了,百度it ,那些原始碼都憂傷的躲在CSDN中,老衲還是光頭沒積分型別的,沒有辦法,偶爾找幾個不用積分的連結吧,妹的,download的好幾天,都沒下來1K,徹底被打敗了。
一狠心一咬牙,自己幹了。毛爺爺教育我們說,自己動手,不愁吃喝拉撒睡。於是開始找開源的程式碼,開始我還天真的尋找Java版的,後來才明白,java的 運算能力根本不被大家認可,像人臉識別這種需要很高運算能力的,需要很高效率的事情,都只有C/C++的。後來就看到了OpenCV這個開源專案,一點一 點開始,終於完成了Demo版本,先晒幾張識別的照片,然後再談談Demo實現過程。
(本來想用本人靚照,後來想想,怕大家嚇怕了不敢繼續讀下去,還是找明星吧
這是載入影象後再通過影象識別,找到人臉,畫出人臉區域的紅圈後的效果。
一、OpenCV介紹
OpenCV的全稱是Open Source Computer Vision Library,是一個跨平臺的計算機視覺庫。OpenCV是由英特爾公司發起並參與開發,以BSD許可證授權發行,可以在商業和研究領域中免費使用。OpenCV可用於開發實時的影象處理、計算機視覺以及模式識別程式。
計算機視覺的應用領域越來越廣泛,無論從手機應用,行為分析,文書處理還有遊戲設計等,在很多地方已經投入了應用生產,而不學一點視覺的東西感覺自己都會落後了,哈哈。目前很多的計算機視覺的軟體都有其侷限性,成本高,開發週期長,沒有固定統一的API設計等等。
OpenCV在Intel公司發起後,不僅在這些問題上給了很多獨特的解決方案,同時還可以安裝Intel公司的IPP來進行加速處理。作為我們學習,就不必購買IPP,直接使用開源的OpenCV足以解決很多問題。
二、OpenCV安裝總結(在Windows環境下,如果需要了解Linux下的安裝過程,可以去官方的http://www.opencv.org.cn/forum/尋找解決辦法)
1.安裝VS2008,相信這個都沒問題。VC++2008Express也可以
2.安裝OpenCV2.0版本。
這個解釋一下啊,現在OpenCV已經出到了2.3版本,但是2.0是目前穩定的最新本,因為OpenCV是開源的專案,在持續的開發中,而2.0網上的介紹大多基於此,新版本的改進還很少詳細的介紹。所以2.0已經足夠用了。下載地址
下載後安裝,我安裝在了D:\Program Files\OpenCV2.0下
3.安裝CMake
CMake的百科解釋:CMake 是個跨平臺的自動化建構系統,它用組態檔控制建構過程(build process)的方式和 Unix 的 Make 相似,只是 CMake 的組態檔取名為 CmakeLists.txt。Cmake 並不直接建構出最終的軟體,而是產生標準的建構檔(如 Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),然後再依一般的建構方式使用。這使得熟悉某個整合開發環境(IDE)的開發者可以用標準的方式建構他的軟體,這種可以使用各平臺的原生建構系統的能力是 CMake 和 SCons 等其他類似系統的區別之處。CMake 可以編譯原始碼、製作程式庫、產生介面卡(wrapper)、還可以用任意的順序建構執行檔、
我的理解就是CMake是個開源的專案,用於構建原始碼,但是它構建不生成可用檔案,而是按照你喜歡的方式幫你構建原始碼,構建成特定IDE可用的工程。
一會需要用到它來幫助我們將OpenCV原始碼編譯成VS可用的工程。
4.用CMake匯出VC++專案檔案
- 執行cmake-gui,設定路徑為OpenCV安裝路徑(本文件假定安裝位置為:D:\Program Files\OpenCV2.0),並建立子目錄D:\Program Files\OpenCV2.0\vc2008,用於存放編譯結果。
- 然後點 configure,在彈出的對話方塊內選擇 Visual Studio 9 2008。
- 如果是VC++2008的Express版本,則不支援OpenMP,所以需要取消ENABLE_OPENMP選項,取消後再次選擇“Congfigure”,完成後選擇“Generate”。VC++ 2008(不是Express版本)支援OpenMP,如果你使用VC++2008,強烈建議不要取消這個選項。
注意:OpenCV2.1中沒有ENABLE_OPENMP選項,在安裝VC++2008時可以不管這個選項。
點選看大圖 |
點選看大圖 |
點選看大圖 |
5.編譯 OpenCV Debug和Release版本庫
完成上一步驟後,將在D:\Program Files\OpenCV2.0\vc2008目錄下生成OpenCV.sln的VC Solution File,請用VC++ 2008 Express開啟OpenCV.sln,然後執行如下操作:
- 在Debug下,選擇Solution Explorer裡的 Solution OpenCV,點右鍵,執行"Rebuild Solution";如編譯無錯誤,再選擇INSTALL專案,執行"Build"。
- 在Release下,選擇Solution Explorer裡的 Solution OpenCV,點右鍵,執行"Rebuild Solution";如編譯無錯誤,再選擇INSTALL專案,執行"Build"。
此時,OpenCV的*d.dll檔案(for debug)和*.dll檔案(for release)將出現在D:\Program Files\OpenCV2.0\vc2008\bin目錄中;OpenCV的*d.lib檔案(for debug)和*.lib檔案(for release)將出現在D:\Program Files\OpenCV2.0\vc2008\lib目錄;標頭檔案*.h出現在D:\Program Files\OpenCV2.0\vc2008\include\opencv中。
可以被VC++ 2008 Express呼叫的OpenCV動態庫生成完畢
點選看大圖 |
點選看大圖 |
點選看大圖 |
點選看大圖 |
點選看大圖 |
6.配置Windows環境變數Path
將D:\Program Files\OpenCV2.0\vc2008\bin加入Windows系統環境變數Path中。加入後可能需要登出當前Windows使用者(或重啟)後重新登陸才生效。
點選看大圖 |
點選看大圖 |
7.為VC++ 2008 Express配置OpenCV環境
開啟VC++ 2008 Express,選單 Tools -> Options -> Projects and Solutions -> VC++ Directories
- Show directories for選擇executable files,加入目錄 D:\Program Files\OpenCV2.0\vc2008\bin
- Show directories for選擇include files,加入目錄 D:\Program Files\OpenCV2.0\vc2008\include\opencv
- Show directories for選擇library files,加入目錄 D:\Program Files\OpenCV2.0\vc2008\lib
關閉VC++ 2008 Express。
點選看大圖 |
點選看大圖 |
OK,到現在為止呢,我們就配置好了環境可以使用OpenCV來程式設計,下面將介紹如何使用OpenCV,編寫人臉識別的程式碼。
二、人臉識別程式編寫。
1.首先建立一個機遇對話方塊的MFC工程FaceDetection2。
檔案如圖:
2.將對話方塊修改成如圖所示
3.按照如下步驟配置用到的lib
- 選擇Solution Explorer裡的FaceDetection2專案,點選滑鼠右鍵,選擇Properties,在[連結器 LINKER]的[輸入INPUT]中:
- 為專案的Debug配置增加 [依賴的庫 Additional Dependencies]:cxcore200d.lib cv200d.lib highgui200d.lib(注意,檔名cv200d.lib 可能是cv***d.lib等形式,具體應檢視D:\Program Files\OpenCV2.0\vc2008\lib。如果使用的是OpenCV2.1,應輸入:cxcore210d.lib cv210d.lib highgui210d.lib )
- 為專案的Release配置增加[依賴的庫 Additional Dependencies]:cxcore200.lib cv200.lib highgui200.lib (注意:如果使用的是OpenCV2.1,應輸入:cxcore210.lib cv210.lib highgui210.lib)
- 在 [配置屬性 Configuration Properties]- [General] -[字符集 Character Set] 修改為使用“多位元組字符集” (由於2008預設是以Unicode字符集編譯的
4.然後編輯FaceDetection2Dlg.cpp檔案,原始碼如下
// FaceDetection2Dlg.cpp : implementation file
//
#include "stdafx.h"
#include "FaceDetection2.h"
#include "FaceDetection2Dlg.h"
#include <string.h>
#include <iostream>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
using namespace std;
const char* cascade_name="haarcascade_frontalface_alt2.xml";//分類器的名稱
const char* cascade_name1="haarcascade_eye_tree_eyeglasses.xml";//分類器的名稱
const char* cascade_name2="haarcascade_frontalface_alt_tree.xml";//分類器的名稱
const char* cascade_name3="haarcascade_mcs_mouth.xml";//分類器的名稱
const char* cascade_name4="haarcascade_mcs_nose.xml";//分類器的名稱
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CFaceDetection2Dlg dialog
CFaceDetection2Dlg::CFaceDetection2Dlg(CWnd* pParent /*=NULL*/)
: CDialog(CFaceDetection2Dlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CFaceDetection2Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CFaceDetection2Dlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(ID_FaceDetected, &CFaceDetection2Dlg::OnBnClickedFacedetected)
END_MESSAGE_MAP()
// CFaceDetection2Dlg message handlers
BOOL CFaceDetection2Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CFaceDetection2Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CFaceDetection2Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CFaceDetection2Dlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CFaceDetection2Dlg::OnBnClickedFacedetected()
{
// 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_name2, 0, 0, 0 );
//載入不成功則顯示錯誤訊息,並退出
if(cascade)
{
storage = cvCreateMemStorage(0);
cvNamedWindow( "人臉檢測", CV_WINDOW_AUTOSIZE ); //建立視窗
//如果圖片存在則分析並顯示結果,否則退出程式
if(src)
detect_and_draw(src);//呼叫人臉檢與標示事件
cvReleaseImage(&src);
cvReleaseMemStorage( &storage );
}else{
AfxMessageBox(L"無法載入分類器,請確認後重試!");
}
cvReleaseHaarClassifierCascade( &cascade );
}
void CFaceDetection2Dlg::detect_and_draw(IplImage *img)
{
static CvScalar color[] = {{0,0,255},{0,128,255},{0,255,255},{0,255,0},{0,128,255},{255,128,0},{255,255,0},{255,0,0},{255,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[i], 3, 8, 0 );
}
}
cvShowImage( "人臉檢測", img );
cvReleaseImage( &gray );
cvReleaseImage( &small_img );
}
其中OnBnClickedFacedetected()為按鈕FaceDetect的監聽方法
detect_and_draw(IplImage *img)方法用於檢測人臉
5.執行觀察結果
三、總結
在原始碼中,
const char* cascade_name="haarcascade_frontalface_alt2.xml";//分類器的名稱
const char* cascade_name1="haarcascade_eye_tree_eyeglasses.xml";//分類器的名稱
const char* cascade_name2="haarcascade_frontalface_alt_tree.xml";//分類器的名稱
const char* cascade_name3="haarcascade_mcs_mouth.xml";//分類器的名稱
const char* cascade_name4="haarcascade_mcs_nose.xml";//分類器的名稱
這是不同的分類器,你可以在你安裝的OpenCV中找到。如D:\Program Files\OpenCV2.0\vs2008\data\haarcascades
不同分類器能夠幫助你識別不同的部分,如眼睛,鼻子和嘴,更多的需要自己去探索吧。
求分享求推薦。啊
網址:http://blog.renren.com/share/246648717/8171467499