原文:http://blog.csdn.net/mr_curry/article/details/51098311

第一次写博客哈哈,有些小激动,还请各位大神多多包涵~ 
最近的项目需要用到人脸识别,作为一个车辆工程的二年级本科生是崩溃的(一是没有很好的编程基础,只会编一下C与C#;二是…我是车辆工程的啊喂…) 
不过自己还是对计算机视觉这方面还是很感兴趣的,因为做竞赛的缘由,以前多多少少有一点小基础,但要完全做出来还是感觉有些难度。调了一段时间的代码,嘿嘿实现了。这个里面有两点有些“与众不同”(自认为)1.我用Mat代替了IplImage;2.将其用MFC进行表达。(废话少说)接下来贴程序…… 
先说一下我的版本,我是用的VS2013与Opencv2.4.9。首先我们需要在VS中新建一个MFC的框架。

 
 
 
然后点击完成就可以了。接下来我们需要在窗口里面拉几个控件。一个picture control、一个button控件,一个Static Text控件。下面其实是我后来又想做人脸匹配,加了一些功能(好吧我并不会做)。 

修改ID:picture control——–face_picture; 
button——————StartWatch; 
Static Text————-TIME_NEW; 
把我的ID贴出来,方便大家理解。然后就是要为Static Text添加变量,刚开始以为这个和C#的框架差不多,可以直接用什么”label.Text=”,后来才知道先要添加变量,一通乱搞,还翻了书,晕死。 
 
 
 
如图,增添这个我是主要想显示人脸识别的函数运行速度如何,是多少秒。接下来我们双击button控件,进入代码页。 
代码如下:首先是一个你需要引用的头文件:


#include "stdafx.h"
#include "人脸识别与特征匹配.h"
#include "人脸识别与特征匹配Dlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

第二步:

using namespace std;
using namespace cv;
  • 1
  • 2
  • 1
  • 2

然后我们先声明“detectAndDisplay”函数,这里我是用Mat类进行实现,没有用IplImage什么指针的进行实现,一句话,不会管理内存。而后的 haarcascade_frontalface_alt.xml、haarcascade_eye_tree_eyeglasses.xml这两个级联分类器(我也不知道这玩意是不是这么叫的)可以在OpenCV的文件夹里面找到,我是把他们移到了桌面上。

// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
void detectAndDisplay(Mat frame);//声明函数
String face_cascade_name = "C:\\Users\\strstr\\Desktop\\haarcascade_frontalface_alt.xml";//人脸的训练数据
String eyes_cascade_name = "C:\\Users\\strstr\\Desktop\\haarcascade_eye_tree_eyeglasses.xml";//人眼的训练数据
CascadeClassifier face_cascade;
CascadeClassifier eyes_cascade;
string window_name = "人脸识别与检测";
RNG rng(12345);
Mat Allframe;//用于点击button存储照片,同学们可以无视
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

接下来,我将一路贴代码。有一些是MFC预留的,关键的是button里面的内容和detectAndDisplay函数。

class CAboutDlg : public CDialogEx
{ public:
CAboutDlg(); // 对话框数据
enum { IDD = IDD_ABOUTBOX }; protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 // 实现
protected:
DECLARE_MESSAGE_MAP()
}; CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
} void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
} BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP() // C人脸识别与特征匹配Dlg 对话框 C人脸识别与特征匹配Dlg::C人脸识别与特征匹配Dlg(CWnd* pParent /*=NULL*/)
: CDialogEx(C人脸识别与特征匹配Dlg::IDD, pParent)
, face_time(_T(""))
, face_name(_T(""))
, face_no_name(_T(""))
, face_time_new(0)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
} void C人脸识别与特征匹配Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, TIME, face_time);
DDX_Text(pDX, Result, face_name);
DDX_Text(pDX, THEname, face_no_name);
DDX_Text(pDX, TIME_NEW, face_time_new);
} BEGIN_MESSAGE_MAP(C人脸识别与特征匹配Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(StartWatch, &C人脸识别与特征匹配Dlg::OnBnClickedStartwatch)
ON_BN_CLICKED(face_read, &C人脸识别与特征匹配Dlg::OnBnClickedread) ON_BN_CLICKED(face_openvideo, &C人脸识别与特征匹配Dlg::OnBnClickedopenvideo)
ON_BN_CLICKED(Save, &C人脸识别与特征匹配Dlg::OnBnClickedSave)
END_MESSAGE_MAP() // C人脸识别与特征匹配Dlg 消息处理程序 BOOL C人脸识别与特征匹配Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog(); // 将“关于...”菜单项添加到系统菜单中。 // IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
} // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标 // TODO: 在此添加额外的初始化代码 return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
} void C人脸识别与特征匹配Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
} // 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。 void C人脸识别与特征匹配Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文 SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0); // 使图标在工作区矩形中居中
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; // 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
} //当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR C人脸识别与特征匹配Dlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151

以下是Button里的代码:

void C人脸识别与特征匹配Dlg::OnBnClickedStartwatch()
{
face_time = "秒";
double t = 0;
double facelook_time = 0;//用于计算函数运行时间
VideoCapture capture(1);//捕获外部摄像头
Mat frame,newframe;//建立两个Mat,一个用来显示视频,另一个给全局里的Allframe
namedWindow("view", WINDOW_AUTOSIZE);
HWND hWnd = (HWND)cvGetWindowHandle("view");
HWND hParent = ::GetParent(hWnd);
::SetParent(hWnd, GetDlgItem(face_picture)->m_hWnd);
::ShowWindow(hParent, SW_HIDE);//隐藏运行程序框,并且把它“画”到MFC上
if (!face_cascade.load(face_cascade_name)){ printf("--(!)Error loading\n");};
if (!eyes_cascade.load(eyes_cascade_name)){ printf("--(!)Error loading\n");};//加载分类器的
if (capture.isOpened())
{
for (;;)//循环以达到视频的效果
{
capture >> frame;
capture >> newframe;
Allframe = newframe;
if (!frame.empty())
{ t = (double)cvGetTickCount();
detectAndDisplay(frame);//识别的函数
t = (double)cvGetTickCount() - t;//用来计算算法执行时间
facelook_time = t / 1000 / ((double)cvGetTickFrequency()*1000.);//检测时间
face_time_new = facelook_time;//输出到static text中
imshow("view", frame);
UpdateData(FALSE);
}
else
{
printf(" --(!) No captured frame -- Break!"); break;
} waitKey(10);
} }
}
void detectAndDisplay(Mat frame)//识别人脸函数
{
std::vector<Rect> faces;
Mat frame_gray;
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);//转换成灰度图像
equalizeHist(frame_gray, frame_gray);//直方图均衡化
//1.1表示每次图像尺寸减小的比例为1.1,2表示每一个目标至少要被检测到3次才算是真的目标(因为周围的像素和不同的窗口大小都可以检测到人脸),CV_HAAR_SCALE_IMAGE表示不是缩放分类器来检测,而是缩放图像,Size(30, 30)为目标的最小最大尺寸
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30)); for (size_t i = 0; i < faces.size(); i++)
{
Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2);
ellipse(frame, center, Size(faces[i].width / 2, faces[i].height / 2), 0, 0, 360, Scalar(255, 0, 255), 2, 8, 0);//画椭圆 Mat faceROI = frame_gray(faces[i]);
std::vector<Rect> eyes; //-- In each face, detect eyes
eyes_cascade.detectMultiScale(faceROI, eyes, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30)); for (size_t j = 0; j < eyes.size(); j++)//检测眼睛
{
Point eye_center(faces[i].x + eyes[j].x + eyes[j].width / 2, faces[i].y + eyes[j].y + eyes[j].height / 2);
int radius = cvRound((eyes[j].width + eyes[j].height)*0.25);
circle(frame, eye_center, radius, Scalar(255, 0, 0), 3, 8, 0);
}
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

好了,贴一张运行成功的截图,怕丑到各位,打了些马赛克:

最新文章

  1. [LeetCode] Generalized Abbreviation 通用简写
  2. 样式重置 css reset
  3. eclipse中Maven创建WEB项目
  4. 文件打包,下载之使用PHP自带的ZipArchive压缩文件并下载打包好的文件
  5. 关于android的UI更新机制与误区
  6. PHP 记录日志
  7. dependency of static library
  8. UVa 11998 Broken Keyboard (数组模拟链表问题)
  9. selenium源码分析-webdriver(二)
  10. 《STL系列》之vector原理及实现
  11. [转载] 分享D瓜哥最近攒的资料(架构方面)
  12. php正则过滤html标签、空格、换行符的代码,提取图片
  13. Properties --- C++读配置信息的类(一)
  14. Mac Sublime text3 如何设置更加漂亮好用?
  15. 学习python的第三天
  16. 在vue中使用watch监听对象或数组
  17. Chapter 4 Invitations——3
  18. 虚拟机克隆之后,网卡名称从eth0变成eth1之后的解决办法
  19. 基于Gogs+Drone搭建的私有CI/CD平台
  20. mysql 之mvcc多版本控制

热门文章

  1. 【算法笔记】B1040 有几个PAT
  2. CDQZ Day6
  3. Flask基础应用
  4. python四则运算2.0
  5. golang笔记
  6. 爬虫--XPATH解析
  7. 一个数字键盘引发的血案——移动端H5输入框、光标、数字键盘全假套件实现
  8. div+css 制作表格
  9. Android下so注入和hook
  10. Python基础(2) - 动态数据类型