基于开源项目OpenCV的人脸识别Demo版整理(不仅可以识别人脸,还可以识别眼睛鼻子嘴等)【模式识别中的翘楚】

来源:互联网 发布:算法竞赛网站 编辑:程序博客网 时间:2024/04/28 00:01

转载自http://blog.renren.com/share/246648717/8171467499

最近对人脸识别的程序非常感兴趣,但是苦于没有选修多媒体方向,看了几篇关于人脸识别的论文,大概也没看懂多少,什么灰度处理啊,切割识别啊,云里雾里,傻傻看不明白啊。各种苦恼。

    于是就在网上找找,看有木有神马开源代码啊,要是有个现成的源码就更好了,百度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

安装CMakehttp://www.cmake.org/cmake/resources/software.html;

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

不同分类器能够帮助你识别不同的部分,如眼睛,鼻子和嘴,更多的需要自己去探索吧。

求分享求推荐。啊

 



0 0
原创粉丝点击