记住新建项目后,要配置OpenCV环境!参考链接
做工程搭建框架什么的,基本的要熟练啊。
其中借鉴了ww老师的代码~
新建项目,命名:

点确定,然后,我习惯用基于对话框的: 
从工具箱拖几个控件出来: 

给图片随便命名个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.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换成你自己命名的项目名)
然后这个简单的框架就搭好啦! ^-^
















