文章来自于:http://blog.renren.com/share/246648717/8171467499

基于开源项目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

安装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时可以不管这个选项。

点击看大图

点击看大图

点击看大图

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

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

求分享求推荐。啊

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

  1. 基于开源项目SharpMap的热力图(HeatLayer)实现。

    当前公司需要一个用时较少的热力图呈现方案,在避免较底层的GDI开发和比较了多家GIS产品的实际效果之后,团队决定用sharpMap的API来实现,由于之前框架采用的是另外一个开源项目GMap.net, ...

  2. 活动报名 | 如何基于开源项目 Tapdata PDK,快速完成数据源和目标的开发?

      近日,Tapdata 启动 PDK 插件生态共建计划,宣布开源插件开发框架 Tapdata PDK,将自身的数据接口能力开放出来,帮助开发者根据实际需求,自助接入数据源和目标,快速开启「Data ...

  3. 基于开源项目的在线网络视频直播项目---一个很好的电视直播开源项目Sopcast

    http://blog.csdn.net/roy_xu/article/details/2216559 http://115.com/?ct=rar&pickcode=ew52634xr2cr ...

  4. 基于开源项目的在线网络视频直播项目---pc端的推流

    https://github.com/winlinvip/simple-rtmp-server/issues/66 https://github.com/justinmakaila/iOS-Frame ...

  5. C#开源项目

    原文:  http://alance.iteye.com/blog/693987 一.AOP框架        Encase 是C#编写开发的为.NET平台提供的AOP框架.Encase 独特的提供了 ...

  6. 15个具有高度影响力的Apache开源项目

    自1999年创立以来,Apache软件基金会如今已成了众多重要的开源软件项目之家.其中成功的项目有Geronimo,有Tomcat,有Hadoop,有如今成了大数据王国关键车毂的分布式计算系统. 虽然 ...

  7. c#开源项目[转]

    一.AOP框架 Encase 是C#编写开发的为.NET平台提供的AOP框架.Encase 独特的提供了把方面(aspects)部署到运行时代码,而其它AOP框架依赖配置文件的方式.这种部署方面(as ...

  8. 程序员必备,C#各类项目、开源项目插件资料收藏

    一.AOP框架     Encase 是C#编写开发的为.NET平台提供的AOP框架.Encase独特的提供了把方面(aspects)部署到运行时代码,而其它AOP框架依赖配置文件的方式.这种部署方面 ...

  9. Redis开源项目的终极杀手? ——CRUG解读Redis开源协议变更

    引言: 数据库制造商 Redis Labs 本周将公司开发的Redis 模块从 AGPL 迁移到将 Apache v2.0 与 Commons Clause 相结合的许可证,对许可证涵盖的软件作了限制 ...

随机推荐

  1. FSharp.Data 程序集之 Http

    FSharp.Data 程序集之 Http (** # F# Data: HTTP Utilities .NET 库提供了强大的 API,产生和发送 HTTP WEB 请求,有两个类型,一个简单,`W ...

  2. X Window、GNOME和KDE之间的关系

    原文地址:http://blog.csdn.net/jincf2011/article/details/6362923 X Window, 即X Windows图形用户接口,它并不是一个软件,而是一个 ...

  3. 用endsWith()来限制图片的后缀名

    var a=document.getElementById('file-name'); var filename=a.value if(!a.endsWith('.jpg')||!a.endsWith ...

  4. 关于scanf的几种处理方法

    字符输入中,赋值顺序和缓存的联系 scanf是从标准输入缓冲区中读取输入的数据,假设连续输入两个%c格式的字符.而中间又要涉及回车,那么第二个字符将被赋予回车. 解决的方法: .清空输入缓冲区 第一个 ...

  5. 混血儿爹妈要混的远,数据库与WEB分离,得混的近

    最近搞了个漫画网站,放在香港VPS,由于内存不够,把数据库移到了阿里云,混的远了点,没缓存的时候网站打开速度慢了1秒左右.笨狗漫画:http://www.bengou8.com 底部有sql时间cop ...

  6. 初探swift语言的学习笔记四(类对象,函数)

    作者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/29606137 转载请注明出处 假设认为文章对你有所帮助,请通过留言 ...

  7. Example of how to use both JDK 7 and JDK 8 in one build.--reference

    JDK 8 Released Most of us won’t be able to use/deploy JDK 8 in production for a looong time. But tha ...

  8. [转] linux 信号量之SIGNAL

    我们可以使用kill -l查看所有的信号量解释,但是没有看到SIGNAL 0的解释. [root@testdb~]# kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) ...

  9. hdu 1880 字符串hash

    /*普通的hsah 由于元素太多 空间很小..hash碰撞很厉害.30分*/ #include<iostream> #include<cstdio> #include<c ...

  10. Linux命令之 文件归档管理

    1.文件相关知识 Linux怎样保存文件 数据 -这里数据就是文件的内容 元数据 -在linux系统中,所有与某个文件相关的额外信息都保存在一个叫做i-节点(inode)的节构中 文件名 -文件名保存 ...