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

news2025/1/24 11:38:02

          打开不同格式的图形文件,彩色装灰度图像、锐化、高斯滤波、边界检测及将其存储为需求格式是图像处理的最基本的操作。如果单纯用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.coloradmin.cn/o/1289661.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

股票所有均线都跌破应该怎么操作?

股票跌破所有均线说明股票趋势是走坏的&#xff0c;并且均线对股票起到压制作用&#xff0c;投资者有两种操作方式&#xff0c;第一种是割肉换股&#xff0c;投资者可以在股票小幅上涨时&#xff0c;将股票全部卖出&#xff0c;再买入最近比较强势的个股&#xff0c;赚取收益、…

ubuntu安装MySQL8

1.下载mysql8 MySQL :: Download MySQL Installer (Archived Versions) 选择对应的mysql版本和对应的ubuntu版本图即可 2.下载后上传到sftp文件夹中&#xff0c;然后通过以下命令解压 tar -xvf mysql-server_8.0.29-1ubuntu20.04_amd64.deb-bundle.tar 3.依次安装即可 &#…

数据结构与算法之美学习笔记:32 | 字符串匹配基础(上):如何借助哈希算法实现高效字符串匹配?

标题 前言BF 算法RK 算法解答开篇 & 内容小结 前言 本节课程思维导图&#xff1a; 从今天开始&#xff0c;我们来学习字符串匹配算法。我们用的最多的比如 Java 中的 indexOf()&#xff0c;Python 中的 find() 函数等&#xff0c;它们底层就是依赖接下来要讲的字符串匹配算…

解决:spring boot+mybatis进行增删改查的时候,接收到前端数据,并且执行成功了,但是数据库里面添加的内容都是空值

在写spring boot整合mybatis的时候&#xff0c;我在Apifox里面测试&#xff0c;数据也传递过去了&#xff0c;后端服务器也接收到了参数&#xff0c;就是数据库里面添加的都是空值&#xff1f;&#xff1f;&#xff1f; 前端接收到了数据&#xff0c;并且没有报错 Apifox里面也…

【微服务】spring循环依赖深度解析

目录 一、循环依赖概述 1.2 spring中的循环依赖 二、循环依赖问题模拟 2.1 循环依赖代码演示 2.2 问题分析与解决 2.2.1 使用反射中间容器 三、spring循环依赖问题解析 3.1 spring中的依赖注入 3.1.1 field属性注入 3.1.2 setter方法注入 3.1.3 构造器注入 3.2 spri…

Python中字符串列表的相互转换详解

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 在Python编程中&#xff0c;经常会遇到需要将字符串列表相互转换的情况。这涉及到将逗号分隔的字符串转换为列表&#xff0c;或者将列表中的元素连接成一个字符串。本文将深入讨论这些情景&#xff0c;并提供丰富…

JAVA网络编程——BIO、NIO、AIO深度解析

I/O 一直是很多Java同学难以理解的一个知识点&#xff0c;这篇帖子将会从底层原理上带你理解I/O&#xff0c;让你看清I/O相关问题的本质。 1、I/O的概念 I/O 的全称是Input/Output。虽常谈及I/O&#xff0c;但想必你也一时不能给出一个完整的定义。搜索了谷哥欠&#xff0c;发…

吉利护航,宣称比友商“更懂车”,魅族造车的底气与底色

继小米、华为后&#xff0c;又一家手机厂商宣布跨界造车。 在近日举办的2023魅族秋季无界生态发布会上&#xff0c;星纪魅族集团&#xff08;下称“魅族”&#xff09;董事长兼CEO沈子瑜宣布&#xff0c;魅族正式进入汽车市场&#xff0c;将在2024年第一季度启动“DreamCar共创…

CoreDNS实战(十一)-分流与重定向

本文主要介绍了目前CoreDNS服务在外部域名递归结果过程中出现的一些问题以及使用dnsredir插件进行分流和alternate插件进行重试优化的操作。 1 自建DNS服务现状 一般来说&#xff0c;无论是bind9、coredns、dnsmasq、pdns哪类dns服务器&#xff0c;我们自建的监听在UDP53端口…

微信怎么自动跟圈?怎么一键转发好友的朋友圈?

做私域、微商的小伙伴们每天需要发许多朋友圈来推广产品&#xff0c;一个人手上就有好几个微信的话&#xff0c;每个微信都要发朋友圈的话&#xff0c;非常麻烦。有没有一键转发同步好友朋友圈的功能呢&#xff1f; 朋友圈互动 1&#xff09;查看朋友圈&#xff1a;可通过昵称…

智能优化算法应用:基于梯度算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于梯度算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于梯度算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.梯度算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

识别和修复网站上损坏链接的最佳实践

如果您有一个网站&#xff0c;我们知道您花了很多时间在它上面&#xff0c;以使其成为最好的资源。如果你的链接不起作用&#xff0c;你的努力可能是徒劳的。您网站上的断开链接可能会以两种方式损害您的业务&#xff1a; 它们对企业来说是可怕的&#xff0c;因为当消费者点击…

接上文 IBM ServeRAID M1015阵列卡 支持RAID5

模块到了&#xff0c;由于着急测试没直接拍照&#xff0c;就是一个跟指甲盖大小的模块&#xff0c;直接安装到阵列卡U1接口上&#xff0c;&#xff0c;不知道U1是哪个位置的参考前文&#xff0c;安装到机器上之后的图片如下 启动服务器&#xff0c;进入WebBIOS&#xff0c;选择…

Databend 如何利用 GPT-4 进行质量保证

背景 在数据库行业&#xff0c;质量是核心要素。 Databend 的应用场景广泛&#xff0c;特别是在金融相关领域&#xff0c;其查询结果的准确性对用户至关重要。因此&#xff0c;在快速迭代的过程中&#xff0c;如何确保产品质量&#xff0c;成为我们面临的重大挑战。 随着 Da…

微信小程序基础bug

1.苹果11手机小程序请求数据不显示 设置-》隐私-》分析与改进-》开启 ”与开发者共享“ 2.<navigator>组件回退delta不成功 tabBar 页面是不能实现后退的效果的. 因为, 当我们跳转到 tabBar 页面&#xff0c;会关闭其他所有非tabBar 页面,所以当处于 tabBar 页面时, 无…

Spring Cache【娓娓道来】

目录​​​​​​​ 1.自我介好&#x1f633;&#x1f633;&#x1f633; 2.常用注解 &#x1f495;&#x1f495;&#x1f495; 3.EnableCaching&#x1f926;‍♂️&#x1f926;‍♂️&#x1f926;‍♂️ 4.CachePut&#x1f937;‍♀️&#x1f937;‍♀️&#x1f93…

7.上传project到服务器及拉取服务器project到本地、更新代码冲突解决

1.上传project到SVN服务器 1.在eclipse中&#xff0c;从show view里调出SVN资源库视图 2.在SVN资源库窗口的空白位置右键选择新建资源库位置 3.填好服务器的地址 4.资源库导入成功,SVN资源库视图下出现导入的资源库 5.新建project 6.写好project的初始版本 7.右键project --&…

C++基础 -46- 类的静态函数成员

类的静态函数成员可以不创建类直接访问 #include "iostream"using namespace std;class base {public:static void show(){cout << "hello world" << endl;} };int main() {base::show(); }类的静态函数成员不能访问非静态成员 class base…

GPT实现开放式世界游戏实践【生化危机】

最近开始研究如何基于GPT构建一个游戏引擎&#xff0c;于是先从简单的文字游戏开始探索。 从最简单的选择机制、故事机制&#xff0c;完善成一个包括天气、事件、技能、属性、伙伴、建造系统的-生化危机版文字游戏-。 我唯一的体验是&#xff1a;AI游戏&#xff0c;大有可为! …

【LVS实战】04 LVS+Keepalived实现负载均衡高可用

一、介绍 Keepalived 是一个用于 Linux 平台的高可用性软件。它实现了虚拟路由器冗余协议 (VRRP) 和健康检查功能&#xff0c;可以用于确保在多台服务器之间提供服务的高可用性。Keepalived 可以检测服务器的故障&#xff0c;并在主服务器宕机时&#xff0c;自动将备份服务器提…