zoukankan      html  css  js  c++  java
  • 【OpenCV】【MFC】图片、视频、摄像头输入响应【详细图解】

    记住新建项目后,要配置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换成你自己命名的项目名)

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

     

  • 相关阅读:
    Sql语句创建表
    刷新、关闭等误操作造成当前页面信息的丢失的解决方案
    asp.net文本框中只允许用户输入数字
    为每个用户创建文件夹,并实现图片上传
    在updatepanel中使用fileupload控件
    解决弹出提示框后字体变大的BUG
    SQL 2005新增的几个函数之学习
    .net实现单张图片的上传
    数据分页
    所谓三门问题
  • 原文地址:https://www.cnblogs.com/GraceSkyer/p/8584331.html
Copyright © 2011-2022 走看看