1. 程式人生 > >基於開源專案OpenCV的人臉識別Demo版整理(不僅可以識別人臉,還可以識別眼睛鼻子嘴等)

基於開源專案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已經足夠用了。下載地址

http://www.opencv.org.cn/index.php/Download

下載後安裝,我安裝在了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時可以不管這個選項。

點選看大圖

Enlarge

點選看大圖

點選看大圖

Enlarge

點選看大圖

點選看大圖

Enlarge

點選看大圖

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動態庫生成完畢

點選看大圖

Enlarge

點選看大圖

點選看大圖

Enlarge

點選看大圖

點選看大圖

Enlarge

點選看大圖

點選看大圖

Enlarge

點選看大圖

點選看大圖

Enlarge

點選看大圖

6.配置Windows環境變數Path

將D:\Program Files\OpenCV2.0\vc2008\bin加入Windows系統環境變數Path中。加入後可能需要登出當前Windows使用者(或重啟)後重新登陸才生效。

點選看大圖

Enlarge

點選看大圖

點選看大圖

Enlarge

點選看大圖

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。

點選看大圖

Enlarge

點選看大圖

點選看大圖

Enlarge

點選看大圖

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