• 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
    ");};
        if (!eyes_cascade.load(eyes_cascade_name)){ printf("--(!)Error loading
    ");};//加载分类器的
        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

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

    这里写图片描述

  • 相关阅读:
    python3 操作excel(读操作)
    display:inline-block;产生间隙解决方法
    vedio自定义样式
    angularjs路由
    移动端设置字体px转换rem的脚本
    div在不固定高度的情况下垂直或者水平居中
    css气泡地址和分享地址
    js点击按钮div显示,点击div或者body和按钮,div隐藏
    js倒计时跳转页面
    点击按钮div显示,点击div或者document,div隐藏
  • 原文地址:https://www.cnblogs.com/lizhigang/p/7206880.html
Copyright © 2020-2023  润新知