当前位置: 首页 > article >正文

用OpenCV与MFC写一个图像格式转换及简单处理程序

          打开不同格式的图形文件,彩色装灰度图像、锐化、高斯滤波、边界检测及将其存储为需求格式是图像处理的最基本的操作。如果单纯用MFC编程,是一个令人头痛的事情,有不少的代码量。可用OpenCV与MFC编程就变得相对简单。下面来详细演示这一编程操作。

一  在VS2022中创建一个MFC对话框Project

      在V2022中用MFC向导创建一个对话框Project,在对话框中添加如下按钮控件:

修改控件ID

“打开图像文件”的ID修改如下:

“彩色图像转换为灰度图像”的ID修改如下:

“图像锐化“的ID修改如下: 

“图像高斯滤波“的ID修改如下:

“图像边缘检测“的ID修改如下:

 

“图像文件另存为“的ID修改如下:

”退出“的ID修改如下:

二   设置Project属性

          设置使用字符集   使用“Unicode字符集”,如下:

    设置Debug|X64附加依赖库

设置Release|X64 附加依赖库

三 包含OpenCV 相关头文件,并定义变量

   在对话框头文件中包含OpenCV相关头文件如下:

// MFCDiaologOpenCVDlg.h: 头文件
//

#pragma once
#include <opencv2/opencv.hpp>

using namespace cv;

在头文件中定义以下私有变量:

class CMFCDiaologOpenCVDlg : public CDialogEx
{
// 构造
public:
	CMFCDiaologOpenCVDlg(CWnd* pParent = nullptr);	// 标准构造函数
private:
	Mat src;
	CWnd* pWnd;
	CRect mRec;
	CPoint mPoint;
	CString m_Path;
	CString m_strEx;
	CString m_strName;
	String m_str;
		
// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_MFCDIAOLOGOPENCV_DIALOG };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedOpen();
	afx_msg void OnBnClickedCvt();
	afx_msg void OnBnClickedSaveas();
	afx_msg void OnBnClickedOk();
};
四 编写程序代码

     为”打开图像文件”控件添加如下响应代码:

void CMFCDiaologOpenCVDlg::OnBnClickedOpen()
{
	// TODO: 在此添加控件通知处理程序代码
	CFileDialog fdlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("All files(*.*)|*.*||"));
	if (fdlg.DoModal() == IDOK)
	{
		m_Path = fdlg.GetPathName();
		m_strEx = fdlg.GetFileExt();
		m_strName = fdlg.GetFileName();

		m_Path.ReleaseBuffer();
		m_strEx.ReleaseBuffer();
		m_strName.ReleaseBuffer();
	}
	if (m_strEx == "BMP" || m_strEx == "bmp" || m_strEx == "TIF" || m_strEx == "tif" || m_strEx == "PNG" || m_strEx == "png" || m_strEx == "jpg" || m_strEx == "JPG")
	{
		pWnd = GetDlgItem(IDC_PICSHOW);
		pWnd->GetClientRect(&mRec);
		mPoint = mRec.TopLeft();
		pWnd->ClientToScreen(&mPoint);
		m_str = CT2A(m_Path);
		src = imread(m_str);
		if(src.empty())
			MessageBox(_T("打开图像文件失败!"));
		else
		{
			m_str = CT2A(m_strName);
			namedWindow(m_str, WINDOW_AUTOSIZE);
			moveWindow(m_str, mPoint.x, mPoint.y);
			imshow(m_str, src);
		}
	}
	else
	{
		MessageBox(_T("你打开的文件不是本程序支持的图像文件!"));
	}
}

    为”彩色图像转换为灰度图像”控件添加如下响应代码:

void CMFCDiaologOpenCVDlg::OnBnClickedCvt()
{
	// TODO: 在此添加控件通知处理程序代码
	Mat des;
	cvtColor(src, des, COLOR_BGR2GRAY, 0);

	destroyAllWindows();
	m_str = CT2A(m_strName);
	namedWindow(m_str, WINDOW_AUTOSIZE);
	moveWindow(m_str, mPoint.x, mPoint.y);
	imshow(m_str, des);
	src.release();
	des.copyTo(src);
}

为”图像锐化”控件添加如下响应代码:

void CMFCDiaologOpenCVDlg::OnBnClickedSharp()
{
	// TODO: 在此添加控件通知处理程序代码
	Mat sharpenKernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
	filter2D(src, src, -1, sharpenKernel);
	destroyAllWindows();
	namedWindow(m_str, WINDOW_AUTOSIZE);
	moveWindow(m_str, mPoint.x, mPoint.y);
	imshow(m_str, src);
}

 为”图像高斯滤波”控件添加如下响应代码:

void CMFCDiaologOpenCVDlg::OnBnClickedGausFilter()
{
	// TODO: 在此添加控件通知处理程序代码
	Mat gaussianKernel = getGaussianKernel(5, 2);
	filter2D(src, src, -1, gaussianKernel);
	destroyAllWindows();
	namedWindow(m_str, WINDOW_AUTOSIZE);
	moveWindow(m_str, mPoint.x, mPoint.y);
	imshow(m_str, src);
}

为”图像边缘检测”控件添加如下响应代码: 

void CMFCDiaologOpenCVDlg::OnBnClickedEdgeDetect()
{
    // TODO: 在此添加控件通知处理程序代码
    Mat kernel1 = (Mat_<char>(3, 3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);
    Mat kernel2 = (Mat_<char>(3, 3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);
    Mat dst1, dst2;
    filter2D(src, dst1, -1, kernel1);
    filter2D(src, dst2, -1, kernel2);
    dst1 = abs(dst1);
    dst2 = abs(dst2);
    src.release();
    add(dst1, dst2, src);
    destroyAllWindows();
    namedWindow(m_str, WINDOW_AUTOSIZE);
    moveWindow(m_str, mPoint.x, mPoint.y);
    imshow(m_str, src);
}

为”图像另存为”控件添加如下响应代码:

void CMFCDiaologOpenCVDlg::OnBnClickedSaveas()
{
	// TODO: 在此添加控件通知处理程序代码
	CFileDialog fdlg(FALSE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("All files(*.*)|*.*||"));
	if (fdlg.DoModal() == IDOK)
	{
		m_Path = fdlg.GetPathName();
		m_strEx = fdlg.GetFileExt();
		m_strName = fdlg.GetFileName();

		m_Path.ReleaseBuffer();
		m_strEx.ReleaseBuffer();
		m_strName.ReleaseBuffer();
	}
	if (m_strEx == "BMP" || m_strEx == "bmp" || m_strEx == "TIF" || m_strEx == "tif" || m_strEx == "PNG" || m_strEx == "png" || m_strEx == "jpg" || m_strEx == "JPG")
	{
		m_str = CT2A(m_Path);
		imwrite(m_str, src);
		src = imread(m_str);
		destroyAllWindows();
		m_str = CT2A(m_strName);
		namedWindow(m_str, WINDOW_AUTOSIZE);
		moveWindow(m_str, mPoint.x, mPoint.y);
		imshow(m_str, src);
	}
	else
	{
		MessageBox(_T("你输入的文件格式不是不是本程序支持的图像文件格式,不能保存!"));
	}

}

为”退出”控件添加如下响应代码:

void CMFCDiaologOpenCVDlg::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码
	//destroyAllWindows();
	CDialogEx::OnOK();
}
五   程序试运行

      按“Ctrl+F5”试运行,程序跑起来了,如下:

 

点击“打开图像文件按钮”,进入到打开图像界面,如下:

  选中1.bmp后点击打开,结果如下:

点击“图像另存为” 按钮,进入图像存储界面,如下:

点击“保存”,弹出确认对话框,如下:

点击是,回到原界面后,如下:

显示的图像变成了2.png,在打开图像时看到的2.png是灰度图像,现在变成了彩色图像。

点击“彩色图像转换为灰度图像”,结果如下:

点击图像另存为,进入图像存储界面

在文件名对话框中输入3.tif,点击保存,结果如下:

显示的图像变成了3.tif,再点击“打开图像文件”按钮,去看一下存储的文件是否存在,进入到打开文件界面,如下:

可以看到前面存储的3.tif文件确实存在。

关闭对话框,点“退出”,退出程序。

重新按“Ctrl+F5”运行程序,再试下打开3.tif这个存储文件,看能否正常打开,打开结果,如下:

        确实能打开。说明控件响应程序没有问题。

       点击“打开图想文件” ,然后打开如下图像。

点击“图像锐化”,结果如下:

点击“图像边缘检测”,结果如下:

虽然效果不是让人满意,但确实检测到了边界。

再打开一张图像,如下:

点击“图像锐化”后的效果如下:

再点击“图像高斯滤波”,结果如下:

      几行代码就完成了图像转换及图像的简单处理,可以看出OpenCV确实强悍。值得我们去深入学习与研究。

       这个程序还存在些问题,当激活别的运行程序后,再回到这个对话框程序,可能回发现打开的图片不见了,或者跑到别的地方去了,这是MFC界面编程问题,如何处理,这里这里暂不做讨论。留到后面的机器视觉编程实战部分再做介绍。

       此程序的编程环境:Win10+VS2022+OpenCV4.8,示例程序的源代码已上传到CSDN,链接为:https://download.csdn.net/download/billliu66/88593238


http://www.kler.cn/news/159747.html

相关文章:

  • Win11安装Docker
  • 【数据库】数据库多种锁模式,共享锁、排它锁,更新锁,增量锁,死锁消除与性能优化
  • 二叉树链式结构的实现——C语言
  • PG 常用维护性 SQL
  • git报错invalid object xxx和unable to read tree xxxxxx
  • 播放器开发(六):音频帧处理并用SDL播放
  • 三部曲法求未定式极限中的1无穷次方型
  • 【探索Linux】—— 强大的命令行工具 P.20(多线程 | 线程互斥 | 互斥锁 | 死锁 | 资源饥饿)
  • 【教程】Conda更换镜像源安装pytorch
  • Git篇如何搭建自己的git仓库
  • 前端知识笔记(二十五)———JS中的异步编程与Promise
  • 如何给自己的网站加密
  • C++大小写字母转换
  • 【PID学习笔记 6 】控制系统的性能指标之二
  • Zookeeper 安装与部署
  • Java 中最常用的设计模式之一,工厂模式模式的写法,
  • 不同场景下如何构建高品质的SD-WAN网络?
  • 【libcurl库】安装及其编程访问百度首页(一)
  • threejs WebGLRenderer 像素比对画布大小的影响
  • 如何查看linux块大小
  • 基于Spring,SpringMVC,MyBatis的校园二手交易网站
  • 【泛型-胡乱砍】
  • php5和php7有什么区别
  • 用友U8 Cloud SQL注入漏洞复现
  • Web(7)内网渗透
  • Matlab进阶绘图第35期—双特征渲染三维散点图
  • 前端:HTML鼠标样式及其对应的CSS属性值
  • win10与 vm虚拟机win7共享文件夹创建
  • 【头歌系统数据库实验】实验5 SQL的多表查询-1
  • Day42| Leetcode 416. 分割等和子集