1. 程式人生 > >OPENCV人臉檢測實現

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
()//攝像頭按鈕

三 人臉檢測實現

// MyFaceDetectDlg.h : 標頭檔案
//
#pragma once
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\ml\ml.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檔案複製到編譯出程式的目錄(例如Debug目錄下)
這裡寫圖片描述
這個檔案在目錄opencv\sources\data\haarcascades下。
這裡寫圖片描述
這裡寫圖片描述

相關推薦

OPENCV人臉檢測實現

前段日子,寫了個人臉檢測的小程式,可以檢測標記圖片、視訊、攝像頭中的人臉。效果還行吧,用的是opencv提供人臉庫。至於具體的人臉檢測原理,找資料去啃吧。 環境:VS2013+OPENCV2.4.10+Win8.1 一 基於對話方塊的MF

呼叫opencv 人臉檢測實現問題解決~~(VS2013+Opencv)

前輩的文章詳細介紹了訓練xml分類器的過程,和人臉檢測相關的引數設定和程式碼,原文在這裡:傳送門 但是程式碼直接拿來用的話還是會出問題的, 這篇記錄的就是實現上述文章中呼叫xml的批量圖片人臉檢測遇到的問題和解決的辦法,有空的時候也會將自己訓練的詳細過程和

opencv人臉檢測_Haar特徵分類器實現人臉檢測_cascade.detectMultiScale引數詳解

1.  概述 CascadeClassifier為OpenCV中cv namespace下用來做目標檢測的級聯分類器的一個類。該類中封裝的目標檢測機制,簡而言之是滑動視窗機制+級聯分類器的方式 2.  支援的特徵 對於Haar、LBP和HOG,CascadeClas

(學習筆記二)——基於opencv人臉檢測原理及實現

最近搞了幾天的人臉檢測,終於把大體框架和原理搞清楚了,現在寫出來供大家學習之用,如有不對之處,還請大家指正。也希望大家在學習opencv的過程中能將學習過程及重點記錄下來,以部落格的形式分析,畢竟opencv的教材還不太多,我們自己學習大部分要靠網上的資料。通過部落格分享的

基於opencv人臉檢測原理及實現

最近搞了幾天的人臉檢測,終於把大體框架和原理搞清楚了,現在寫出來供大家學習之用,如有不對之處,還請大家指正。也希望大家在學習opencv的過程中能將學習過程及重點記錄下來,以部落格的形式分析,畢竟opencv的教材還不太多,我們自己學習大部分要靠網上的資料。通過部落格分享

OpenCV人臉檢測(完整源代碼+思路)

exceptio pop ret 基礎 err 攝像 alt lena ann 本博文IDE為vs2013 OpenCV2.49 話不多說,先看視頻演示(20S演示): 例如以下: https://v.youku.com

簡單opencv人臉檢測程式碼:LBP/Haar特徵

前言 目前網路上有太多opencv人臉檢測程式碼,但大部分都是用老的1.0介面,程式碼存在太多冗餘(各種記憶體分配...看著太不舒服了,話說還有人用1.x版本的opencv嗎- -),而實際上用2.0以上版本實現人臉檢測功能是可以比較簡潔的。(官方也早有相關示例) 人臉檢

Python-OpenCV人臉檢測---直接呼叫訓練好的Harr特徵

人臉檢測 定義人臉檢測函式detectFaces(),檢測圖片中所有出現的人臉,並返回人臉的矩形座標(矩形左上、右下頂點座標)。使用上面提到的xml檔案(haar特徵),haarcascades目錄下有好幾個是關於人臉檢測的檔案,這裡選擇haarcascade_frontalface_default.

keras系列︱人臉表情分類與識別:opencv人臉檢測+Keras情緒分類(四)

人臉識別熱門,表情識別更加。但是表情識別很難,因為人臉的微表情很多,本節介紹一種比較粗線條的表情分類與識別的辦法。 Keras系列: 本次講述的表情分類是識別的分析流程分為:

python-opencv-人臉識別實現 從圖片中扣人臉

最近專案需要,從百度,bing 爬取圖片,並對圖片中人臉進行扣取,然後扣取的人臉作為機器學習的樣本資料進行人工標註,圖片爬取了人工篩選比較耗時,於是查詢資料發現opencv庫中人臉識別可以實現該需求,識別率還可以。 #-*-coding:utf8-*- import os

Opencv人臉檢測

OpenCv人臉檢測: 要實現人臉識別功能,首先要進行人臉檢測,判斷出圖片出人臉的位置,才能進行下一步的操作! OpenCv人臉檢測的方法 在OpenCv中主要使用兩種特徵(即兩種方法)進行人臉檢測 1、Haar特徵 2、LBP特

*.exe觸發了一個斷點--opencv人臉檢測

*.exe觸發了一個斷點–opencv人臉檢測 利用opencv進行人臉檢測,遇到一個十分不解的問題,每次程式退出都會觸發斷點,單步除錯無數次根本沒用,最後偶然得以解決,記錄在此,防止後來者踩坑。 事情發生在女朋友的電腦上,她之前裝的vs2010,然

opencv+人臉檢測(OpenCv3.0+VS2013)

進入正題吧----------------->最近一直在弄人臉檢測的程式碼,用的就是opencv3.0自己帶的人臉檢測的程式碼,可是一直就是出錯,在網上搜了好多,一直沒有找到解決的辦法,可能是自

vs2015學習qt562_64位的opencv人臉檢測專案工程配置

1、說明:文件中不懂的地方可參考:vs2015學習opencv330_64位的工程配置 。 2、vs2015下載安裝 3、vs2015的qt外掛下載安裝 4、qt庫下載安裝(最後的分享地址中,在qt庫的目錄下面找到安裝包,安裝好後再把需要的庫拷貝到qt

opencv人臉檢測,旋轉處理

不能 ont sin 賦值 修改配置 裁剪 net ogg 超過 年會簽到,拍自己的大頭照,有的人可能會拍成橫向的,需要旋轉,用人臉檢測並修正它(圖片)。 1. 無腦檢測步驟為: 1. opencv 讀取圖片,灰度轉換 2. 使用CascadeClassifier()通過訓

【Caffe實踐】基於Caffe的人臉檢測實現

0. 引言 深度學習可以說是在人臉分析相關領域遍地開花,近年來在人臉識別,深度學習在人臉檢測,人臉關鍵點檢測中有很廣泛的應用,這篇文章中,初步實現了基於深度學習CNN的人臉檢測。 1. 方法討論 深度學習一般沒有進行直接的檢測,現有的檢測大多都是基於分

OpenCV: OpenCV人臉檢測框可信度排序

       使用OpenCV進行人臉識別時,使用 casecade.detectMultiScale        函式,可輸出每個檢測框的置信度 程式碼段: const int numReserve = 4; std::vector<  int

opencv人臉檢測程式碼應用與分析(PC端和Android端)

(1)OpenCV人臉檢測C++程式流程: OpenCV的人臉檢測程式採用了Viola & Jones人臉檢測方法,主要是呼叫訓練好的瀑布級聯分類器cascade來進行模式匹配。 cvHaarDetectObjects先將影象灰度化,根據傳入引數判斷是否進行can

OpenCV人臉檢測的速度

各位大蝦好,小弟有一個關於OpenCV人臉檢測的問題想請教一下: 我用攝像頭開啟480x640的視窗,然後使用OpenCV的人臉檢測函式cvHaarDetectObjects進行人臉檢測。函式配置如下: faces = cvHaarDetectObjects( detectImg, (CvHaarClass

openCV-人臉檢測與特徵點識別

綜述 最近在做計算機視覺的一些基礎訓練,用opencv做了做人臉檢測。 注意opencv的人臉檢測不是基於深度學習的。後期我還做了用tensorflow搞人臉識別的demo,到時候再發一下。 環境 mac os pycharm 使用opencv3