【OpenCV】【MFC】圖片、視頻、攝像頭輸入響應【詳細圖解】
阿新 • • 發佈:2018-03-17
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】圖片、視頻、攝像頭輸入響應【詳細圖解】