MFC (VS2019)+ OpenCV,显示图片的3种方法
1 方法介绍
2 方法一:嵌套OpenCV窗口显示图片
2.1 建立供工程 添加控件
2.2 引用头文件
2.3 找到OnInitDialog()函数,在其中添加如下代码
2.4 在button触发函数中加入代码(就是你双击button进入的函数)
2.5 注意事项
3 方法二: 转换图片格式
3.1 MatToCImage格式转换 定义
3.2 OnPaint() 添加代码 画出图像
4 方法三: OpenCV图片保存后,再用FMC读取显示
4.1 添加代码
4.2 为什么要先保存在读取呢?
1 方法介绍
1、嵌套。 直接将OpenCV窗口嵌套到MFC的Pictrue Control控件中。此方法既能直接显示图片,也可直接使用OpenCV的鼠标按键事件,但对于鼠标滚轮事件只能使用MFC本地的滚轮函数。
2、转换。 将OpenCV读取或处理的图片转换格式,使之成为MFC的Pictrue Control控件可显示的图片格式。此方法每刷新一次图片便需要转换格式一次,比较麻烦,且只能使用MFC的鼠标事件。
3、保存。 将OpenCV读取或处理的图片保存为本地图片,然后用MFC读取图片的方法读取并显示。此方法是笨方法,在特定情况下使用,保存和读取图片比较耗时,但无需转换格式,同样只能使用MFC的鼠标事件。
2 方法一:嵌套OpenCV窗口显示图片
嵌套。直接将OpenCV窗口嵌套到MFC的Pictrue Control控件中。此方法既能直接显示图片,也可直接使用OpenCV的鼠标按键事件,但对于鼠标滚轮事件只能使用MFC本地的滚轮函数。
2.1 建立供工程 添加控件
新建工程,命名为 showRealVideo,创建好之后,自动生成以下文件

打开对话框后,
在工具箱选择picture control控件,并拖到对话框内,(右键修改属性),修改ID为IDC_PICTURE_STATIC,
添加一个Button按钮,修改ID为IDC_PICTURE_BUTTON,描述文字为 “显示图像”


双击button (“显示图像”)按钮,之后可以进入****Dlg.cpp,在里面进行如下修改代码


编写代码,只需修改MFCApplication1Dlg.cpp文件。
具体修改步骤如下:
2.2 引用头文件
在showRealVideoDlg.cpp中 添加opencv头文件

#include <opencv2/opencv.hpp>
//cvGetWindowHandle("ImageShow");//嵌套opencv窗口,需要使用下面头文件
#include<opencv2/highgui/highgui_c.h>
2.3 找到OnInitDialog()函数,在其中添加如下代码

// TODO: 在此添加额外的初始化代码
cv::namedWindow("ImageShow");//创建OpenCV窗口
HWND hWnd = (HWND)cvGetWindowHandle("ImageShow");//嵌套opencv窗口
HWND hParent = ::GetParent(hWnd);
::SetParent(hWnd,GetDlgItem(IDC_PICTURE_STATIC)->m_hWnd);
::ShowWindow(hParent,SW_HIDE);
2.4 在button触发函数中加入代码(就是你双击button进入的函数)

void CshowRealVideoDlg::OnBnClickedPictureButton()
{
// TODO: 在此添加控件通知处理程序代码
cv::Mat img = cv::imread("D:\Projects\test_Images\9.jpg");
CRect rect;
CWnd* pWnd = GetDlgItem(IDC_PICTURE_STATIC);//获取picture control控件
pWnd->GetClientRect(&rect);//控制图片的大小
cv::resize(img, img, cv::Size(rect.Width(), rect.Height()));//将图片resize,适用窗口尺寸
imshow("ImageShow", img);
}
![图片[1] - 【18】MFC入门到精通——MFC(VS2019)+ OpenCV 显示图片的3种方法 - 宋马](https://pic.songma.com/blogimg/20250718/210efc49a54644c0929cfeb6536143a4.png)

2.5 注意事项
如果图片没有resize,那么图片将以原尺寸显示,不会自适应窗口大小;
超出窗口以外的尺寸,就不会显示。
void CshowRealVideoDlg::OnBnClickedPictureButton()
{
// TODO: 在此添加控件通知处理程序代码
cv::Mat img = cv::imread("D:\Projects\test_Images\9.jpg");
CWnd* pWnd = GetDlgItem(IDC_PICTURE_STATIC);//获取picture control控件
imshow("ImageShow",img);
}

也可以将代码全部写在Button按钮函数中,
即将OnInitDialog()函数中自己添加的代码,剪切到OnBnClickedPictureButton()函数里。

3 方法二: 转换图片格式
转换。 将OpenCV读取或处理的图片转换格式,使之成为MFC的Pictrue Control控件可显示的图片格式。此方法每刷新一次图片便需要转换格式一次,比较麻烦,且只能使用MFC的鼠标事件。
1、新建MFC应用程序、添加Pictrue Control控件(同上)
2、引用头文件
在showRealVideoDlg.cpp中 添加opencv头文件,
并声明函数 void MatToCImage(Mat &mat, CImage &cImage);

#include <opencv2/opencv.hpp>
void MatToCImage(cv::Mat& mat, CImage& cImage);
3.1 MatToCImage格式转换 定义
//在CshowRealVideoDlg::.cpp最后添加MatToCImage函数定义:
//将OpenCV处理的Mat图片格式 转换为MFC的Pictrue Control控件可显示的CImage格式
void CshowRealVideoDlg::MatToCImage(cv::Mat& mat, CImage& cImage)
{
//create new CImage
int width = mat.cols;
int height = mat.rows;
int channels = mat.channels();
cImage.Destroy(); //clear
cImage.Create(width, height, 8 * channels); //默认图像像素单通道占用1个字节
//copy values
uchar* ps;
uchar* pimg = (uchar*)cImage.GetBits(); //A pointer to the bitmap buffer 指向位图缓冲区的指针
int step = cImage.GetPitch();
for (int i = 0; i < height; ++i)
{
ps = (mat.ptr<uchar>(i));
for (int j = 0; j < width; ++j)
{
if (channels == 1) //gray
{
*(pimg + i * step + j) = ps[j];
}
else if (channels == 3) //color
{
for (int k = 0; k < 3; ++k)
{
*(pimg + i * step + j * 3 + k) = ps[j * 3 + k];
}
}
}
}
}
3.2 OnPaint() 添加代码 画出图像
CshowRealVideoDlg::OnPaint()添加以下代码 画出图像
//////添加用户自己的代码
UpdateWindow();//刷新窗口
cv::Mat matImg = cv::imread("D:\Projects\test_Images\9.jpg"); //opencv读取图片
CRect rect;//定义矩形类
CWnd* pWnd = GetDlgItem(IDC_PICTURE_STATIC);//获取控件句柄
pWnd->GetClientRect(&rect); //获取句柄指向控件区域的大小
CDC* pDc = pWnd->GetDC();//获取picture的DC
cv::Mat resizedImg;
int win_w = rect.Width(), win_h = rect.Height();//获取窗口宽高
cv::resize(matImg, resizedImg, cv::Size(win_w, win_h));//将图片resize,适用窗口尺寸
int img_w = resizedImg.cols, img_h = resizedImg.rows;//获取图片宽高
CImage ImageCam;
MatToCImage(resizedImg, ImageCam);//转换图片格式
pDc->SetStretchBltMode(COLORONCOLOR);
ImageCam.Draw(pDc->m_hDC, 0, 0, win_w, win_h, 0, 0, img_w, img_h);//画出图片
ReleaseDC(pDc);
运行直接显示图片
![图片[2] - 【18】MFC入门到精通——MFC(VS2019)+ OpenCV 显示图片的3种方法 - 宋马](https://pic.songma.com/blogimg/20250718/d4256783c82d4efc81caa5424d63e501.png)
如果要使用,点击按钮 ,显示图片,
将上面OnPaint()里面添加的代码,复制到OnBnClickedPictureButton()函数里。
(OnPaint()里面添加的代码 删除或注释掉)
![图片[3] - 【18】MFC入门到精通——MFC(VS2019)+ OpenCV 显示图片的3种方法 - 宋马](https://pic.songma.com/blogimg/20250718/b3d0429053d94f89aae284a9647a17b7.png)
![图片[4] - 【18】MFC入门到精通——MFC(VS2019)+ OpenCV 显示图片的3种方法 - 宋马](https://pic.songma.com/blogimg/20250718/5f16b3d56e224d3484b4bb7b010434df.png)

4 方法三: OpenCV图片保存后,再用FMC读取显示
保存。 将OpenCV读取或处理的图片保存为本地图片,然后用MFC读取图片的方法读取并显示。此方法是笨方法,在特定情况下使用,保存和读取图片比较耗时,但无需转换格式,同样只能使用MFC的鼠标事件。
1、新建MFC应用程序、添加Pictrue Control控件(同上)
2、引用头文件
在showRealVideoDlg.cpp中 添加opencv头文件,
#include <opencv2/opencv.hpp>
4.1 添加代码
void CshowRealVideoDlg::OnBnClickedPictureButton()
{
// TODO: 在此添加控件通知处理程序代码
cv::Mat matImg = cv::imread("D:\Projects\test_Images\9.jpg");//opencv读取图片
cv::imwrite("D:\Projects\test_Images\9_new.jpg", matImg);//保存opencv图片
CImage img;
img.Load(L"D:\Projects\test_Images\9_new.jpg");//mfc读取图片
int img_w = img.GetWidth(), img_h = img.GetHeight();//获取图片宽高
UpdateWindow();//刷新窗口
CRect rect;//定义矩形类
CWnd* pWnd = GetDlgItem(IDC_PICTURE_STATIC);//获取控件句柄
pWnd->GetClientRect(&rect); //获取句柄指向控件区域的大小
CDC* pDc = pWnd->GetDC();//获取picture的DC
int win_w = rect.Width(), win_h = rect.Height();//获取窗口宽高
pDc->SetStretchBltMode(COLORONCOLOR);
img.Draw(pDc->m_hDC, 0, 0, win_w, win_h, 0, 0, win_w, win_h);//画出图片
ReleaseDC(pDc);
}
(程序中没有写 resize,所以图片没有自适应窗口大小)
如果不需要按钮,直接显示,将上面代码剪切到 OnPaint()里面

4.2 为什么要先保存在读取呢?
为什么要先保存在读取呢? 看似多余,实则不然。
直接MFC读取,会报错
CImage img;
img.Load(L"D:\Projects\test_Images\9.jpg");//mfc读取图片

![图片[5] - 【18】MFC入门到精通——MFC(VS2019)+ OpenCV 显示图片的3种方法 - 宋马](https://pic.songma.com/blogimg/20250718/cdda88fe63a34dc3a7e9a181f4fce39d.png)
将保存的图片 再次用OpenCV方式发打开显示,出错
cv::imwrite("D:\Projects\test_Images\9_new.jpg", matImg);//保存opencv图片
![图片[6] - 【18】MFC入门到精通——MFC(VS2019)+ OpenCV 显示图片的3种方法 - 宋马](https://pic.songma.com/blogimg/20250718/1afa8f1620c34fcb99c017e3b1d44a9c.png)
进一步查看,发现保存后的图片信息发生了变化,
![图片[7] - 【18】MFC入门到精通——MFC(VS2019)+ OpenCV 显示图片的3种方法 - 宋马](https://pic.songma.com/blogimg/20250718/cb1daa92612a4325aa13f1a37e3764d4.png)

【参考教程】
使用 MFC 和 OpenCV 实现实时摄像头视频显示
MFC(vs2013)+opencv+海康SDK_显示视频教程
VC++海康威视视频人数流量统计数据库连接
如何利用MFC及Opencv读入摄像头并显示画面
关于找不到cvGetWindowHandle()的解决方法
MFC+Opencv+显示图片的方法
MFC OpenCV,示图片的3种方法




















暂无评论内容