如何使用MFC結合opencv實現影片撥放/暫停_class的使用x如何添加class_part1

會有需要對opencv 進行 UI  設計的開發者朋友們



這篇會教大家如何實現   在  MFC ( Microsoft Foundation Class) 這個framework

去進行配置教學結合opencv實現  視訊載入  撥放/暫停 等效果
【第一階段_具備新增MFC專案及設置的能力】

檔案 --> 新增 --> 專案



選擇  Visual C++  MFC 應用程式










按下完成後  就可看到  MFC 的視窗畫面



我們來拉個 button 吧

Caption  改成   "打開視頻"  

( ps : 改變控建上顯示的文字  )


ID欄位  改成  IDC_OpenVideo




對  Button 控建   快點 兩下 跳至程式碼區塊



按鈕點擊完  -->  跳出一個窗口 --> 供使用者作要讀取的影片選擇




參數作用  (六個參數):

bOpenFileDialog    為TRUE則顯示打開對話框,為FALSE則顯示保存對話文件框(另存新檔)        
lpszDefExt         指定文件默認擴展名
lpszFileName       指定初始文件名       
dwFlags            指定對話框風格(默認 OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT)   
lpszFilter         過濾器 指明可供選擇的文件類型和相應的擴展名      
pParentWnd         父窗口指針      

其中,擴展檔名遵循下面的格式如下:

"Chart Files (*.xlc)|*.xlc| Worksheet Files (*.xls)|*.xls| Data Files (*.xlc;*.xls)|*.xlc ; *.xls| All Files (*.*)|*.*||";




【第一階段  程式碼】  

位於 XXXDlg.cpp
XXX  ------>  指你當初自訂的專案名稱
以這邊為例  我是取名為  MFC_opencv_test
MFC_opencv_testDlg.cpp



// MFC_opencv_testDlg.cpp : 實作檔
//

#include "stdafx.h"
#include "MFC_opencv_test.h"
#include "MFC_opencv_testDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 對 App About 使用 CAboutDlg 對話方塊

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()


// CMFC_opencv_testDlg 對話方塊



CMFC_opencv_testDlg::CMFC_opencv_testDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(CMFC_opencv_testDlg::IDD, pParent)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMFC_opencv_testDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CMFC_opencv_testDlg, CDialogEx)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    ON_BN_CLICKED(IDC_OpenVideo, &CMFC_opencv_testDlg::OnBnClickedOpenvideo)
END_MESSAGE_MAP()


// CMFC_opencv_testDlg 訊息處理常式

BOOL CMFC_opencv_testDlg::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 CMFC_opencv_testDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    {
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }
    else
    {
        CDialogEx::OnSysCommand(nID, lParam);
    }
}

// 如果將最小化按鈕加入您的對話方塊,您需要下列的程式碼,
// 以便繪製圖示。對於使用文件/檢視模式的 MFC 應用程式,
// 框架會自動完成此作業。

void CMFC_opencv_testDlg::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 CMFC_opencv_testDlg::OnQueryDragIcon()
{
    return static_cast<HCURSOR>(m_hIcon);
}



void CMFC_opencv_testDlg::OnBnClickedOpenvideo()
{
    // TODO:  在此加入控制項告知處理常式程式碼
    char aviName[300]; // 需初始化 不能用 指標形式
    //char *aviName;
    CFileDialog inDlg(TRUE, NULL, NULL, NULL, NULL, NULL);
    /*
        CFileDialog::CFileDialog( 
            BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL,
            LPCTSTR lpszFileName = NULL,
            DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
            LPCTSTR lpszFilter = NULL, CWnd* pParentWnd = NULL 
        );
    */
    inDlg.m_ofn.lpstrFile = (LPWSTR)&aviName[0];
    //將陣列指標傳給lpstrFile,運行結束後我們的文件名稱就會存至陣列中
    if (inDlg.DoModal() == IDOK) //判定按鈕控建  是否被點選   
    {
        //這裡你可能要做  開啟影像、視頻 , 讀取影像、視頻 , frame的處理..etc

    }
}







這裡 我們如果要用 opencv 第一版  充斥著指標 的opencv2.1

那我們想一下   開啟一個 video 會需要他的相關屬性

像是   capture 指標 、 視頻的  寬度  及  高度  和 指定處理的frame

我們把這些資訊都另外包在一個類中

這裡我門要學習   新增一個自創的  類


對 專案   -->  右鍵 --> 新增 --> C++類別 -->按下  新增


將類別名稱   取名為  CVideoInfo





類別 跟 結構  有點像

唯一的差別在於

結構(Structure)  :  只能包含資料變數

類別(Class) : 擴充可包含到處理資料的函數


在類別中

不同的資料變數  ,名稱也會不同 , 稱為 「資料成員」(data member),又可叫「屬性」(attribute)

處理資料變數的函數   ,  則稱為 「成員函數」(member function) , 又叫做「方法」



【第二階段_這裡我們進入到  opencv的環境配置】





撰寫程式碼時  記得引用  標頭

#include<cv.h>
#include<highgui.h>
#include<cvwimage.h>



我們在去

VideoInfo.cpp 中  賦予 兩個 pointer 空值(NULL)


之後 我們去 XXXDlg.h

標頭中

多 include 剛剛  編輯的   VideoInfo.h


之後來 定義相關的  對象





接著一樣去 對應的 cpp檔案中

請你去找  OnInitDialog() 的 函數


我們要在此 block 中  給他  new 一個 對象





這樣子的話呢

我們的 對象  就創建好了






接著我們來 寫 打開視頻文件的函數


回至OnBnClickedOpenvideo()   按鈕點擊事件函數




當我們確定這個 模態對話框之後
我們就可以抓到 視頻對應的路徑
我們就來打開這個視頻

並且把  Capture 指標   保存到我們的 成員變數裏頭去





首先我們來獲取  視頻的   寬度   及   高度

cvGetCaptureProperty透過此 函數能協助 opencv 開發者獲取 視頻文件的基本寬高屬性



此時 進行 編譯
你會發現  下方產生些 error message


法一.  試試看  調整  字符集



法二. 去解決 error  C4996  的 問題

去   專案  ----> 屬性 ---->  C/C++ ---> 前置處理器

定義  多增加

_CRT_SECURE_NO_WARNINGS



問題就可以成功被你解決了


可以建置成功   正常運行


萬歲



之後我們先來 創建一個   影像空間

每次讀視訊frame 時  把它存起來



這邊就  利用  cvCreateImage()來幫助我們   創建 影像

需要  大小(寬度 , 高度)   8位元 3 通道

等參數


測試一下按鈕  

發現  按鈕事件 有點出錯



換成 2.1 版本  在測一次







切記   Debug  和  Release 兩個都要重新設置一次  include路徑  lib路徑  和 輸入喔


這裡我試過   Debug  不能   Release 才可

而且要用2.1版本


T T  過程  實在   艱辛

目前已經實現   按鈕按下   確實可彈出對話框的功能

但是會出現   中文亂碼  





將在下節進行  問題解決分享








留言

張貼留言

這個網誌中的熱門文章

何謂淨重(Net Weight)、皮重(Tare Weight)與毛重(Gross Weight)

Architecture(架構) 和 Framework(框架) 有何不同?_軟體設計前的事前規劃的藍圖概念

(2021年度)駕訓學科筆試準備題庫歸納分析_法規是非題