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换成你自己命名的项目名)

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

     

  • 相关阅读:
    关于Maya Viewport 2.0 API 开发的介绍视频
    春节大假
    Some tips about the life cycle of Maya thread pool
    Can I compile and run Dx11Shader for Maya 2015 on my side?
    How to get current deformed vertex positions in MoBu?
    想加入全球首届的 欧特克云加速计划吗?
    三本毕业(非科班),四次阿里巴巴面试,终拿 offer(大厂面经)
    mac、window版编辑器 webstorm 2016... 永久破解方法。
    node 搭载本地代理,处理web本地开发跨域问题
    js 一维数组,转成嵌套数组
  • 原文地址:https://www.cnblogs.com/GraceSkyer/p/8584331.html
Copyright © 2011-2022 走看看