OpenCV+MFC学习笔记(一):通过OpenCV读取图片在Picture Control中并自适应显示

在前面我们已经完成VS2022下安装和配置OpenCV环境参数下面我们开始小试身手,试试OpenCV读取图片到Picture Control中。网上的资料大多是基于C++控制台的,少有MFC桌面应用程序的。这里整理了三段代码,作为第一次的笔记。

分别是:MFC中对话框读取图片、OpenCV自适应绘图、OpenCV载入图片。

我们的场景如下图:左边是个Picture Control,右边是个Button,目标是通过Button来打开资源管理器对话框,选中图片,通过OpenCV载入到左边的Picture Control并将图片自适应展示。

第一步:打开资源管理器对话框,选择图片文件,返回文件路径以备用

CString CmyMFCDlg::fun_LoadImg()
{
	// TODO: 在此添加命令处理程序代码
	CString imagePath = L"";//选择的图片全路径
	BOOL isOpen = TRUE;		//是否打开(否则为保存)
	CString defaultDir = L"E:\\";	//默认打开的文件路径
	CString fileName = L"";			//默认打开的文件名
	CString filter = L"文件 (*.bmp; *.jpg;*.png)|*.bmp;*.jpg;*.png||";	//文件过虑的类型
	CFileDialog openFileDlg(isOpen, NULL, defaultDir + fileName, OFN_HIDEREADONLY | OFN_READONLY, filter, NULL);
	if (openFileDlg.DoModal() == IDOK)
	{
		imagePath = openFileDlg.GetPathName();
	}
	return imagePath;
}

第二步:OpenCV自适应绘图

#include "opencv2/opencv.hpp"
#include <opencv2/highgui/highgui_c.h>

using namespace cv;

……

//参数1:opencv即将读的图,
//参数2:需要展示的Picture Control的ID
void CmyMFCDlg::DrawMat(cv::Mat& img, UINT nID)
{
	cv::Mat imgTmp;
	CRect rect;
	GetDlgItem(nID)->GetClientRect(&rect);  // 获取控件大小
	cv::resize(img, imgTmp, cv::Size(rect.Width(), rect.Height()));// 缩放Mat并备份
	// 转一下格式 ,这段可以放外面,
	switch (imgTmp.channels())
	{
	case 1:
		cv::cvtColor(imgTmp, imgTmp, CV_GRAY2BGRA); // GRAY单通道
		break;
	case 3:
		cv::cvtColor(imgTmp, imgTmp, CV_BGR2BGRA);  // BGR三通道
		break;
	default:
		break;
	}
	int pixelBytes = imgTmp.channels() * (imgTmp.depth() + 1); // 计算一个像素多少个字节
	// 制作bitmapinfo(数据头)
	BITMAPINFO bitInfo;
	bitInfo.bmiHeader.biBitCount = 8 * pixelBytes;
	bitInfo.bmiHeader.biWidth = imgTmp.cols;
	bitInfo.bmiHeader.biHeight = -imgTmp.rows;
	bitInfo.bmiHeader.biPlanes = 1;
	bitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bitInfo.bmiHeader.biCompression = BI_RGB;
	bitInfo.bmiHeader.biClrImportant = 0;
	bitInfo.bmiHeader.biClrUsed = 0;
	bitInfo.bmiHeader.biSizeImage = 0;
	bitInfo.bmiHeader.biXPelsPerMeter = 0;
	bitInfo.bmiHeader.biYPelsPerMeter = 0;
	// Mat.data + bitmap数据头 -> MFC
	CDC* pDC = GetDlgItem(nID)->GetDC();
	::StretchDIBits(
		pDC->GetSafeHdc(),
		0, 0, rect.Width(), rect.Height(),
		0, 0, rect.Width(), rect.Height(),
		imgTmp.data,
		&bitInfo,
		DIB_RGB_COLORS,
		SRCCOPY
	);
	ReleaseDC(pDC);
}
//.h文件
#include "opencv2/opencv.hpp"
……
public:
	
	CString  fun_LoadImg();//第一步	
	void DrawMat(cv::Mat& img, UINT nID);//第二步
    afx_msg void OnBnClickedTest();	//第三步

第三步:展示OpenCV的图片

//button按钮响应事件
void CmyMFCDlg::OnBnClickedTest()
{
	USES_CONVERSION;//和下一行的W2A的目的一样,是为了CString类型转const String
	Mat src = imread(W2A(fun_LoadImg()), 1);
	DrawMat(src, IDC_STATIC);
}

我们编译下看看效果:

猜你喜欢

转载自blog.csdn.net/laolitou_1024/article/details/124002068