文章来自于: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
不同分类器能够帮助你识别不同的部分,如眼睛,鼻子和嘴,更多的需要自己去探索吧。
求分享求推荐。啊