个人理解的原理:
设定时器按一定频率捕获图片,在一帧帧显示在MFC的picture控件上。(类似电影)所以管家还是如何把图片显示在picture控件上。这里直接粘代码。
// MFCVideoDlg.h : 头文件
//
#pragma once
//www
#include
#include
#include
#include "cv.h"
using namespace cv;
// CMFCVideoDlg 对话框
class CMFCVideoDlg : public CDialogEx
{
// 构造
public:
CMFCVideoDlg(CWnd* pParent = NULL); // 标准构造函数
// 对话框数据
enum { IDD = IDD_MFCVIDEO_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
//www
void CMFCVideoDlg::showMatImgToWnd(CWnd* pictureWnd, const Mat& disimg);
// 实现
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void On_OpenCamera();
protected:
// afx_msg LRESULT OnTimer(WPARAM wParam, LPARAM lParam);
public:
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg void On_CloseCamera();
afx_msg void On_CaptureImage();
};
// MFCVideoDlg.cpp : 实现文件
//
#include "stdafx.h"
#include "MFCVideo.h"
#include "MFCVideoDlg.h"
#include "afxdialogex.h"
//www
#include "opencv2/opencv.hpp"
#include "CvvImage.h"
using namespace cv;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMFCVideoDlg 对话框
//www
//CvCapture* Capture;
VideoCapture Capture;
Mat g_srcImage;
CvCapture* m_Video;
IplImage* frame;
IplImage* m_grabframe;
//www
Mat mm_grabframe;
bool isClose = true ;
CRect rect;
CDC *pDC;
HDC hDC;
CWnd *pwnd;
int ImgNum = 0;
CMFCVideoDlg::CMFCVideoDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CMFCVideoDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMFCVideoDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CMFCVideoDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, &CMFCVideoDlg::On_OpenCamera)
// ON_MESSAGE(timer, &CMFCVideoDlg::OnTimer)
ON_WM_TIMER()
ON_BN_CLICKED(IDC_BUTTON2, &CMFCVideoDlg::On_CloseCamera)
ON_BN_CLICKED(IDC_BUTTON3, &CMFCVideoDlg::On_CaptureImage)
END_MESSAGE_MAP()
// CMFCVideoDlg 消息处理程序
BOOL CMFCVideoDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
// 如果向对话框添加最小化按钮,则需要下面的代码
// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
// 这将由框架自动完成。
void CMFCVideoDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0);
// 使图标在工作区矩形中居中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMFCVideoDlg::OnQueryDragIcon()
{
return static_cast(m_hIcon);
}
void CMFCVideoDlg::On_OpenCamera()
{
// TODO: 在此添加控件通知处理程序代码
isClose = 1;
Capture.open(0);//创建一个摄像头对象并且指定摄像头编号,只有一个写0就可以
Capture>> g_srcImage;
//imshow("显示摄像头",g_srcImage);//这步真的能从摄像头获取一帧图像,但是并没有在指定MFC控件上显示
pwnd = GetDlgItem(IDC_PIC_STATIC);
showMatImgToWnd(pwnd,g_srcImage);
SetTimer(1, 25, NULL); //定时器,定时时间和帧率一致
}
//afx_msg LRESULT CMFCVideoDlg::OnTimer(WPARAM wParam, LPARAM lParam)
//{
// return 0;
//}
void CMFCVideoDlg::OnTimer(UINT_PTR nIDEvent)
{
TODO: 在此添加消息处理程序代码和/或调用默认值
Capture>> g_srcImage;
pwnd = GetDlgItem(IDC_PIC_STATIC);
showMatImgToWnd(pwnd,g_srcImage);
CDialogEx::OnTimer(nIDEvent);
}
void CMFCVideoDlg::On_CloseCamera()
{
g_srcImage = imread("E:\\vs2012\\MFCVideo\\MFCVideo\\1.jpg");
pwnd = GetDlgItem(IDC_PIC_STATIC);
showMatImgToWnd(pwnd,g_srcImage);
isClose = 0;
KillTimer(1);
//if (!Capture)
//{
// MessageBox(_T("没有打开摄像头!!!"));
// return;
//}
//
}
void CMFCVideoDlg::On_CaptureImage()
{
// TODO: 在此添加控件通知处理程序代码
if (isClose == false)
{
MessageBox(_T("摄像头已关闭,无法捕捉图像!!!"));
return;
}
CString ImagePath=TEXT("E:\\vs2012\\MFCVideo\\MFCVideo\\标定图片\\");
if (!PathIsDirectory(ImagePath))
{
CreateDirectory(ImagePath, 0);//不存在则创建
MessageBox(_T("标定图片文件夹已创建!!!"));
return;
}
char ImagesName[100];
ImgNum = ImgNum + 1;
sprintf_s(ImagesName, "%s%.2d%s", "E:\\vs2012\\MFCVideo\\MFCVideo\\标定图片\\", ImgNum, ".jpg");
imwrite(ImagesName,g_srcImage);//把图像写入指定文件夹的文件中去
//以下代码是完成图像的显示过程
pwnd = GetDlgItem(IDC_PIC1_STATIC);
showMatImgToWnd(pwnd,g_srcImage);
}
void CMFCVideoDlg::showMatImgToWnd(CWnd* pictureWnd, const Mat& disimg)
{
if (disimg.empty()) return ;
static BITMAPINFO *bitMapinfo = NULL;
static bool First = TRUE;
if (First)
{
BYTE *bitBuffer = new BYTE[40 + 4 * 256];//开辟一个内存区域
if (bitBuffer == NULL)
{
return;
}
First = FALSE;
memset(bitBuffer, 0, 40 + 4 * 256);
bitMapinfo = (BITMAPINFO *)bitBuffer;
bitMapinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitMapinfo->bmiHeader.biPlanes = 1;
for (int i = 0; i<256; i++)
{ //颜色的取值范围 (0-255)
bitMapinfo->bmiColors[i].rgbBlue = bitMapinfo->bmiColors[i].rgbGreen = bitMapinfo->bmiColors[i].rgbRed = (BYTE)i;
}
}
bitMapinfo->bmiHeader.biHeight = -disimg.rows;//www:难道是位图原点在左上角,所以要反一下
bitMapinfo->bmiHeader.biWidth = disimg.cols;
bitMapinfo->bmiHeader.biBitCount = disimg.channels() * 8;
CRect drect;
pictureWnd->GetClientRect(drect); //pWnd指向CWnd类的一个指针
CClientDC dc(pictureWnd);
HDC hDC = dc.GetSafeHdc(); //HDC是Windows的一种数据类型,是设备描述句柄;
SetStretchBltMode(hDC, COLORONCOLOR);
StretchDIBits(hDC,
0,
0,
drect.right, //显示窗口宽度
drect.bottom, //显示窗口高度
0,
0,
disimg.cols, //图像宽度
disimg.rows, //图像高度
disimg.data,
bitMapinfo,
DIB_RGB_COLORS,
SRCCOPY);
}