如何利用MFC及Opencv读入摄像头并显示画面

如何利用MFC及Opencv读入摄像头并显示画面?

       一般在做机器视觉项目或其他视频监控类的工程情况下,首先遇到的问题就是如何有效读入摄像头并显示,当然在opencv当中其实只用几个函数就可以解决,但是如果想显示在指定的界面,opencv就没那么方便了,本文是利用MFC制作一个简单的视频显示界面框架。如下图:



制作步骤及方法:

1、首先利用MFC应用程序向导新建一个对话框,然后在对话框中添加如上控件,两个Picture Control并更改ID为IDC_PIC_STATIC、IDC_PIC1_STATIC及三个按钮的名字。在实现过程中会用到一个文件CvvImage,因为本人使用的软件版本是Visual Studio 2013及Opencv 2.4.9,这个文件在当前的Opencv 2.4.9版本中被删除了,也不知道为什么要弃用这个。好了,这个文件网上有很多。下载好之后将文件复制到当前工程目录下,然后在当前项目界面的右边点击添加头文件CvvImage.h以及在源文件中点击添加CvvImage.cpp文件,如下图:

之后,就在OpenCameraDlg.cpp文件中添加头文件:

#include "opencv2/opencv.hpp"
#include "CvvImage.h"

以及using namespace std;  using namespace cv;


2、定义全局变量:

CvCapture* Capture;
CvCapture* m_Video;
IplImage* frame;
IplImage* m_grabframe;
CRect rect;
CDC *pDC;
HDC hDC;
CWnd *pwnd;
int ImgNum = 0;


3、在对话框中右键点击打开摄像头按钮,点击添加事件响应函数一栏,然后函数名命名为On_OpenCamera

void CShowPicture_MFCDlg::On_OpenCamera()
{
	// TODO: Add your command handler code here
	Capture = cvCreateCameraCapture(0); //
	if (Capture==0)
	{
		MessageBox(_T("无法连接摄像头!!!"));
		return;
	}

	frame = cvQueryFrame(Capture); //从摄像头或者文件中抓取并返回一帧
	pDC = GetDlgItem(IDC_PIC_STATIC)->GetDC();//GetDlgItem(IDC_PIC_STATIC)意思为获取显示控件的句柄(句柄就是指针),获取显示控件的DC
	GetDlgItem(IDC_PIC_STATIC)->GetClientRect(&rect);
	hDC = pDC->GetSafeHdc();//获取显示控件的句柄

	CvvImage m_CvvImage;
	m_CvvImage.CopyOf(frame, 1); //复制该帧图像   
	m_CvvImage.DrawToHDC(hDC, &rect); //显示到设备的矩形框内
	ReleaseDC(pDC);

	SetTimer(1, 25, NULL); //定时器,定时时间和帧率一致
}

4、添加定时器函数

右键单击对话框在类向导中选择映射消息一栏,然后双击选择WM_TIMER,如下图所示:


在其中添加响应函数代码:

void CShowPicture_MFCDlg::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: Add your message handler code here and/or call default
	pDC = GetDlgItem(IDC_PIC_STATIC)->GetDC();//GetDlgItem(IDC_PIC_STATIC)意思为获取显示控件的句柄(句柄就是指针),获取显示控件的DC

	GetDlgItem(IDC_PIC_STATIC)->GetClientRect(&rect);

	hDC = pDC->GetSafeHdc();//获取显示控件的句柄

	frame = cvQueryFrame(Capture); //从摄像头或者文件中抓取并返回一帧
	CvvImage m_CvvImage;
	m_CvvImage.CopyOf(frame, 1); //复制该帧图像   
	
	m_CvvImage.DrawToHDC(hDC, &rect); //显示到设备的矩形框内
	
	CDialogEx::OnTimer(nIDEvent);
}
5、添加关闭摄像头响应函数代码

      在关闭摄像头按钮上右键选择添加响应函数一栏,并命名为On_CloseCamera,代码如下:

void CShowPicture_MFCDlg::On_CloseCamera()
{
	// TODO: Add your command handler code here
	if (!Capture)
	{
		MessageBox(_T("没有打开摄像头!!!"));
		return;
	}
	
	cvReleaseCapture(&Capture);

	pDC = GetDlgItem(IDC_PIC_STATIC)->GetDC();//GetDlgItem(IDC_PIC_STATIC)意思为获取显示控件的句柄(句柄就是指针),获取显示控件的DC

	GetDlgItem(IDC_PIC_STATIC)->GetClientRect(&rect);

	hDC = pDC->GetSafeHdc();//获取显示控件的句柄

	frame = cvLoadImage("D:\\Documents\\Visual Studio 2013\\Projects\\beijing.jpg"); //图片读取路径可以自己设定
	CvvImage m_CvvImage;
	m_CvvImage.CopyOf(frame, 1); //复制该帧图像   
	m_CvvImage.DrawToHDC(hDC, &rect); //显示到设备的矩形框内
	ReleaseDC(pDC);
}

6、添加捕获图像响应函数代码

      在捕获图像按钮上右键单击选择添加事件响应函数一栏,并命名函数为On_CaptureImage,代码如下:

void CShowPicture_MFCDlg::On_CaptureImage()
{
	// TODO: Add your command handler code here
	
	//m_grabframe = cvQueryFrame(Capture);
	m_grabframe = frame;
	if (m_grabframe == 0)
	{
		MessageBox(_T("摄像头已关闭,无法捕捉图像!!!"));
		return;
	}
	
	CString ImagePath=TEXT("D:\\Documents\\Visual Studio 2013\\Projects\\标定图片\\");

	//CString ImagePath = _T("D:\\Documents\\Visual Studio 2013\\Projects\\标定图片\\");

	if (!PathIsDirectory(ImagePath))

	{
		CreateDirectory(ImagePath, 0);//不存在则创建
		MessageBox(_T("标定图片文件夹已创建!!!"));
		return;
	}
	char ImagesName[100];

	ImgNum = ImgNum + 1;

	sprintf_s(ImagesName, "%s%.2d%s", "D:\\Documents\\Visual Studio 2013\\Projects\\标定图片\\", ImgNum, ".jpg");
	
	IplImage * m_snap = cvCreateImage(cvGetSize(m_grabframe), m_grabframe->depth, m_grabframe->nChannels);
	cvCopy(m_grabframe, m_snap, NULL);
	cvSaveImage(ImagesName, m_snap); //把图像写入指定文件夹的文件中去

	//以下代码是完成图像的显示过程
	pDC = GetDlgItem(IDC_PIC1_STATIC)->GetDC();//GetDlgItem(IDC_PIC_STATIC)意思为获取显示控件的句柄(句柄就是指针),获取显示控件的DC

	GetDlgItem(IDC_PIC1_STATIC)->GetClientRect(&rect);

	hDC = pDC->GetSafeHdc();//获取显示控件的句柄

	CvvImage m_CvvImage;
	m_CvvImage.CopyOf(m_snap, 1); //复制该帧图像   
	m_CvvImage.DrawToHDC(hDC, &rect); //显示到设备环境的矩形框内
}

至此,整个过程就大致完成了,程序运行效果如下:



有什么疑问可以留言。。。谢谢!!!


  • 28
    点赞
  • 193
    收藏
    觉得还不错? 一键收藏
  • 66
    评论
评论 66
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值