MFC中利用Opencv与C++抓取摄像头进行人脸识别(Mat)
原文: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
好了,贴一张运行成功的截图,怕丑到各位,打了些马赛克:
MFC中利用Opencv与C++抓取摄像头进行人脸识别(Mat)的更多相关文章
- 如何利用Python网络爬虫抓取微信朋友圈的动态(上)
今天小编给大家分享一下如何利用Python网络爬虫抓取微信朋友圈的动态信息,实际上如果单独的去爬取朋友圈的话,难度会非常大,因为微信没有提供向网易云音乐这样的API接口,所以很容易找不到门.不过不要慌 ...
- 在python3下使用OpenCV 抓取摄像头图像并实时显示3色直方图
以下代码为在Python3环境下利用OpenCV 抓取摄像头的实时图像, 通过OpenCV的 calHist函数计算直方图, 并显示在3个不同窗口中. import cv2 import numpy ...
- 利用Python网络爬虫抓取微信好友的签名及其可视化展示
前几天给大家分享了如何利用Python词云和wordart可视化工具对朋友圈数据进行可视化,利用Python网络爬虫抓取微信好友数量以及微信好友的男女比例,以及利用Python网络爬虫抓取微信好友的所 ...
- 利用Python网络爬虫抓取微信好友的所在省位和城市分布及其可视化
前几天给大家分享了如何利用Python网络爬虫抓取微信好友数量以及微信好友的男女比例,感兴趣的小伙伴可以点击链接进行查看.今天小编给大家介绍如何利用Python网络爬虫抓取微信好友的省位和城市,并且将 ...
- 如何利用Python网络爬虫抓取微信好友数量以及微信好友的男女比例
前几天给大家分享了利用Python网络爬虫抓取微信朋友圈的动态(上)和利用Python网络爬虫爬取微信朋友圈动态——附代码(下),并且对抓取到的数据进行了Python词云和wordart可视化,感兴趣 ...
- 利用python scrapy 框架抓取豆瓣小组数据
因为最近在找房子在豆瓣小组-上海租房上找,发现搜索困难,于是想利用爬虫将数据抓取. 顺便熟悉一下Python. 这边有scrapy 入门教程出处:http://www.cnblogs.com/txw1 ...
- php中CURL技术模拟登陆抓取数据实战,抓取某校教务处学生成绩。
这两天有基友要php中curl抓取教务处成绩的源码,用于微信公众平台的开发.下面笔者只好忍痛割爱了.php中CURL技术模拟登陆抓取数据实战,抓取沈阳工学院教务处学生成绩. 首先,教务处登录需要验证码 ...
- Android利用tcpdump和wireshark抓取网络数据包
Android利用tcpdump和wireshark抓取网络数据包 主要介绍如何利用tcpdump抓取andorid手机上网络数据请求,利用Wireshark可以清晰的查看到网络请求的各个过程包括三次 ...
- python之OpenCv(五)---抓取摄像头视频图像
OpenCV 可以通过 头videoCapture()方法打开摄像 摄像头变量 = cv2.VideoCapture(n) n为整数,内置摄像头为0,若有其他摄像头则依次为1,2,3,4,... ...
随机推荐
- JavaScript对象基础知识总结
1.什么叫JavaScript对象? 定义:名值对的集合.简单的讲就是容纳属性值和属性值的容器,这些属性可以是无序的,基本上JavaScript中所有的事物都可以看成对象. 拓展:我们经常说,数组也是 ...
- 快速修改数据库日志的增长修改为50M[转]
尚未亲测..请君慎重使用.. SET NOCOUNT ON ), @sqlTotal NVARCHAR(MAX),@sqlSingle NVARCHAR(MAX),@sql NVARCHAR(MAX) ...
- OpenStack Neutron配置虚拟机访问外网
配置完成后的网络拓扑如下: 当前环境: X86服务器1台 Ubuntu 16.04 DevStack搭建OpenStack 网络拓扑: 外部网络:192.168.98.0/24 内部网络:10.0.0 ...
- (转)虚拟路由器冗余协议【原理篇】VRRP详解
原文:http://blog.51cto.com/zhaoyuqiang/1166840 为什么要使用VRRP技术 我们知道,为了实现不同子网之间的设备通信,需要配置路由.目前常用的指定路由方法有两种 ...
- c++ 网络编程(六)LINUX下 socket编程 多播与广播 实现一次发送所有组客户端都能接收到
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9614288.html 一.多播 锲子:有这么一种情况,网络电台可能需要同时向成千上万的用户传输 ...
- cg教程
Unity对shader的重点支持是cg语言,因为具有跨平台性质 Cg语言和CPU 上的C语言是很相似的,只不过有了自己的一套关键字和函数库 Cg语言的权威和入门教程在NVID1A的官方网站上,如果以 ...
- vue 坑之 vuex requires a Promise polyfill in this browser
android内嵌H5页面不显示出现这个问题,原因有很多 首先,别急,请看下面的推荐方案: 1.找个Android真机测试下(机型版本为4.4以上),真机联调测试 Android 只需要四个步骤: 1 ...
- Hibernate中的CRUD操作
1.添加数据操作 插入数据使用session对象的save()方法完成. 插入代码: @Test public void Test1(){ SessionFactory sessionFactor ...
- MySQL之函数
了解编程的人一般都会知道函数的重要性,丰富的函数有的时候可以给我们带来事半功倍的效果,在MySQL中提供了许多的内置函数,能够帮助开发人员编写简单快捷的SQL语句,除了这些内置的函数之外,用户也可以自 ...
- SP16580 QTREE7 - Query on a tree VII
Description 一棵树,每个点初始有个点权和颜色(0/1) 0 u :询问所有u,v 路径上的最大点权,要满足u,v 路径上所有点的颜色都相同 1 u :反转u 的颜色 2 u w :把u 的 ...