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的框架。

MFC建立 
MFC建立 
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

好了,貼一張運行成功的截圖,怕丑到各位,打了些馬賽克:

這里寫圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM