- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章基于OpenCV读取摄像头实现单个人脸验证MFC程序由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
与上一篇博客类似,这篇博客介绍使用OpenCV实现的MFC程序,可以实现单个人脸的验证,并在图像和界面给出识别结果。效果图如下:
置信度一栏可以填写判定的阈值,默认为70。打开摄像头才能进行验证或拍照,拍照之前可以清除之前拍摄的训练图片,可以拍摄多张用于识别。其中mfc中的图像显示需要用到CvImage.cpp和CvImage.h两个文件,该代码在比较新的OpenCV内已经没有了,所以可以直接用我代码里的.
有人说代码的检测率不高,其实可以归结为两方面的原因,第一人脸检测率不高,这个可以通过嵌套检测嘴角、眼睛等来降低,或者背景、光照固定的话可以通过图像差分来解决;第二是识别方法本身的问题,如果想提高识别率,可以添加多张不同姿态、光照下的人脸作为训练的样本,如果有时间的话可以在采集图像时给出一个人脸框,引导用户对齐人脸进行采集,三星手机解除锁屏就有这么一个功能.
下面贴一下主要的代码:
VideoMFCDlg.cpp 。
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
|
// VideoMFCDlg.cpp : implementation file
//
#include "stdafx.h"
#include "VideoMFC.h"
#include "VideoMFCDlg.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CvCapture* capture;
CRect rect;
CDC *pDC;
HDC
hDC;
CWnd *pwnd;
CvVideoWriter* writer = 0;
IplImage *resizeRes;
//存放检测到的人脸
IplImage* faceGray;
//存放检测到的人脸 灰度图像
bool
bool_cameOpen =
false
;
//全局变量 标志摄像头是否打开
bool
bool_picNum =
false
;
//全局变量 标志训练图片是否为空
bool
bool_detec_reco =
false
;
//全局变量
double
dConfidence = 0;
//置信度
int
predictedLabel = 100000;
CvMemStorage* storage = 0;
CvHaarClassifierCascade* cascade = 0;
CvHaarClassifierCascade* nested_cascade = 0;
int
use_nested_cascade = 0;
const
char
* cascade_name =
"../data/haarcascades/haarcascade_frontalface_alt.xml"
;
const
char
* nested_cascade_name =
"../data/haarcascade_eye_tree_eyeglasses.xml"
;
double
scale = 1;
int
num_components = 9;
double
facethreshold = 9.0;
//cv::Ptr<cv::FaceRecognizer> model = cv::createFisherFaceRecognizer();
cv::Ptr<cv::FaceRecognizer> model = cv::createLBPHFaceRecognizer();
//LBP的这个方法在单个人脸验证方面效果最好
//cv::Ptr<cv::FaceRecognizer> model = cv::createEigenFaceRecognizer();
vector<Mat> images;
vector<
int
> labels;
IplImage *frame, *frame_copy = 0;
IplImage *image = 0;
const
char
* scale_opt =
"--scale="
;
// 分类器选项指示符号
int
scale_opt_len = (
int
)
strlen
(scale_opt);
const
char
* cascade_opt =
"--cascade="
;
int
cascade_opt_len = (
int
)
strlen
(cascade_opt);
const
char
* nested_cascade_opt =
"--nested-cascade"
;
int
nested_cascade_opt_len = (
int
)
strlen
(nested_cascade_opt);
int
i;
const
char
* input_name = 0;
// CAboutDlg dialog used for App About
CString strConfidence =
"70"
;
CEdit* pEdtConfidence;
CString strTip =
""
;
CEdit* pTip;
class
CAboutDlg :
public
CDialogEx
{
public
:
CAboutDlg();
// Dialog Data
enum
{ IDD = IDD_ABOUTBOX };
protected
:
virtual
void
DoDataExchange(CDataExchange* pDX);
// DDX/DDV support
// Implementation
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()
// CVideoMFCDlg dialog
CVideoMFCDlg::CVideoMFCDlg(CWnd* pParent
/*=NULL*/
)
: CDialogEx(CVideoMFCDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void
CVideoMFCDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CVideoMFCDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CVideoMFCDlg::OnBnClickedButton1)
ON_WM_TIMER()
ON_BN_CLICKED(IDC_BUTTON2, &CVideoMFCDlg::OnBnClickedButton2)
ON_WM_CLOSE()
ON_EN_CHANGE(IDC_EdtConfidence, &CVideoMFCDlg::OnEnChangeEdtconfidence)
ON_BN_CLICKED(IDC_Photograph, &CVideoMFCDlg::OnBnClickedPhotograph)
ON_BN_CLICKED(IDC_Recognize, &CVideoMFCDlg::OnBnClickedRecognize)
ON_BN_CLICKED(IDC_ClearPictures, &CVideoMFCDlg::OnBnClickedClearpictures)
END_MESSAGE_MAP()
// CVideoMFCDlg message handlers
BOOL
CVideoMFCDlg::OnDestroy()
{
cvReleaseImage( &resizeRes );
cvReleaseImage( &faceGray );
return
TRUE;
}
BOOL
CVideoMFCDlg::OnInitDialog()
{
CDialogEx::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)
{
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);
}
}
// 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
pwnd = GetDlgItem(IDC_ShowImage);
//pwnd->MoveWindow(35,30,352,288);
pDC =pwnd->GetDC();
//pDC =GetDC();
hDC= pDC->GetSafeHdc();
pwnd->GetClientRect(&rect);
GetDlgItem(IDC_BUTTON2)->EnableWindow(
false
);
GetDlgItem(IDC_Photograph)->EnableWindow(
false
);
GetDlgItem(IDC_Recognize)->EnableWindow(
false
);
pEdtConfidence = (CEdit*) GetDlgItem(IDC_EdtConfidence);
pTip = (CEdit*) GetDlgItem(IDC_Tip);
pEdtConfidence->SetWindowText(
"70"
);
pEdtConfidence->GetWindowText(strConfidence);
pTip->SetWindowText( strTip );
if
(read_img_number()>0)
bool_picNum =
true
;
else
bool_picNum =
false
;
return
TRUE;
// return TRUE unless you set the focus to a control
}
void
CVideoMFCDlg::OnSysCommand(
UINT
nID,
LPARAM
lParam)
{
if
((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::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
CVideoMFCDlg::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
{
CDialogEx::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR
CVideoMFCDlg::OnQueryDragIcon()
{
return
static_cast
<
HCURSOR
>(m_hIcon);
}
/*****************************************打开摄像头*******************************************/
void
CVideoMFCDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
//AfxMessageBox("OK");
if
(!capture)
{
capture = cvCaptureFromCAM(0);
//AfxMessageBox("OK");
}
if
(!capture)
{
AfxMessageBox(
"无法打开摄像头"
);
return
;
}
//writer=cvCreateVideoWriter("MyVideo.avi",CV_FOURCC('x','v','I','D'),25,cvSize(640,480));
// 测试
IplImage* m_Frame;
m_Frame=cvQueryFrame(capture);
CvvImage m_CvvImage;
m_CvvImage.CopyOf(m_Frame,1);
if
(
true
)
{
m_CvvImage.DrawToHDC(hDC, &rect);
//cvWaitKey(10);
}
// 设置计时器,每10ms触发一次事件
SetTimer(1,10,NULL);
cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
// 加载分类器
if
( !cascade )
{
MessageBox(
"无法加载分类器文件,请确认!"
);
}
storage = cvCreateMemStorage(0);
// 创建内存存储器
//if( !input_name || (isdigit(input_name[0]) && input_name[1] == '\0') ) // 判断输入参数是视频序号,还是文件
capture = cvCaptureFromCAM( !input_name ? 0 : input_name[0] -
'0'
);
// 创建视频读取结构
/*
else if( input_name )
{
image = cvLoadImage( input_name, 1 ); // 如果是图像则加载
if( !image )
{
capture = cvCaptureFromAVI( input_name ); // 不是图像则尝试视频读取
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 640);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 480); ////////////////////////////////////////////////////////////////////
}
}*/
//else
// image = cvLoadImage( "lena.bmp", 1 ); //都没有则调用程序所在目录的lena.jpg图片
//cvNamedWindow( "result", 1 );
GetDlgItem(IDC_BUTTON1)->EnableWindow(
false
);
GetDlgItem(IDC_BUTTON2)->EnableWindow(
true
);
GetDlgItem(IDC_Photograph)->EnableWindow(
true
);
GetDlgItem(IDC_Recognize)->EnableWindow(
true
);
bool_detec_reco =
false
;
bool_cameOpen =
true
;
}
/********************************************设置定时器*********************************************/
void
CVideoMFCDlg::OnTimer(
UINT_PTR
nIDEvent)
{
//显示摄像头
IplImage* m_Frame;
m_Frame=cvQueryFrame(capture);
//AllocConsole();
//判断是检测还是识别人脸
if
(bool_cameOpen)
{
if
(!bool_detec_reco)
//false只为识别
{
detect_and_draw(m_Frame);
//检测人脸
//_cprintf("%s\n", "jiance");
}
else
if
(bool_picNum)
//false代表训练图片为空
recog_and_draw(m_Frame);
//检测和识别人脸
}
CvvImage m_CvvImage;
m_CvvImage.CopyOf(m_Frame,1);
if
(
true
)
{
m_CvvImage.DrawToHDC(hDC, &rect);
//cvWriteFrame(writer,m_Frame); //将帧图像通过writer写入文件
//cvWaitKey(10);
}
if
(bool_detec_reco)
{
if
(predictedLabel <= dConfidence)
{
CString tipPhoto = strTip +
"\r\n验证成功!!"
;
pTip->SetWindowText( tipPhoto );
}
else
{
CString tipPhoto = strTip +
"\r\n验证失败!!"
;
pTip->SetWindowText( tipPhoto );
}
}
CDialogEx::OnTimer(nIDEvent);
}
//关闭摄像头按钮
void
CVideoMFCDlg::OnBnClickedButton2()
{
// TODO: Add your control notification handler code here
cvReleaseVideoWriter(&writer);
cvReleaseCapture(&capture);
CDC MemDC;
CBitmap m_Bitmap1;
m_Bitmap1.LoadBitmap(IDB_BITMAP1);
MemDC.CreateCompatibleDC(NULL);
MemDC.SelectObject(&m_Bitmap1);
pDC->StretchBlt(rect.left,rect.top,rect.Width(),rect.Height(),&MemDC,0,0,48,48,SRCCOPY);
GetDlgItem(IDC_BUTTON1)->EnableWindow(
true
);
GetDlgItem(IDC_BUTTON2)->EnableWindow(
false
);
GetDlgItem(IDC_Photograph)->EnableWindow(
false
);
GetDlgItem(IDC_Recognize)->EnableWindow(
false
);
bool_cameOpen =
false
;
}
//关闭窗体
void
CVideoMFCDlg::OnClose()
{
// TODO: Add your message handler code here and/or call default
cvReleaseCapture(&capture);
CDialogEx::OnClose();
}
void
CVideoMFCDlg::OnEnChangeEdtconfidence()
{
}
//拍照按钮
void
CVideoMFCDlg::OnBnClickedPhotograph()
{
// TODO: 在此添加控件通知处理程序代码
if
(!faceGray)
{
pTip->GetWindowText(strTip);
CString tipPhoto = strTip +
"\r\n拍照失败,请将摄像头对准人脸"
;
pTip->SetWindowText( tipPhoto );
return
;
}
Mat img(faceGray,0);
stringstream ss;
ss << (read_img_number()+1);
string faceImgName =
"..//einfacedata//trainingdata//"
+ss.str()+
".jpg"
;
imwrite(faceImgName,img);
//pTip->GetWindowText(strTip);
CString tipPhoto = strTip +
"\r\n拍照成功!已存为"
+ (
"/einfacedata/trainingdata/"
+ss.str()+
".jpg"
).c_str();
pTip->SetWindowText( tipPhoto );
//MessageBox("OK");
}
//开始验证按钮
void
CVideoMFCDlg::OnBnClickedRecognize()
{
// TODO: 在此添加控件通知处理程序代码
images.clear();
labels.clear();
pEdtConfidence->GetWindowText(strConfidence);
try
{
dConfidence =
atoi
((
const
char
*)strConfidence);
}
catch
(cv::Exception &e)
{
MessageBox(
"置信度请输入整数!"
);
return
;
}
model->set(
"threshold"
, dConfidence);
//string output_folder;
//output_folder = string("../einfacedata");
//读取你的CSV文件路径
//string fn_csv = string("../einfacedata/at.txt");
//两个容器来存放图像数据和对应的标签
/*
try
{
read_csv(fn_csv, images, labels);
}
catch(cv::Exception &e)
{
cerr<<"Error opening file "<<fn_csv<<". Reason: "<<e.msg<<endl;
exit(1);
}
*/
if
(!read_img(images, labels))
{
AfxMessageBox(
"Error in reading images!"
);
//MessageBox("Error in reading images!");
images.clear();
labels.clear();
return
;
}
//如果没有读到足够的图片,就退出
if
(images.size() < 1)
{
MessageBox(
"This demo needs at least 1 images to work!"
);
return
;
}
//training
model->train(images, labels);
bool_detec_reco =
true
;
bool_picNum =
true
;
}
//清除训练图片
void
CVideoMFCDlg::OnBnClickedClearpictures()
{
// TODO: 在此添加控件通知处理程序代码
if
(delete_img())
{
//pTip->GetWindowText(strTip);
CString tipPhoto = strTip +
"\r\n删除成功!"
;
pTip->SetWindowText( tipPhoto );
bool_detec_reco =
false
;
bool_picNum =
false
;
}
else
{
//pTip->GetWindowText(strTip);
CString tipPhoto = strTip +
"\r\n删除失败!"
;
pTip->SetWindowText( tipPhoto );
}
}
|
detect_recog.cpp和上一篇博客类似 。
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
|
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <time.h>
#include <ctype.h>
#include "detect_recog.h"
#include <opencv2\contrib\contrib.hpp>
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <io.h>
#include <direct.h>
#include <sys/types.h>
#include <conio.h>
using
namespace
std;
using
namespace
cv;
void
detect_and_draw( IplImage* img )
// 只是检测,并圈出人脸
{
static
CvScalar colors[] =
{
{{0,0,255}},
{{0,128,255}},
{{0,255,255}},
{{0,255,0}},
{{255,128,0}},
{{255,255,0}},
{{255,0,0}},
{{255,0,255}}
};
IplImage *gray, *small_img;
int
i, j;
gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );
small_img = cvCreateImage( cvSize( cvRound (img->width/scale),
cvRound (img->height/scale)), 8, 1 );
cvCvtColor( img, gray, CV_BGR2GRAY );
// 彩色RGB图像转为灰度图像
cvResize( gray, small_img, CV_INTER_LINEAR );
cvEqualizeHist( small_img, small_img );
// 直方图均衡化
cvClearMemStorage( storage );
if
( cascade )
{
double
t = (
double
)cvGetTickCount();
CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
1.1, 2, 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
|CV_HAAR_DO_ROUGH_SEARCH
//|CV_HAAR_DO_CANNY_PRUNING
//|CV_HAAR_SCALE_IMAGE
,
cvSize(30, 30) );
t = (
double
)cvGetTickCount() - t;
// 统计检测使用时间
//printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
for
( i = 0; i < (faces ? faces->total : 0); i++ )
{
CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
// 将faces数据从CvSeq转为CvRect
CvMat small_img_roi;
CvSeq* nested_objects;
CvPoint center,recPt1,recPt2;
CvScalar color = colors[i%8];
// 使用不同颜色绘制各个face,共八种色
int
radius;
center.x = cvRound((r->x + r->width*0.5)*scale);
// 找出faces中心
center.y = cvRound((r->y + r->height*0.5)*scale);
recPt1.x = cvRound((r->x)*scale);
recPt1.y = cvRound((r->y)*scale);
recPt2.x = cvRound((r->x + r->width)*scale);
recPt2.y = cvRound((r->y + r->height)*scale);
radius = cvRound((r->width + r->height)*0.25*scale);
cvGetSubRect( small_img, &small_img_roi, *r );
IplImage *result;
CvRect roi;
roi = *r;
result = cvCreateImage( cvSize(r->width, r->height), img->depth, img->nChannels );
cvSetImageROI(img,roi);
// 创建子图像
cvCopy(img,result);
cvResetImageROI(img);
//IplImage *resizeRes;
CvSize dst_cvsize;
dst_cvsize.width=(
int
)(100);
dst_cvsize.height=(
int
)(100);
resizeRes=cvCreateImage(dst_cvsize,result->depth,result->nChannels);
cvResize(result,resizeRes,CV_INTER_NN);
faceGray = cvCreateImage(cvGetSize(resizeRes), IPL_DEPTH_8U, 1);
//创建目标图像
cvCvtColor(resizeRes,faceGray,CV_BGR2GRAY);
//cvCvtColor(src,des,CV_BGR2GRAY)
cvShowImage(
"resize"
, resizeRes );
cvRectangle(img,recPt1,recPt2,color,1, 8,0);
//rectangle(img,recPt1,recPt2,color,1,8,0);
//cvCircle( img, center, radius, color, 3, 8, 0 ); // 从中心位置画圆,圈出脸部区域
if
( !nested_cascade )
continue
;
nested_objects = cvHaarDetectObjects( &small_img_roi, nested_cascade, storage,
1.1, 2, 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
//|CV_HAAR_DO_CANNY_PRUNING
//|CV_HAAR_SCALE_IMAGE
,
cvSize(0, 0) );
for
( j = 0; j < (nested_objects ? nested_objects->total : 0); j++ )
{
CvRect* nr = (CvRect*)cvGetSeqElem( nested_objects, j );
center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);
center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);
radius = cvRound((nr->width + nr->height)*0.25*scale);
cvCircle( img, center, radius, color, 3, 8, 0 );
}
}
}
//cvShowImage( "result", img );
cvReleaseImage( &gray );
cvReleaseImage( &small_img );
}
//检测并识别人脸,并在每帧图片上写入结果
void
recog_and_draw( IplImage* img )
{
static
CvScalar colors[] =
{
{{0,0,255}},
{{0,128,255}},
{{0,255,255}},
{{0,255,0}},
{{255,128,0}},
{{255,255,0}},
{{255,0,0}},
{{255,0,255}}
};
IplImage *gray, *small_img;
int
i, j;
gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 );
small_img = cvCreateImage( cvSize( cvRound (img->width/scale),
cvRound (img->height/scale)), 8, 1 );
cvCvtColor( img, gray, CV_BGR2GRAY );
// 彩色RGB图像转为灰度图像
cvResize( gray, small_img, CV_INTER_LINEAR );
cvEqualizeHist( small_img, small_img );
// 直方图均衡化
cvClearMemStorage( storage );
if
( cascade )
{
double
t = (
double
)cvGetTickCount();
CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
1.1, 2, 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
|CV_HAAR_DO_CANNY_PRUNING
//|CV_HAAR_SCALE_IMAGE
,
cvSize(30, 30) );
t = (
double
)cvGetTickCount() - t;
// 统计检测使用时间
//printf( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) );
for
( i = 0; i < (faces ? faces->total : 0); i++ )
{
CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
// 将faces数据从CvSeq转为CvRect
CvMat small_img_roi;
CvSeq* nested_objects;
CvPoint center,recPt1,recPt2;
CvScalar color = colors[i%8];
// 使用不同颜色绘制各个face,共八种色
int
radius;
center.x = cvRound((r->x + r->width*0.5)*scale);
// 找出faces中心
center.y = cvRound((r->y + r->height*0.5)*scale);
recPt1.x = cvRound((r->x)*scale);
recPt1.y = cvRound((r->y)*scale);
recPt2.x = cvRound((r->x + r->width)*scale);
recPt2.y = cvRound((r->y + r->height)*scale);
radius = cvRound((r->width + r->height)*0.25*scale);
cvGetSubRect( small_img, &small_img_roi, *r );
IplImage *result;
CvRect roi;
roi = *r;
result = cvCreateImage( cvSize(r->width, r->height), img->depth, img->nChannels );
cvSetImageROI(img,roi);
// 创建子图像
cvCopy(img,result);
cvResetImageROI(img);
//IplImage *resizeRes;
CvSize dst_cvsize;
dst_cvsize.width=(
int
)(100);
dst_cvsize.height=(
int
)(100);
resizeRes=cvCreateImage(dst_cvsize,result->depth,result->nChannels);
cvResize(result,resizeRes,CV_INTER_NN);
faceGray = cvCreateImage(cvGetSize(resizeRes), IPL_DEPTH_8U, 1);
//创建目标图像
cvCvtColor(resizeRes,faceGray,CV_BGR2GRAY);
//cvCvtColor(src,des,CV_BGR2GRAY)
cvShowImage(
"resize"
, resizeRes );
cvRectangle(img,recPt1,recPt2,color,3, 8,0);
//cvCircle( img, center, radius, color, 3, 8, 0 ); // 从中心位置画圆,圈出脸部区域
Mat test = faceGray;
//images[images.size() - 1] = test;
model->train(images, labels);
//predictedLabel = model->predict(test);
double
predicted_confidence = 0.0;
model->predict(test,predictedLabel,predicted_confidence);
stringstream strStream;
strStream<<predicted_confidence;
string ss = strStream.str();
cvText(img, ss.c_str(), r->x+r->width*0.5, r->y);
if
(predicted_confidence <= dConfidence)
cvText(img,
"Result:YES"
, 0, 30);
else
cvText(img,
"Result:NO"
, 0, 30);
//cout << "predict:"<<model->predict(test) << endl;
//cout << "predict:"<< predictedLabel << "\nconfidence:" << predicted_confidence << endl;
if
( !nested_cascade )
continue
;
nested_objects = cvHaarDetectObjects( &small_img_roi, nested_cascade, storage,
1.1, 2, 0
//|CV_HAAR_FIND_BIGGEST_OBJECT
//|CV_HAAR_DO_ROUGH_SEARCH
//|CV_HAAR_DO_CANNY_PRUNING
//|CV_HAAR_SCALE_IMAGE
,
cvSize(0, 0) );
for
( j = 0; j < (nested_objects ? nested_objects->total : 0); j++ )
{
CvRect* nr = (CvRect*)cvGetSeqElem( nested_objects, j );
center.x = cvRound((r->x + nr->x + nr->width*0.5)*scale);
center.y = cvRound((r->y + nr->y + nr->height*0.5)*scale);
radius = cvRound((nr->width + nr->height)*0.25*scale);
cvCircle( img, center, radius, color, 3, 8, 0 );
}
}
}
//cvShowImage( "result", img );
cvReleaseImage( &gray );
cvReleaseImage( &small_img );
}
void
cvText(IplImage* img,
const
char
* text,
int
x,
int
y)
{
CvFont font;
double
hscale = 1.0;
double
vscale = 1.0;
int
linewidth = 2;
cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX | CV_FONT_ITALIC,hscale,vscale,0,linewidth);
CvScalar textColor =cvScalar(0,255,255);
CvPoint textPos =cvPoint(x, y);
cvPutText(img, text, textPos, &font,textColor);
}
Mat norm_0_255(cv::InputArray _src)
{
Mat src = _src.getMat();
Mat dst;
switch
(src.channels())
{
case
1:
cv::normalize(_src, dst, 0, 255, cv::NORM_MINMAX, CV_8UC1);
break
;
case
3:
cv::normalize(_src, dst, 0, 255, cv::NORM_MINMAX, CV_8UC3);
break
;
default
:
src.copyTo(dst);
break
;
}
return
dst;
}
void
read_csv(
const
string &filename, vector<Mat> &images, vector<
int
> &labels,
char
separator)
{
std::ifstream file(filename.c_str(), ifstream::in);
if
(!file)
{
string error_message =
"No valid input file was given."
;
CV_Error(CV_StsBadArg, error_message);
}
string line, path, classlabel;
while
(getline(file, line))
{
stringstream liness(line);
getline(liness, path, separator);
//遇到分号就结束
getline(liness, classlabel);
//继续从分号后面开始,遇到换行结束
if
(!path.empty() && !classlabel.empty())
{
images.push_back(imread(path, 0));
labels.push_back(
atoi
(classlabel.c_str()));
}
}
}
//实现了从trainningdata 目录下直接读取jpg文件作为训练集
bool
read_img(vector<Mat> &images, vector<
int
> &labels)
{
long
file;
struct
_finddata_t
find;
//AllocConsole();
string path =
"..//einfacedata//trainingdata/"
;
char
filepath[60];
//_chdir("..//einfacedata//trainingdata");
if
((file=_findfirst(
"..//einfacedata//trainingdata/*.jpg"
, &find))==-1L)
{
AfxMessageBox(
"Cannot find the dir"
);
return
false
;
}
int
i = 0;
images.push_back(imread(path+find.name, 0));
labels.push_back(0);
while
(_findnext(file, &find)==0)
{
//_cprintf("%s\n", path+find.name);
//_cprintf("%d\n", i++);
images.push_back(imread(path+find.name, 0));
labels.push_back(0);
}
_findclose(file);
return
true
;
}
//实现了从trainningdata 目录下读取jpg文件数目
int
read_img_number()
{
long
file;
int
i = 0;
struct
_finddata_t
find;
//AllocConsole();
string path =
"..//einfacedata//trainingdata/"
;
char
filepath[60];
if
((file=_findfirst(
"..//einfacedata//trainingdata/*.jpg"
, &find))==-1L)
return
i;
i++;
while
(_findnext(file, &find)==0)
{
i++;
}
_findclose(file);
return
i;
}
bool
delete_img()
{
system
(
"del ..\\einfacedata\\trainingdata\\"
);
return
true
;
}
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
原文链接:https://blog.csdn.net/iteye_13202/article/details/82554526 。
最后此篇关于基于OpenCV读取摄像头实现单个人脸验证MFC程序的文章就讲到这里了,如果你想了解更多关于基于OpenCV读取摄像头实现单个人脸验证MFC程序的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我有一个 MFC 项目,它链接到第三方 dll。在程序退出时,IDE 会报告“检测到内存泄漏!”并倾倒泄漏物。 这些泄漏来自第三方 dll。我很确定这些是错误的报道。 (Google 的快速检查表明
首先我想要的是:能够显示具有多列的网格,每个单元格都有一个自定义渲染回调。因此,您可以使用这样的控件在游戏中显示您的库存,或者类似于 Google Chrome 中的行为,它会显示您访问的热门页面的网
在新的 MFC 功能(功能包)中,菜单出现在三个地方: 在菜单栏中 (CMFCMenuBar) 在弹出菜单中 (CMFCPopupMenu) 在 CMFCButton 的“下拉菜单”版本中 我想在所有
在我的 MFC 项目中,我想动态生成标签。例如:我必须为它们生成 4 个编辑控件和相应的标签——比如“Label1”“Label2”...... CStatic *label[MAX_THREAD];
我有第一个对话框,上面有一个简单的按钮,单击该按钮时,使用 CDialog::Create(IDD,this) 创建了第二个对话框。我希望在销毁第二个对话框但不向第二个对话框添加任何代码时通知父级,即
我们的代码库中的添加到剪贴板代码非常低级 - 分配全局内存等等。对于简单的情况,我只想将一些纯文本放在剪贴板上,是否有任何例程可以包装所有这些内容? 一个例子是 CRichEditCtrl 具有 Co
我对 mfc 中事件和消息之间的区别有点困惑。 他们是一样的吗? 最佳答案 由于您专门询问 MFC,我假设您指的是可以在 MFC 类的属性窗口中定义的事件处理程序和消息处理程序。 在“事件”下,您可以
如何以编程方式检测我的 MFC 应用程序当前是否正在显示模式对话框或属性表?目前我正在使用以下内容,但我觉得该代码也会触发无模式对话框。 bool HasModalDialog(const CWnd*
我有两个按钮: 单选按钮:“十六进制” 按钮:“A” 我想在用户选中“十六进制”按钮时启用“A”(“A”在创建时的状态为“禁用”),我该怎么做?谢谢大家。 最佳答案 您需要使用 CButton 's
通常情况下,窗口的厚度为 4 个像素,可以通过 GetSystemMetrics 方法获取。我可以更改它的值,例如 2 个像素吗? 非常感谢! 最佳答案 简单的回答:不。不适用于特定窗口。 复杂的答案
我需要打开一个从同一个类实例化的对话框两次。当我尝试这个时 CdelmeDlg dlg; dlg.DoModal(); dlg.DoModal(); 第二个调用只打开对话框一瞬间,然后关闭。我敢打赌消
如何通过代码在 mfc 中减少标题栏的窗口? 最佳答案 用: ModifyStyle (WS_CAPTION, 0); // to hide ModifyStyle (0, WS_CAPTION);
我使用 AfxMessageBox 关键字显示消息框。基本的东西。 但是,由于路径的长度,它显示如下: 有什么方法可以阻止它以这种方式自动换行吗? 抱歉,如果这是一个愚蠢的问题。但如果我只有一个句子,
所以,我有一个 MFC 程序的插件。我正在使用鼠标事件 Hook (来自 SetWindowsHookEx)来捕获点击。主机应用程序可以打开任意数量的(可能重叠的)子窗口,但我只想拦截特定子窗口中的点
我正在尝试将图像添加到现有按钮..我在一定程度上做到了这一点,问题是我可以添加一个所有者绘制的图像,但无法添加我想要的确切图像..示例见下文代码 CButton* pBtn= (CButton*)Ge
我想在对话框的标题栏上放置一些控件。一种可能的解决方案是,我只是从对话框中删除标题栏并绘制自己的标题栏。 但是如果我自己画标题栏,标题栏的外观不会根据窗口的主题而改变。而且我也不得不忍受接近、最小化和
我已经使用 MinGW 开发了 WinAPI 应用程序,没有问题。现在,我可以用 MFC 做同样的事情吗? 最佳答案 你不能。 MFC 代表 Microsoft Foundation Classes,
(我正在使用VS ++ 2005) 我在对话框上放置了编辑框控件(ID为ID_edit_box),并为其关联了两个变量(使用处理程序向导):控件(c_editbox)和值(v_editbox)变量。我
我有一个自定义 MFC 对话框 CMyDialog,使用资源编辑器添加了一个类型为 CMyControl 的自定义控件 - 该对话框有一个控件的成员变量并且有 DDX设置。 该控件正在接收绘制消息,并
直到现在,我从未真正需要我正在开发的大型 MFC(如果重要,则为单文档界面)应用程序的 Winapp ExitInstance()。但现在我这样做了,主要是为了清理内存分配、卸载一些 DLL 等。好吧
我是一名优秀的程序员,十分优秀!