OpenCVMFC图片视频摄像头输入响应详细图解

Posted GraceSkyer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCVMFC图片视频摄像头输入响应详细图解相关的知识,希望对你有一定的参考价值。

记住新建项目后,要配置OpenCV环境!参考链接http://blog.csdn.net/zy122121cs/article/details/49180541

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

 

 其中借鉴了ww老师的代码~

新建项目,命名:

点确定,然后,我习惯用基于对话框的:然后点击完成。

从工具箱拖几个控件出来:    Combo Box组合框属性设置:

给图片随便命名个ID,再选择类型Frame:

 

 

如右图所示,框架就搭好了:

 

在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

 

注:以上代码均加在Test01Dlg.cpp中(Test01换成你自己命名的项目名)

 

然后这个简单的框架就搭好啦!    ^-^

 

以上是关于OpenCVMFC图片视频摄像头输入响应详细图解的主要内容,如果未能解决你的问题,请参考以下文章

Python+OpenCV4:读写输入和输出的简单实践(图片视频摄像头)

关于OpenCV调用摄像头及视频和图片的保存

[音视频处理] FFmpeg使用指北1-视频解码

视频的输入和输出

OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。(代

图解Java中的GC(分代收集器)