win10企业版
Microsoft Visual Studio Community 2019 版本 16.9.5
OpenCV440
在MFC项目中显示图片有三种方式
1、嵌套。直接将OpenCV窗口嵌套到MFC的Pictrue Control控件中。此方法既能直接显示图片,也可直接使用OpenCV的鼠标按键事件,但对于鼠标滚轮事件只能使用MFC本地的滚轮函数。
2、转换。将OpenCV读取或处理的图片转换格式,使之成为MFC的Pictrue Control控件可显示的图片格式。此方法每刷新一次图片便需要转换格式一次,比较麻烦,且只能使用MFC的鼠标事件。
3、保存。将OpenCV读取或处理的图片保存为本地图片,然后用MFC读取图片的方法读取并显示。此方法是笨方法,在特定情况下使用,保存和读取图片比较耗时,但无需转换格式,同样只能使用MFC的鼠标事件。
首先
- 配置好opencv后,添加按钮,保证opencv运行正常
按钮事件中添加代码
// TODO: 在此添加控件通知处理程序代码
Mat img = imread(R"(png\cropped-OpenCV_logo_white_300x.png)");
imshow(“img”, img);
waitKey(0);
- 嵌套
在OnInitDialog()中添加如下代码:
/第一种方式 PictureControl 嵌套imshow显示Mat/
namedWindow(“ImageShow”);//创建OpenCV窗口
HWND hWnd = (HWND)cvGetWindowHandle(“ImageShow”);//嵌套opencv窗口,需要#include <opencv2/highgui/highgui_c.h>
HWND hParent = ::GetParent(hWnd);
::SetParent(hWnd, GetDlgItem(IDC_STATIC)->m_hWnd);
::ShowWindow(hParent, SW_HIDE);
//获取PictureControl控件大小
CRect rc;
CWnd* pWnd = GetDlgItem(IDC_STATIC);//参数为控件ID
pWnd->GetClientRect(&rc);//rc为控件的大小。
//根据父窗体大小设置opencv显示窗口大小
resizeWindow(“ImageShow”, Size(rc.Width(), rc.Height()));
在按钮事件函数中添加如下代码
// TODO: 在此添加控件通知处理程序代码
Mat mat = imread(R"(png\cropped-OpenCV_logo_white_300x.png)");
imshow(“ImageShow”, mat);//opencv显示图片
waitKey(1);
效果
-
转换
添加转换函数
//转换函数
void MatToCImage(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(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];
}
}
}
}
}
在按钮事件函数中添加如下代码
// TODO: 在此添加控件通知处理程序代码
CRect rect;//定义矩形类
CWnd pWnd = GetDlgItem(IDC_STATIC);//获取控件句柄
pWnd->GetClientRect(&rect); //获取句柄指向控件区域的大小
CDC pDc = pWnd->GetDC();//获取picture的DCMat mat = imread(R"(png\cropped-OpenCV_logo_white_300x.png)");
int win_w = rect.Width(), win_h = rect.Height();//获取窗口宽高
int img_w = mat.cols, img_h = mat.rows;//获取图片宽高
CImage ImageCam;
MatToCImage(mat, ImageCam);//转换图片格式
pDc->SetStretchBltMode(COLORONCOLOR);
ImageCam.Draw(pDc->m_hDC, 0, 0, win_w, win_h, 0, 0, win_w, win_h);//画出图片
ReleaseDC(pDc);
效果
-
保存
在按钮事件函数中添加如下代码
// TODO: 在此添加控件通知处理程序代码
Mat mat = imread(R"(png\cropped-OpenCV_logo_white_300x.png)");//opencv读取图片
bool b=imwrite(R"(png\temp.png)", mat);//保存opencv图片CImage cimage;
cimage.Load(_T(“png\temp.png”));//mfc读取图片
int img_w = cimage.GetWidth(), img_h = cimage.GetHeight();//获取图片宽高
UpdateWindow();//刷新窗口
CRect rect;//定义矩形类
CWnd* pWnd = GetDlgItem(IDC_STATIC);//获取控件句柄
pWnd->GetClientRect(&rect); //获取句柄指向控件区域的大小
CDC* pDc = pWnd->GetDC();//获取picture的DC
int win_w = rect.Width(), win_h = rect.Height();//获取窗口宽高
pDc->SetStretchBltMode(COLORONCOLOR);
cimage.Draw(pDc->m_hDC, 0, 0, win_w, win_h, 0, 0, win_w, win_h);//画出图片
ReleaseDC(pDc);
效果