1. 程式人生 > >【OpenCV】【MFC】圖片、視頻、攝像頭輸入響應【詳細圖解】

【OpenCV】【MFC】圖片、視頻、攝像頭輸入響應【詳細圖解】

tsp box 背景建模 img 有變 highgui 復制 creat int

記住新建項目後,要配置OpenCV環境!參考鏈接http://blog.csdn.net/zy122121cs/article/details/49180541

做工程搭建框架什麽的,基本的要熟練啊。

其中借鑒了ww老師的代碼~

新建項目,命名:技術分享圖片

點確定,然後,我習慣用基於對話框的:技術分享圖片然後點擊完成。

從工具箱拖幾個控件出來: 技術分享圖片 Combo Box組合框屬性設置:技術分享圖片

給圖片隨便命名個ID:技術分享圖片

如右圖所示,框架就搭好了:技術分享圖片

在Test01Dlg.h頭文件中添加如下:

//包含Opencv庫函數
#include <iostream>
#include <vector>
#include <io.h>
#include <direct.h>
#include <stdio.h>
#include <afxwin.h>

#include "opencv2/imgproc/imgproc.hpp"//圖像處理函數基本模塊,包括圖像濾波、圖像幾何變換、色彩空間轉換等
#include "opencv2/highgui/highgui.hpp"//視頻捕捉,圖像視頻讀取解碼,圖形交互
#include "afxwin.h"

using namespace std;
using namespace cv;

繼續在這裏加以下代碼,定義枚舉類型和私有變量:

private:
    //定義枚舉類型
    typedef enum {ememVIDEO_IN, emPICTURES_IN,emCAMERA_IN } READ_METHOD;//讀入方式,圖像0,分為相機1,視頻2讀入
    typedef enum {emVIEWBEF, emVIEWAFT } SHOW_WINDOW;//讀入窗口,0為第一個窗口,2為第二個窗口

    //全局私有變量
    VideoCapture cap_VidCam;//獲取相機輸入或者本地視頻
    cv::Mat m_frmBef;//原圖像
    int inputType;//選擇的數據輸入方式
int nImageWidth;//記錄或設置的圖像寬度 int nImageHeight;//記錄或設置的圖像高度 CString workDir;//圖像初始默認文件夾

初始化部分BOOL CTest01Dlg::OnInitDialog():

技術分享圖片
 1 BOOL CTest01Dlg::OnInitDialog()
 2 {
 3     CDialogEx::OnInitDialog();
 4 
 5     // 將“關於...”菜單項添加到系統菜單中。
 6 
 7     // IDM_ABOUTBOX 必須在系統命令範圍內。
 8     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 9     ASSERT(IDM_ABOUTBOX < 0xF000);
10 
11     CMenu* pSysMenu = GetSystemMenu(FALSE);
12     if (pSysMenu != NULL)
13     {
14         BOOL bNameValid;
15         CString strAboutMenu;
16         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
17         ASSERT(bNameValid);
18         if (!strAboutMenu.IsEmpty())
19         {
20             pSysMenu->AppendMenu(MF_SEPARATOR);
21             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
22         }
23     }
24 
25     // 設置此對話框的圖標。當應用程序主窗口不是對話框時,框架將自動
26     //  執行此操作
27     SetIcon(m_hIcon, TRUE);            // 設置大圖標
28     SetIcon(m_hIcon, FALSE);        // 設置小圖標
29 
30     // TODO: 在此添加額外的初始化代碼
31 
32     //初始化視頻數據讀入方法
33     com_InputStyle.SetCurSel(1);
34     inputType=emPICTURES_IN;
35 
36     //將OpenCV中的窗口顯示在MFC中
37     namedWindow("emVIEWBEF", WINDOW_AUTOSIZE);
38     HWND hWnd = (HWND) cvGetWindowHandle("emVIEWBEF");
39     HWND hParent = ::GetParent(hWnd);
40     ::SetParent(hWnd, GetDlgItem(IDC_FRMBEF)->m_hWnd);
41     ::ShowWindow(hParent, SW_HIDE);
42 
43     UpdateData( FALSE );//更新界面控件
44 
45     //將OpenCV中的窗口顯示在MFC中
46     workDir = F_InitWorkDir();//判斷Imgs及SaveFrame文件夾是否存在,不存在創建(ww)
47 
48     //初始化圖像顯示控件的圖像
49     CRect rect;
50     GetDlgItem(IDC_FRMBEF) ->GetClientRect( &rect );
51     m_frmBef = Mat::zeros(rect.Height(), rect.Width(), CV_8UC3);
52 
53     return TRUE;  // 除非將焦點設置到控件,否則返回 TRUE
54 }
View Code

void CTest01Dlg::OnPaint()部分:

技術分享圖片
 1 void CTest01Dlg::OnPaint()
 2 {
 3     if (IsIconic())
 4     {
 5         CPaintDC dc(this); // 用於繪制的設備上下文
 6 
 7         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
 8 
 9         // 使圖標在工作區矩形中居中
10         int cxIcon = GetSystemMetrics(SM_CXICON);
11         int cyIcon = GetSystemMetrics(SM_CYICON);
12         CRect rect;
13         GetClientRect(&rect);
14         int x = (rect.Width() - cxIcon + 1) / 2;
15         int y = (rect.Height() - cyIcon + 1) / 2;
16 
17         // 繪制圖標
18         dc.DrawIcon(x, y, m_hIcon);
19     }
20     else
21     {
22         CDialogEx::OnPaint();
23 
24         CDialog::UpdateWindow();                // 更新windows窗口,如果無這步調用,圖片顯示還會出現問題
25         if (!m_frmBef.empty())
26         {
27             F_ShowImage(emVIEWBEF,m_frmBef);    // 重繪圖片函數
28         }
29     }
30 }
View Code

單擊combo box組合框右鍵,給圖像輸入方式下拉框關聯變量:技術分享圖片

然後,給變量命個名:技術分享圖片

單擊組合框右鍵,選擇“添加事件處理程序” 技術分享圖片

給函數命名:技術分享圖片

然後編輯該函數,加一行代碼:技術分享圖片

類似的給“選擇”按鈕添加函數,代碼如下:

技術分享圖片
 1 // 根據選擇不同,分別做攝像頭輸入,視頻輸入,本地圖像組輸入背景建模處理
 2 void CTest01Dlg::OnBnChoosePicture()
 3 {
 4     // TODO: 在此添加控件通知處理程序代碼
 5     if (inputType==emPICTURES_IN)//(1)如選擇圖像輸入
 6     {
 7         StopCam();//停止相機工作
 8         string frmPath;
 9         frmPath = DoSelectFiles(
10             _T("*.bmp"), 
11             OFN_ENABLESIZING |OFN_EXPLORER | OFN_ALLOWMULTISELECT | OFN_HIDEREADONLY,
12             _T("image files (*.bmp; *.png; *.jpg) |*.bmp; *.png; *.jpg; *.jpeg| All Files (*.*) |*.*||"),
13             _T("選擇圖像序列"),
14             workDir+"\Imgs");
15         m_frmBef=cv::imread(frmPath);//讀取圖像
16         F_ShowImage(emVIEWBEF,m_frmBef);
17     }
18     else if(inputType==emCAMERA_IN)//(2)如選擇視頻輸入
19     {
20         //攝像頭輸入,設置攝像頭顯示分辨率
21         nImageWidth = 640;
22         nImageHeight = 480;
23         //打開第一個攝像頭
24         if ( !cap_VidCam.open(0) )
25         {
26             AfxMessageBox(_T("打開攝像頭失敗!"));
27             return;
28         }
29         cap_VidCam.set(CV_CAP_PROP_FRAME_WIDTH,  nImageWidth); //cv設置視頻流的幀寬度(只對攝像頭有效)
30         cap_VidCam.set(CV_CAP_PROP_FRAME_HEIGHT, nImageHeight);//cv設置視頻流的幀高度(只對攝像頭有效)
31         // 啟動攝像頭後顯示實時畫面
32         SetTimer(1, 10, NULL);    // 10ms 定時顯示
33         while(1) {
34             cap_VidCam >> m_frmBef;
35             if(m_frmBef.empty()) break;
36             F_ShowImage(emVIEWBEF,m_frmBef);
37             if(waitKey(20)>0)break;
38         }
39         cap_VidCam.release();
40     }
41     else//(3)如選擇視頻輸入
42     {
43         CStringA videoFiles;//存儲文件的名字
44         StopCam();//停止相機工作
45         videoFiles = DoSelectFiles(
46             _T("*.avi"), 
47             OFN_ENABLESIZING |OFN_EXPLORER | OFN_ALLOWMULTISELECT | OFN_HIDEREADONLY,
48             _T("video files (*.avi) |*.avi| All Files (*.*) |*.*||"),
49             _T("選擇視頻文件"),
50             workDir+"\Videos");
51         cap_VidCam.open(LPCSTR(videoFiles));//打開文件
52         SetTimer(1, 10, NULL);    // 10ms 定時顯示
53         while(1) {
54             cap_VidCam >> m_frmBef;
55             if(m_frmBef.empty()) break;
56             F_ShowImage(emVIEWBEF,m_frmBef);
57             if(waitKey(20)>0)break;
58         }
59         cap_VidCam.release();
60     }
61 }
View Code

繼續在下面添加 關閉攝像頭部分 代碼:

技術分享圖片
 1 //關閉攝像頭
 2 void CTest01Dlg::StopCam()
 3 {
 4     if (cap_VidCam.isOpened())
 5     {
 6         KillTimer(1);//該函數移除先前用SetTimer設置的定時器,在定時器使用完畢後移除定時器時使用
 7         // 對圖像數據清零
 8         m_frmBef = Scalar(0);
 9         cap_VidCam.release();//釋放VideoCapture對象
10     }
11 }
View Code

打開文件對話框相關代碼:

技術分享圖片
 1 //彈出打開文件對話框,選擇單個文件,並可以限制文件類型
 2 CStringA CTest01Dlg::DoSelectFiles(
 3     LPCTSTR    lpszDefExt,
 4     DWORD    dwFlags,
 5     LPCTSTR    lpszFilter,
 6     LPCSTR    lpstrTitle,
 7     LPCSTR    lpstrInitialDir )
 8 {
 9     CStringA selectedFile;
10     POSITION filePosition;
11 
12     CFileDialog dlg( TRUE, lpszDefExt, NULL, dwFlags, lpszFilter, NULL );    
13     dlg.m_ofn.lpstrFile[0] = NULL; 
14     dlg.m_ofn.lpstrTitle = lpstrTitle;
15     dlg.m_ofn.lpstrInitialDir = lpstrInitialDir;
16 
17     if( dlg.DoModal() == IDOK )
18     {
19         selectedFile = dlg.GetPathName();
20     }
21     return selectedFile;
22 }
23 //初始化(創建)程序運行所需的文件夾
24 CString CTest01Dlg::F_InitWorkDir()
25 {
26     CStringA strPath;
27      TCHAR path[_MAX_PATH];
28     TCHAR drive[_MAX_DRIVE];
29     TCHAR dir[_MAX_DIR];
30     TCHAR fname[_MAX_FNAME];
31     TCHAR ext[_MAX_EXT];
32     ::GetModuleFileName(AfxGetApp()->m_hInstance, path, _MAX_PATH);
33     _tsplitpath(path, drive, dir, fname, ext);
34 
35     strPath.Empty();
36     strPath += CString(drive);
37     strPath += CString(dir); 
38 
39     string saveDir = strPath;
40     saveDir += "/Imgs";
41     F_CheckDir(saveDir, true);
42     saveDir = strPath;
43     saveDir += "/Videos";
44     F_CheckDir(saveDir, true);
45     saveDir = strPath;
46     saveDir += "/SaveFrame";
47     F_CheckDir(saveDir, true);
48 
49     return CString(strPath);
50 }
51 //檢查文件夾是否存在
52 bool CTest01Dlg::F_CheckDir(const string dir, bool creatDir /* = false */)
53 {
54     bool RetVal = false;
55 
56     string fileName = dir;
57     fileName += "\\*";
58 
59     _finddata_t FileInfo;
60     long Handle = _findfirst(fileName.c_str(), &FileInfo);    
61 
62     if (Handle == -1L)
63     {
64         if (creatDir)
65         {
66             if(_mkdir(dir.c_str())==0)
67             {
68                 RetVal = true;
69             }
70         }
71     }
72     else
73     {
74         RetVal = true;
75         _findclose(Handle);
76     }
77     return RetVal;
78 }
View Code

顯示圖像部分 代碼:

技術分享圖片
 1 //顯示圖像,將要繪制的圖像 src 復制到 des,然後繪制到控件號為 ID 的 Picture 控件
 2 void CTest01Dlg::F_ShowImage(int type,Mat& src)
 3 {
 4     cv::Mat m_dst;
 5     CRect rect;
 6     GetDlgItem(IDC_FRMBEF)->GetClientRect(&rect);
 7     cv::Rect dst(rect.left,rect.top,rect.right,rect.bottom);
 8     cv::resize(src,m_dst,cv::Size(rect.Width(),rect.Height())); 
 9     if (type==emVIEWBEF)
10     {
11         imshow("emVIEWBEF", m_dst);
12     }
13 }
View Code

然後別忘了給“保存圖片”按鈕 添加響應函數:

技術分享圖片
 1 void CTest01Dlg::OnBnClickedSaveImage()
 2 {
 3     //定義可以保存的圖像類型後綴名
 4     CString csBMP="BMP Files(*.BMP)|*.BMP|";
 5     CString csJPG="JPG Files(*.JPG)|*.JPG|";
 6     CString csTIF="TIF Files(*.TIF)|*.TIF|";
 7     CString csPNG="PNG Files(*.PNG)|*.PNG|";
 8     CString csDIB="DIB Files(*.DIB)|*.DIB|";
 9     CString csPBM="PBM Files(*.PBM)|*.PBM|";
10     CString csPGM="PGM Files(*.PGM)|*.PGM|";
11     CString csPPM="PPM Files(*.PPM)|*.PPM|";
12     CString csSR ="SR  Files(*.SR) |*.SR|";
13     CString csRAS="RAS Files(*.RAS)|*.RAS||";
14 
15     CString csFilter=csBMP+csJPG+csTIF+csPNG+csDIB
16         +csPBM+csPGM+csPPM+csSR+csRAS;
17 
18     CString name[]={"","bmp","jpg","tif","png","dib",
19         "pbm","pgm","ppm","sr", "ras",""};
20 
21     CString strFileName;
22     CString strExtension;
23 
24     CString defaultDir =  workDir+"\SaveFrame";   //默認打開的文件路徑  
25     CString fileName = "new.bmp";         //默認保存的文件名 
26 
27     CFileDialog openFileDlg(false,".bmp", fileName, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, csFilter, NULL);
28     openFileDlg.m_ofn.lpstrInitialDir=defaultDir;//初始化路徑
29     //  文件存盤對話框
30     if (openFileDlg.DoModal()==IDOK ) //  輸入了文件名
31     {        
32         strFileName = openFileDlg.m_ofn.lpstrFile;
33         if (openFileDlg.m_ofn.nFileExtension == 0) //  無文件後綴
34         {  
35             strExtension = name[openFileDlg.m_ofn.nFilterIndex];
36             strFileName = strFileName + . + strExtension;
37             //  加文件後綴
38         }
39 
40         string s(strFileName.GetBuffer());
41         imwrite(s,m_frmBef);   //  當前畫面存盤  
42     }
43 }
View Code

給“關閉”按鈕添加響應函數:

技術分享圖片
1 void CTest01Dlg::OnBnClickedOk()
2 {
3     // TODO: 在此添加控件通知處理程序代碼
4     StopCam();//停止相機工作
5     CDialogEx::OnOK();
6 }
View Code

然後這個簡單的框架就搭好啦!

不知道我有沒有遺漏什麽......先分享我的代碼:https://pan.baidu.com/s/13UvC-Vdn7I95CNFOQD7iUQ

密碼:7eoo

雙擊Test01.sln就行了:技術分享圖片

【OpenCV】【MFC】圖片、視頻、攝像頭輸入響應【詳細圖解】