程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++開發人臉性別識別教程(15)——搭建MFC框架啟動攝像頭

C++開發人臉性別識別教程(15)——搭建MFC框架啟動攝像頭

編輯:關於C++

  在之前的博文中已經完成了針對圖片的人臉性別識別功能,在這篇文章中我們開始引入攝像頭設備,為程序添加第二個功能:視頻人臉性別識別。

  一、添加控件

  這裡需要新添加兩個與視頻人臉性別識別相關的功能控件,一個是“打開視頻”按鈕(ID為IDC_OpenVideo),一個是“暫停按鈕”按鈕。為了適當減少主窗口中的按鈕控件的數量,這裡再次采用一種復用策略,即將視頻識別模式中的“暫停”功能與之前圖片文件夾識別模式中的“下一張”功能合並,通過一個按鈕來控制:

\

  二、CVideoInfo類

  2.1 添加視頻流類

  接下來需要開啟視頻攝像頭,將攝像頭得到的圖像實時的顯示在主程序的picture控件中。有關OpenCv中的攝像頭操作我在C++開發人臉性別識別教程(4)——OpenCv的人臉檢測函數這篇博文中進行了較為詳細的介紹。這裡我們對攝像頭的開啟進行一下小小的封裝,即將其聲明為一個類CVideoInfo,這樣做的原因主要是為了能夠方便後期的處理,我們將攝像頭輸出的視頻流、幀圖像、幀圖像的尺寸(寬度和高度)都封裝在同一個對象中,方便讀取,也方便獲取圖像的相關屬性。

  在VS中切換到類視圖窗口,右擊工程名,添加類:

\

  指定添加類的類型為“C++類”:

\  輸入類名CVideoInfo,對應的.h文件和.cpp文件名稱系統會自動生成,無繼承,訪問屬性默認使用public,單擊完成:

\

  此時在類視圖下可以看到工程中多了一個名為CVideoInfo的類:

\

  2.2 編輯CVideoInfo類

  接下來為CVideoInfo添加相應的代碼。切換到解決方案資源管理器窗口,會發現此時工程目錄下會多出兩個文件,VideoInfo.h和VideoInfo.cpp:

\

  首先編輯類對應的頭文件VideoInfo.h,發現VS已經在頭文件中提供了基本的類聲明,並給出了缺省的構造函數和析構函數,我們在這裡只需向其中添加若干成員變量即可,這裡我們添加四個成員變量:CvCapture*格式的視頻流變量,IplImage*格式的幀圖像變量,以及兩個整型變量用以表示幀圖像的寬度和高度:

    CvCapture* m_pCapture;     //用於存儲攝像頭輸入的視頻流
    IplImage* m_pFrameImage;   //存儲圖片

    int m_FrameWidth;          //圖片寬度
    int m_FrameHeight;         //圖片高度

  最終VideoInfo.h文件中的類聲明代碼如下:

#pragma once
#include "opencv2/opencv.hpp"

class CVideoInfo
{
public:

    CvCapture* m_pCapture;     //用於存儲攝像頭輸入的視頻流
    IplImage* m_pFrameImage;   //存儲圖片

    int m_FrameWidth;          //圖片寬度
    int m_FrameHeight;         //圖片高度

public:
    CVideoInfo(void);          //缺省構造函數
public:
    ~CVideoInfo(void);         //缺省析構函數
};

  至於VideoInfo.cpp,由於VideoInfo類目前只是負責圖像的存儲和顯示,沒有其他額外的功能,因此在這裡只需要完成構造函數對成員變量的初始化,而析構函數采用系統提供的缺省函數即可,VideoInfo.cpp文件的代碼如下:

#include "StdAfx.h"
#include "VideoInfo.h"

CVideoInfo::CVideoInfo(void)  //缺省構造函數
{
    m_pCapture = NULL;
    m_pFrameImage = NULL; 
}

CVideoInfo::~CVideoInfo(void)//缺省析構函數
{
}

  完成了類的定義之後,需要向CGenderRecognitionMFCDlg類中添加一個VideoInfo*形式的變量m_pVideoInfo用來保存當前的視頻流信息,當然使用全局變量也可以實現這個功能,不過會是代碼變得更復雜,不推薦。

\

  在添加變量之前需要先在CGenderRecognitionMFCDlg.h中包含一下VideoInfo.h頭文件,使得VideoInfo類可見:

\

  接下來就可以正式著手開啟攝像頭了。

  三、開啟攝像頭

  雙擊“打開視頻”按鈕,添加對應的事件處理函數:

\

  首先,判斷程序是否進行了分類器加載初始化:

    if (m_boolInitOK == FALSE)
    {
        MessageBox("請先進行初始化");
        return;
    }

  然後使用cvCreateCameraCapture函數開啟攝像頭,並將視頻流賦值給m_pVideoInfo:

m_pVideoInfo->m_pCapture = cvCreateCameraCapture(0);//創建一個Capture(攝像頭)

  注意此時運行程序的話在這句代碼會報錯,原因是m_pVideoInfo這個成員變量尚未被分配內存空間,因此需要在程序開始運行時手動通過new操作符對其進行內存空間的分配,這裡將內存分配的語句放置在OnInitDialog()這個成員函數中:

    /*********為m_pVideoInfo變量分配內存空間**********/
    m_pVideoInfo = new CVideoInfo;

  四、顯示圖像

  在攝像頭捕捉到圖像之後,接下來需要將幀圖像實時的顯示在picture界面中,實現這個功能的方法有很多,這裡采用定時器的方法。即設置一個定時器,每隔一定時間就觸發,在對應的回調函數中完成幀圖像的顯示工作。因此在OnBnClickedButton1Video()函數中需要對定時器進行初始化,單擊“打開視頻”按鈕後,就開始觸發定時器,輪詢播放攝像頭畫面:

SetTimer(1,1,NULL);//觸發一個計數器,在響應函數中完成圖像顯示

  有關MFC中定時器的使用大家參見網上資料,這裡就不再贅述。

  接下來添加定時器消息響應函數,在類視圖中右鍵單擊CGenderRecognitionMFCDlg類,選擇屬性,彈出屬性對話框,在消息欄中找到WM_TIMER,單擊右邊的下拉箭頭,添加消息響應函數OnTimer:

\

  在OnTimer()函數體中完成幀圖像的繪制,這裡直接給出代碼:

void CGenderRecognitionMFCDlg::OnTimer(UINT_PTR nIDEvent)
{
    m_pVideoInfo->m_pFrameImage = cvQueryFrame(m_pVideoInfo->m_pCapture);//得到視頻流中的下一幀

    CvvImage cvvImage;
    cvvImage.CopyOf(m_pVideoInfo->m_pFrameImage);
    cvvImage.DrawToHDC(m_pPicCtlHdc,m_PicCtlRect);
    CDialogEx::OnTimer(nIDEvent);
}

  此時運行程序,程序正常執行,能夠在picture界面上實時的顯示攝像頭采集的圖像,在下一篇博客中將介紹如何向其中添加性別識別的步驟。

\

  五、注意事項

  1、CVideoInfo類的封裝問題

  說實話這裡將攝像頭輸入的視頻流封裝為CVideoInfo類的工作方式顯得有點小題大做,似乎直接在類中添加一個CvCapture*類型的成員變量就能夠完成任務,但隨著程序的改進,我們可能需要得到越來越多的視頻幀圖像的屬性值(如尺寸,通道數等等),甚至需要在讀取幀圖像之前對原圖像做一些必要的、固化的初始化操作,如果我們將視頻流封裝成CVideoInfo類,就能夠方便的以成員函數的形式給出這些操作、屬性值,避免了在程序的大框架下添加,也避免了對各個屬性值的頻繁讀取。

  2、類成員訪問屬性問題

  C++中對類成員變量的訪問屬性推薦設置為private,對成員函數的訪問屬性推薦設置為public,並且推薦通過成員函數來訪問成員變量,而非直接讀取。

  3、定時器問題

  關於VC中定時器的用法網上有很多詳細的說明,例如VC定時器的用法:SetTimer和Ontimer,這裡將時間間隔設置為1毫秒,即每一毫秒就刷新一幀,大家可以嘗試更改其他的時間間隔,觀察效果。

  4、OnInitDialog函數問題

  OnInitDialog()函數在對話框生成的時候調用,因此在基於對話框的程序中,這個函數用來執行程序必要的初始化操作,目前為止在我們的工程中這個函數承擔了初始化Combo Box控件、初始化Combo Box控件、為m_pVideoInfo變量分配內存空間的任務,隨著程序的編寫,還會有更多的初始化操作被加入到這個函數體中。

  5、致歉

  這篇博客是我在寒假之後寫的,中間有一個多月的時間沒寫過代碼,所以思路有點混亂,敘述的不是很清晰,大家見諒。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved