如何使用MFC結合opencv實現影片撥放/暫停_class的使用x如何添加class_part1
會有需要對opencv 進行 UI 設計的開發者朋友們
選擇 Visual C++ MFC 應用程式
這篇會教大家如何實現 在 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 (*.*)|*.*||";
這裡 我們如果要用 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>
【第一階段 程式碼】
位於 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
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 過程 實在 艱辛
目前已經實現 按鈕按下 確實可彈出對話框的功能
但是會出現 中文亂碼
將在下節進行 問題解決分享
可以建置成功 正常運行
萬歲
之後我們先來 創建一個 影像空間
每次讀視訊frame 時 把它存起來
這邊就 利用 cvCreateImage()來幫助我們 創建 影像
需要 大小(寬度 , 高度) 8位元 3 通道
等參數
測試一下按鈕
發現 按鈕事件 有點出錯
切記 Debug 和 Release 兩個都要重新設置一次 include路徑 lib路徑 和 輸入喔
這裡我試過 Debug 不能 Release 才可
而且要用2.1版本
T T 過程 實在 艱辛
目前已經實現 按鈕按下 確實可彈出對話框的功能
但是會出現 中文亂碼
將在下節進行 問題解決分享
作者已經移除這則留言。
回覆刪除