虚位以待(AD)
虚位以待(AD)
首页 > 软件编程 > C/C++编程 > OpenCV实现人脸检测

OpenCV实现人脸检测
类别:C/C++编程   作者:码皇   来源:互联网   点击:

这篇文章主要为大家详细介绍了OpenCV实现人脸检测的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

前段日子,写了个人脸检测的小程序,可以检测标记图片、视频、摄像头中的人脸。效果还行吧,用的是opencv提供人脸库。至于具体的人脸检测原理,找资料去啃吧。

环境:VS2013+OPENCV2.4.10+Win8.1

这里写图片描述

一、基于对话框的MFC

首先,新建一个基于对话框的MFC应用程序,命名为myFaceDetect(取消“安全开发周期(SDL)检查”勾选,我自己习惯取消这个)。

这里写图片描述 

放置Button,设置Button的ID和Caption。
图片按钮——ID:IDC_FACEDETECT
视频按钮——ID:IDC_FACEV
摄像头按钮——ID:IDC_FACEC

二、添加消息响应函数

为图片按钮、视频按钮、摄像头按钮,在类向导中添加消息响应函数。
在图片按钮上右键,选择类向导。在CMyFaceDetectDlg类(对话框类)下选中BN_CLICKED消息,点击添加处理程序。其余两个按钮,按同样操作,添加消息响应函数。
完成上述操作后,获得对应三个按钮的消息响应函数。

这里写图片描述
这里写图片描述

    void CMyFaceDetectDlg::OnClickedFacedetect()//图片按钮void CMyFaceDetectDlg::OnClickedFacev()//视频按钮void CMyFaceDetectDlg::OnClickedFacec()//摄像头按钮

三、人脸检测实现

首先,将OpenCV2.4.10+VS2013环境的配置完成,这个网上有许多教程。这是我以前写的一篇配置教程:Visual Studio 2013+OpenCV2.4.10环境搭建教程

对话框类的头文件:MyFaceDetectDlg.h

    // MyFaceDetectDlg.h : 头文件//#pragma once#include <opencv2/objdetect/objdetect.hpp>#include <opencv2highguihighgui.hpp>#include <opencv2mlml.hpp>#include <opencv.hpp>#include "afxwin.h"using namespace cv;
    // CMyFaceDetectDlg 对话框class CMyFaceDetectDlg : public CDialogEx{
    // 构造public: CMyFaceDetectDlg(CWnd* pParent = NULL);
    // 标准构造函数// 对话框数据 enum {
    IDD = IDD_MYFACEDETECT_DIALOG }
    ;
    protected: virtual void DoDataExchange(CDataExchange* pDX);
    // DDX/DDV 支持// 实现protected: HICON m_hIcon;
    HICON m_catIcon;
    //程序的小猫图标。如果想用默认的图片,可以将其注释掉。 // 生成的消息映射函数 virtual BOOL OnInitDialog();
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()public: afx_msg void OnClickedFacedetect();
    public: CascadeClassifier cascade;
    //级联分类器 Mat image;
    //图片 double scale;
    //缩小比例。缩小图片可以加快检测速度,当然加快检测速度还有其他的方法。public: void detectAndDraw(Mat& img, CascadeClassifier& cascade, double scale);
    //添加的实现人脸检测的函数,核心函数 CButton m_btn;
    //为了美化按钮添加对象,可以注释掉。 afx_msg void OnClickedFacev();
    afx_msg void OnClickedFacec();
    afx_msg void OnBnClickedCancel();
    }
    ;

对话框类的实现:MyFaceDetectDlg.cpp

    // MyFaceDetectDlg.cpp : 实现文件//#include "stdafx.h"#include "MyFaceDetect.h"#include "MyFaceDetectDlg.h"#include "afxdialogex.h"#include <string>#ifdef _DEBUG#define new DEBUG_NEW#endif// CMyFaceDetectDlg 对话框CMyFaceDetectDlg::CMyFaceDetectDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CMyFaceDetectDlg::IDD, pParent){
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    m_catIcon = AfxGetApp()->LoadIcon(IDI_ICON4);
    //加载自己的图标(小猫~) scale = 1.3;
    }
    void CMyFaceDetectDlg::DoDataExchange(CDataExchange* pDX){
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_FACEDETECT, m_btn);
    }
    BEGIN_MESSAGE_MAP(CMyFaceDetectDlg, CDialogEx) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_FACEDETECT, &CMyFaceDetectDlg::OnClickedFacedetect) ON_BN_CLICKED(IDC_FACEV, &CMyFaceDetectDlg::OnClickedFacev) ON_BN_CLICKED(IDC_FACEC, &CMyFaceDetectDlg::OnClickedFacec) ON_BN_CLICKED(IDCANCEL, &CMyFaceDetectDlg::OnBnClickedCancel)END_MESSAGE_MAP()// CMyFaceDetectDlg 消息处理程序BOOL CMyFaceDetectDlg::OnInitDialog(){
    CDialogEx::OnInitDialog();
    // 设置此对话框的图标。 当应用程序主窗口不是对话框时,框架将自动 // 执行此操作 //若不需要自己设置图标,可以将后面所有m_catIcon改成m_hIcon SetIcon(m_catIcon, TRUE);
    // 设置大图标。 SetIcon(m_catIcon, FALSE);
    // 设置小图标 //按钮加载图片背景 //HBITMAP hbmp1 = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP2));
    //m_btn.SetBitmap(hbmp1);
    // TODO: 在此添加额外的初始化代码 return TRUE;
    // 除非将焦点设置到控件,否则返回 TRUE}
    // 如果向对话框添加最小化按钮,则需要下面的代码// 来绘制该图标。 对于使用文档/视图模型的 MFC 应用程序,// 这将由框架自动完成。void CMyFaceDetectDlg::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_catIcon);
    }
    else {
    /*改变对话框背景****若需要默认背景,可以删除*/ CPaintDC dc(this);
    CRect rect;
    GetClientRect(&rect);
    CDC dcBmp;
    dcBmp.CreateCompatibleDC(&dc);
    CBitmap bmpBackGround;
    bmpBackGround.LoadBitmap(IDB_BITMAP4);
    BITMAP m_bitmap;
    bmpBackGround.GetBitmap(&m_bitmap);
    CBitmap *pbmpOld = dcBmp.SelectObject(&bmpBackGround);
    dc.StretchBlt(0, 0, rect.Width(), rect.Height(), &dcBmp, 0, 0, m_bitmap.bmWidth, m_bitmap.bmHeight, SRCCOPY);
    /*********************************/ CDialogEx::OnPaint();
    }
    }
    //当用户拖动最小化窗口时系统调用此函数取得光标//显示。HCURSOR CMyFaceDetectDlg::OnQueryDragIcon(){
    return static_cast<HCURSOR>(m_catIcon);
    }
    void CMyFaceDetectDlg::OnClickedFacedetect(){
    // TODO: 在此添加控件通知处理程序代码 CString filename;
    //打开对话框 CFileDialog OpenDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR, _T("图片 (*.jpg)|*.jpg|(*.*) |*.*|"), NULL);
    if (OpenDlg.DoModal() != IDOK) {
    return;
    }
    filename = OpenDlg.GetPathName();
    //获得文件路径 /*CString转换*string*/ USES_CONVERSION;
    std::string tempName(W2A(filename));
    image = imread(tempName);
    //读取图片 const String cascade_name = "./haarcascade_frontalface_alt2.xml";
    //加载人脸库 if (!cascade.load(cascade_name)) {
    MessageBox(_T("ERROR:Could not load cascade!"));
    return;
    }
    if (!image.data) {
    MessageBox(_T("ERROR:Could not load image!"));
    return;
    }
    namedWindow("人脸检测", CV_WINDOW_AUTOSIZE);
    detectAndDraw(image, cascade, scale);
    //调用人脸检测函数 imshow("人脸检测", image);
    return;
    }
    void CMyFaceDetectDlg::detectAndDraw(Mat& img, CascadeClassifier& cascade, double scale){
    /*程序核心函数,检测标记人脸*/ int i = 0;
    vector<Rect>faces;
    //定义一个容器,保存检测结果 const static Scalar colors[] = {
    CV_RGB(0, 0, 255), CV_RGB(0, 128, 255), CV_RGB(0, 255, 255), CV_RGB(0, 255, 0), CV_RGB(255, 128, 0), CV_RGB(255, 255, 0), CV_RGB(255, 0, 0), CV_RGB(255, 0, 255) }
    ;
    Mat gray, smallImage(cvRound(img.rows / scale), cvRound(img.cols / scale), CV_8UC1);
    //用cvRound取整 cvtColor(img, gray, CV_BGR2GRAY);
    //转化灰度图 resize(gray, smallImage, smallImage.size(), 0, 0, INTER_LINEAR);
    //图片尺度调整 equalizeHist(smallImage, smallImage);
    //直方图均衡 cascade.detectMultiScale(smallImage, faces);
    //核心,检测人脸 for (vector<Rect>::const_iterator r = faces.begin();
    r != faces.end();
    r++, i++) {
    //利用迭代器,标记出人脸位置。 Point center;
    Scalar color = colors[i % 8];
    int radius;
    /*计算出原图像中的圆心和半径。公式很简单,自己写一下,就可以理解了*/ center.x = cvRound((r->x + r->width*0.5)*scale);
    center.y = cvRound((r->y + r->height*0.5)*scale);
    radius = cvRound((r->width + r->height)*0.25*scale);
    /****************/ circle(img, center, radius, color, 3);
    }
    }
    void CMyFaceDetectDlg::OnClickedFacev(){
    // TODO: 在此添加控件通知处理程序代码 //检测视频帧中的人脸 CString filename;
    CFileDialog OpenDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR, _T("视频(*.avi)|*.avi|(*.*)|*.*|"), NULL);
    if (OpenDlg.DoModal() != IDOK) {
    return;
    }
    /*CString转换*string*/ filename = OpenDlg.GetPathName();
    USES_CONVERSION;
    std::string tempName(W2A(filename));
    const String cascade_name = "./haarcascade_frontalface_alt2.xml";
    if (!cascade.load(cascade_name)) {
    MessageBox(_T("ERROR:Could not load cascade!"));
    return;
    }
    VideoCapture capture(tempName);
    //打开视频 if (!capture.isOpened()) {
    MessageBox(_T("ERROR:Could not load Video!"));
    return;
    }
    double rate = capture.get(CV_CAP_PROP_FPS);
    bool stop(false);
    int delay = 1000 / rate;
    while (!stop) {
    if (!capture.read(image))//读取视频帧 break;
    detectAndDraw(image, cascade, scale);
    imshow("人脸检测", image);
    if (waitKey(delay) >= 0) stop = true;
    }
    capture.release();
    return;
    }
    void CMyFaceDetectDlg::OnClickedFacec(){
    // TODO: 在此添加控件通知处理程序代码 //检测摄像头中的人脸数据 const String cascade_name = "./haarcascade_frontalface_alt2.xml";
    if (!cascade.load(cascade_name)) {
    MessageBox(_T("ERROR:Could not load cascade!"));
    return;
    }
    VideoCapture capture(0);
    //打开摄像头 if (!capture.isOpened()) {
    MessageBox(_T("ERROR:Could not load capture!"));
    return;
    }
    //double rate = capture.get(CV_CAP_PROP_FPS);
    //bool stop(false);
    //int delay = 1000 / rate;
    int k=0;
    while (1) {
    if (!capture.read(image)) break;
    detectAndDraw(image, cascade, scale);
    imshow("人脸检测", image);
    k=waitkey(10);
    if (k=27)//ESC键 break;
    }
    capture.release();
    return;
    }
    void CMyFaceDetectDlg::OnBnClickedCancel(){
    // TODO: 在此添加控件通知处理程序代码 CDialogEx::OnCancel();
    }

三 运行程序

视频和图片都有测试,一般只要是正脸、清晰的都能检测图片。另外,需要将haarcascade_frontalface_alt2.xml文件复制到程序目录下。
这里写图片描述 

将文件在目录opencvsourcesdatahaarcascades下。

这里写图片描述 

这里写图片描述

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

您可能感兴趣的文章:

  • Java+opencv3.2.0实现人脸检测功能
  • opencv实现图片与视频中人脸检测功能
  • 基于openCV实现人脸检测
  • OpenCV实现人脸识别
  • opencv 做人脸识别 opencv 人脸匹配分析
  • JavaCV实现人脸检测功能
  • OPENCV+JAVA实现人脸识别
相关热词搜索: OpenCV 人脸检测