C++调用OpenCV实现图像平滑处理

news2025/7/9 7:05:02

1 前言

图像的平滑处理,也叫做模糊处理,是在尽量保留原始图像信息的情况下,抑制或去除图像内的噪声、降低细节层次信息等一系列过程。是一种操作简单但使用频率很高的图像处理方法。由于实际的图像索引方式,与我们常用的x和y轴的定义方式不同,为了确保符号清晰,我们在空间坐标系中表示图像处理滤波器或图像时,一般使用n1和n2来分别表示x和y轴方向的离散坐标。

比如:以一个像素为核心,其周围像素可以组成一个n1行n1列(简称n1 x n2)的矩阵,这样的矩阵结构在滤波操作中被称为“滤波核”。矩阵的行、列数,决定了滤波核的大小。如下图所示的滤波核大小为3x3,包含9个像素。

在OpenCV中,经常用到的二维图像平滑处理有以下4种:均值滤波、中值滤波、高斯滤波和双边滤波。本节我们一起看一下,用C++调用OpenCV接口,如何实现对图像的平滑处理。 

2 均值滤波

2.1 原理

均值滤波器是一种典型的线性滤波算法,可以把图像中的每一个像素当成滤波核的核心,然后计算核内所有像素的平均值,最后将核心像素值改成平均值。其计算过程如下图所示:

 (89 + 134 + 206 + 198 + 24 + 140 + 154 + 199 + 89) / (3 x 3) = 137

滤波核大小是3 x 3,核心像素值是24,与周围像素值相比偏小,所以可以认为核心像素值是噪声。先将滤波核中的所有像素值相加,然后除以像素个数,就得出了平均值137。最后将核心像素值改成137,其颜色与周围像素颜色差别就不大了,图像看起来就变得平滑了。这就是均值滤波器降噪的原理。

2.2 关键接口

C++调用OpenCV实现均值滤波的关键函数原型:

CV_EXPORTS_W void blur( InputArray src, OutputArray dst,
                        Size ksize, Point anchor = Point(-1,-1),
                        int borderType = BORDER_DEFAULT );

参数说明:

参数1:被处理的图像

参数2:均值滤波处理之后的图像

参数3:滤波核大小,其格式为(高度,宽度),建议使用(3,3),(5,5),(7,7)等  宽、高相等的奇数边长。滤波核越大,处理之后的图像越模糊

参数4:滤波核的锚点,建议采用默认值,可以自动计算锚点

参数5:边界样式,建议采用默认值

2.3 代码实现

示例代码采用5 x 5的滤波核,对图像进行均值滤波处理:

#include <opencv2\opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

//均值滤波对图像进行平滑处理
int main()
{
	//定义滤波核大小5x5
	int size = 5;

	//打开原图
	Mat img = imread("flower.jpg");

	//打开失败
	if (img.empty())
	{
		cout << "打开图片失败" << endl;
		return -1;
	}
	Mat blurImg;

	//均值滤波降低图像噪声
	blur(img, blurImg, Size(size, size));
	//显示原图像
	imshow("原图", img);
	//显示去噪后的图像
	imshow("均值滤波", blurImg);
	imwrite("blur.jpg", blurImg);
	waitKey(0);

	//关闭所有窗口
	destroyAllWindows();
	return 0;
}

2.4 效果图

均值滤波器的主要作用是减少图像噪声。当图像中有高斯白噪声时,均值滤波器就可以降低该噪声,因为它可以在像素的相邻像素区域之间取平均值,所以零均值的白噪声将会被抑制。均值滤波器在减少白噪声方面做得比较好。

3 中值滤波

3.1 原理

二维的中指滤波器原理与均值滤波器类似,不同的地方是不计算滤波核内像素的平均值,而是将所有像素值排序,然后把核心像素值,改成最中间的像素值。整个过程会将图像中的每个像素,以其滤波尺寸大小的邻域内像素强度的中值来替代。

其计算过程如下图所示:

 24  89  89  134  140  154  198  199  206

3.2 关键接口

C++调用OpenCV实现中值滤波的关键函数原型:

CV_EXPORTS_W void medianBlur( InputArray src, OutputArray dst, int ksize );

参数说明:

参数1:待处理的图像

参数2:中值滤波处理后的图像

参数3:滤波核大小,其值表示边长,必须是大于1的奇数 3,5,7等

3.3 代码实现

#include <opencv2\opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

//中值滤波对图像进行平滑处理
int main()
{
	//定义滤波核大小5x5
	int size = 5;

	//打开原图
	Mat img = imread("flower.jpg");

	//打开失败
	if (img.empty())
	{
		cout << "打开图片失败" << endl;
		return -1;
	}
	Mat medianblurImg;

	//中值滤波降低图像噪声
	medianBlur(img, medianblurImg, size, size);
	//显示原图像
	imshow("原图", img);
	//显示去噪后的图像
	imshow("中值滤波", medianblurImg);
	imwrite("medianBlur.jpg", medianblurImg);
	waitKey(0);

	//关闭所有窗口
	destroyAllWindows();
	return 0;
}

3.4 效果图

中值滤波器有利于去除椒盐噪声。椒盐噪声通常是在获取图像时,突然出现的扰动造成的,一般在图像中以黑白像素的形式出现。

4 高斯滤波

4.1 原理

高斯滤波器是均值滤波器的修正版本,它将正态分布应用于图像处理中。滤波器中心位置的权重最高,越远离核心的像素权重越低,从中心点向外呈正态分布。像素权重不同不能取平均值,要从权重高的像素中取较多的信息,从权重低的像素中取较少的信息。其权重如下图所示:

高斯滤波的计算过程,涉及到卷积运算,会有一个与滤波核大小相同的卷积核。我们以3 x 3的滤波核为例,来描述一下计算过程。卷积核中保存的值,就是核所覆盖区域的权重值。卷积核中所有权重值相加,结果为1.

如下图所示的3 x 3卷积核。

高斯滤波的计算过程,就是将滤波核中的像素值,与卷积核进行卷积运算,最后将结束结果赋值给滤波核的核心像素。

滤波核中的每个像素值,与卷积核对应位置的权重值相乘,最后计算出9个值:

89 x 0.05    134 x 0.1   206 x 0.05                                      4.45    13.4  10.3

198 x 0.1     24 x 0.4    140 x 0.1                    =                 19.8    9.6    14

154 x 0.05  199 x 0.1   89 x 0.05                                        7.7     19.9  4.45

把这9个值累加,四舍五入取整:

4.45 + 13.4 + 10.3 + 19.8 + 9.6 + 14 + 7.7 + 19.9 + 4.45 = 103.6 ≈ 104

最后得到的这个结果,就是高斯滤波计算结果,滤波核核心像素值,从24改成了104。

4.2关键接口

C++调用OpenCV实现高斯滤波的关键函数原型:

CV_EXPORTS_W void GaussianBlur( InputArray src, OutputArray dst, Size ksize,
                                double sigmaX, double sigmaY = 0,
                                int borderType = BORDER_DEFAULT );

参数说明:

参数1:待处理的图像

参数2:高斯滤波处理之后的图像

参数3:滤波核的大小,宽高必须是奇数,与均值滤波相同

参数4:卷积核水平方向的标准差,建议填0,会根据滤波核的大小自动计算合适的权重比例

参数5:卷积核垂直方向的标准差,建议填0,会根据滤波核的大小自动计算合适的权重比例

参数6:边界样式,建议使用默认值

4.3 代码实现

#include <opencv2\opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

//高斯滤波对图像进行平滑处理
int main()
{
	//定义滤波核大小5x5
	int size = 5;

	//打开原图
	Mat img = imread("flower.jpg");

	//打开失败
	if (img.empty())
	{
		cout << "打开图片失败" << endl;
		return -1;
	}
	Mat gaussImg;

	//高斯滤波5x5降噪
	GaussianBlur(img, gaussImg, Size(size, size), 0, 0);
	//显示原图像
	imshow("原图", img);
	//显示去噪后的图像
	imshow("高斯5x5", gaussImg);
	imwrite("gauss.jpg", gaussImg);
	waitKey(0);

	//关闭所有窗口
	destroyAllWindows();
	return 0;
}

4.4 效果图

高斯滤波也被叫做高斯模糊或高斯平滑,是目前应用最广泛的图像平滑处理算法。高斯滤波可以很好地降低图像噪声,同时将保留更多的细节层次,经过处理的图像,呈现“磨砂玻璃”的滤镜效果。

5 双边滤波

5.1 原理

双边滤波器是一种非线性滤波方法,是结合图像的空间邻近度和像素值相似度的一种折中处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。双边滤波器会自动判断滤波核处于“平坦”区域还是“边缘”区域:如果滤波核处于“平坦”区域,则会使用类似高斯滤波的算法进行滤波;如果滤波核处于“边缘”区域,则加大“边缘”像素的权重,尽可能地让这些像素值保持不变。

5.2 关键接口

C++调用OpenCV实现高斯滤波的关键函数原型:

CV_EXPORTS_W void bilateralFilter( InputArray src, OutputArray dst, int d,
                                   double sigmaColor, double sigmaSpace,
                                   int borderType = BORDER_DEFAULT );

参数说明:

参数1:待处理的图像

参数2:双边滤波处理后的图像

参数3:以当前像素为中心的整个滤波区域的直径。如果d<0,则自动根据sigmaSpace参数  计算得到。该值与保留的边缘信息数量成正比,与方法运行效率成反比

参数4:参与计算的颜色范围,这个值是像素颜色值与周围颜色值的最大差值,只有颜色值  之差小于这个值时,周围的像素才进行滤波计算。值为255时,表示所有颜色都参与计算

参数5:坐标空间的σ(sigma)值,该值越大,参与计算的像素数量就越多

参数6:边界样式,建议默认值

5.3 代码实现

#include <opencv2\opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

//双边滤波对图像进行平滑处理
int main()
{
	//定义滤波区域直径大小
	int d = 5;

	//打开原图
	Mat img = imread("flower.jpg");

	//打开失败
	if (img.empty())
	{
		cout << "打开图片失败" << endl;
		return -1;
	}
	Mat bfImg;

	//双边滤波平滑处理
	bilateralFilter(img, bfImg, d, 2 * d, d / 2);
	//显示原图像
	imshow("原图", img);
	//显示去噪后的图像
	imshow("双边滤波", bfImg);
	imwrite("bilateral.jpg", bfImg);
	waitKey(0);

	//关闭所有窗口
	destroyAllWindows();
	return 0;
}

5.4 效果图

前边介绍的均值滤波、中值滤波和高斯滤波,都会使整幅图像变得平滑,图像中的边界会变得模糊不清。双边滤波与它们不同的地方是,在平滑过程中可以有效保护边界信息。

6 测试项目

6.1 创建项目

创建测试项目、配置开发环境,具体可参考之前文章,这里就不多说了

Win10+OpenCV4.6.0之开发环境(VS2022)配置入门_来灵的博客-CSDN博客

这次测试项目名称image_smoothing,VS2022种创建好的项目截图

 文件目录截图

下边代码是四种滤波器的总代码,您也可以创建每个滤波器单独的代码,这里不再赘述。

#include <opencv2\opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main()
{
	//定义滤波核大小5x5
	int size = 5;

	//定义滤波区域直径大小
	int d = 5;

	//打开原图
	Mat img = imread("flower.jpg");

	//打开失败
	if (img.empty())
	{
		cout << "打开图片失败" << endl;
		return -1;
	}
	Mat blurImg, medianblurImg, gaussImg, bfImg;

	//均值滤波降低图像噪声
	blur(img, blurImg, Size(size, size));

	//中值滤波降低图像噪声
	medianBlur(img, medianblurImg, size);

	//高斯滤波5x5降噪
	GaussianBlur(img, gaussImg, Size(size, size), 0, 0);

	//双边滤波平滑处理
	bilateralFilter(img, bfImg, d, 2 * d, d / 2);

	//显示原图像
	imshow("原图", img);
	//显示处理后的图像
	imshow("均值滤波", blurImg);
	imshow("中值滤波", medianblurImg);
	imshow("高斯滤波", gaussImg);
	imshow("双边滤波", bfImg);

	//保存处理后的图像
	imwrite("blur.jpg", blurImg);
	imwrite("medianBlur.jpg", medianblurImg);
	imwrite("gauss.jpg", gaussImg);
	imwrite("bilateral.jpg", bfImg);

	//按下任何键结束程序
	waitKey(0);

	//关闭所有窗口
	destroyAllWindows();
	return 0;
}

6.2 效果图

7 总结

最后对四种常用的图像滤波器用途做以总结:

滤波器类型

用途

均值滤波

降低高斯白噪声

中值滤波

降低椒盐噪声

高斯滤波

降低图像噪声

双边滤波

降低图像噪声、同时保护图像边界信息

8 参考文献

1 《Python OpenCV从入门到精通》明日科技

2 OpenCV: Image Filtering

3 OpenCV平滑图像_w3cschool

4 OpenCV计算机视觉学习(4)——图像平滑处理(均值滤波,高斯滤波,中值滤波,双边滤波) - 战争热诚 - 博客园

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/36897.html

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

相关文章

2022年 SecXOps 安全智能分析技术白皮书 学习笔记 免费下载地址

核心能力 为了加快安全分析能力更全面、更深入的自动化 &#xff0c;SecXOps 的目标在于创建一个集成的用于 Security 的 XOps 实践&#xff0c;提升安全分析的场景覆盖率和运营效率。SecXOps 技术并不 015 SecXOps 技术体系 是 Ops 技术在安全领域的简单加和&#xff0c;SecXO…

postman拦截浏览器请求

postman可以去浏览器请求进行拦截&#xff0c;并将请求存放至集合。 原理 postman内部有捕获http请求流量的代理&#xff1b; postman app 监听这客户端程序或者设备发出的调用请求&#xff1b;postman 代理端会捕获到请求并把它转发到服务器&#xff1b;服务器将响应返回给p…

双非大学改考408,软件工程专业考研报考人数较少!

南昌航空大学是一所双非大学&#xff0c;位于江西省南昌市。南昌航空大学计算机学科评估没有&#xff0c;软件工程学科评估C&#xff0c;计算机实力在双非大学中也并不算强。南昌航空大学今年计算机考研大变化&#xff0c;软件学院的所有专业&#xff08;包括&#xff1a;软件工…

虚拟化性能优化系列-numatune

numatune是什么 numatune是libvirt的一个参数&#xff0c;可以用在numa架构的host上&#xff0c;以控制子机的内存访问策略。 使用方法如下&#xff0c;参考libvirt文档 <domain> ... <numatune> <memory mode"strict" nodeset"1-4,^3"/&…

多线程(1)

多线程 前言 &#xff1a; 上文主要了解到了进程&#xff0c; 那么为啥需要引入进程呢&#xff1f;   或者说为啥要有进程呢&#xff1f; 其实这里最主要的目的是为了解决 并发编程 这样的问题。 了解 &#xff1a;   这里 cpu 进入了多核心的时代&#xff0c;想要进一步提…

解决:给 VSCode 手动添加(解压压缩包)相关插件的问题

1、一般的添加方式为&#xff1a; 在 VSCode 里面扩展程序里面直接搜索添加即可&#xff1b; 2、如何手动添加一个 VSCode 相关插件&#xff1f; 其一、首先把相关文件解压&#xff0c;解压成一个文件夹&#xff1b; 其二、找到 VSCode 的 extensions 的地址并把 A 所述文件…

【Java 设计模式】创建者模式 之抽象工厂模式

抽象工厂模式1 概念2 角色3 甜品店案例3.1 类图3.2 实现4 优缺点1 概念 产品族&#xff1a;华为既有华为手机&#xff0c;也有华为电脑、华为平板&#xff0c;华为手机、华为电脑和华为平板属于一个产品族&#xff0c;因为他们都是华为品牌。产品等级&#xff1a;有华为手机&am…

骁龙咣咣咣三脚,再次改写格局

鱼羊 萧箫 发自 凹非寺量子位 | 公众号 QbitAI盆友们&#xff0c;骁龙&#xff0c;已经不再是以前那个骁龙了。就在大家吃瓜安卓新旗舰芯片谁家首发之际&#xff0c;骁龙峰会的绝对主角&#xff0c;却只差没把“时代变了”写在脸上&#xff1a;先是第一天直接挤爆AI牙膏管&…

创建Struts2项目并实现一个例子

文章目录一、创建Struts2项目二、struts2的一个例子一、创建Struts2项目 本人所用idea应用程序。以下全部内容&#xff0c;都是以idea为例 创建项目前&#xff0c;你需要下载Struts2所需要的jar包&#xff0c;你可以直接去官网下载&#xff0c;也可以点击https://pan.baidu.c…

LeetCode - 1419 数青蛙

题目来源 1419. 数青蛙 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个字符串 croakOfFrogs&#xff0c;它表示不同青蛙发出的蛙鸣声&#xff08;字符串 "croak" &#xff09;的组合。由于同一时间可以有多只青蛙呱呱作响&#xff0c;所以 croakOfFrog…

基于蜻蜓优化算法的认知无线电网络的服务质量研究附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

葡萄糖-聚乙二醇-牛血清白蛋白,BSA-PEG-Glucose,牛血清白蛋白-PEG-葡萄糖

葡萄糖-聚乙二醇-牛血清白蛋白,BSA-PEG-Glucose,牛血清白蛋白-PEG-葡萄糖 牛血清白蛋白&#xff08;BSA&#xff09;&#xff0c;是牛血清中的一种球蛋白&#xff0c;包含607个氨基酸残基&#xff0c;分子量为66.446KDa&#xff0c;可以提供PEG接枝修饰葡萄糖&#xff0c;葡萄…

独家 | 人工智能的记忆与泛化(附链接)

作者&#xff1a;Manuel Brenner 翻译&#xff1a;陈之炎校对&#xff1a;赵茹萱本文约4500字&#xff0c;建议阅读8分钟本文为你介绍了人工智能 记忆与泛化相关知识。标签&#xff1a;人工智能&#xff0c;记忆&#xff0c;泛化“对不可见数据的泛化能力是机器学习的核心。”当…

测试用例设计方法之场景设计法

基本流&#xff1a;采用直黑线表示&#xff0c;是经过用例的最简单的路径&#xff08;无任何差错&#xff0c;程序从开始直接执行到结束&#xff09; 备选流&#xff1a;采用不同颜色表示&#xff0c;一个备选流可能从基本流开始&#xff0c;在某个特定条件下执行&#xff0c;…

声明变量let和const

1.let的声明 JavaScript中用var关键字来声明变量&#xff0c;而在ES6中&#xff0c;还可以使用新增的let的关键字来声明变量。与var不同的是let声明的变量只能在代码块中有效。 {let a5;var b6;console.log(a);console.log(b);} 执行结果&#xff1a; 能正常输出&#xff0c;…

178:vue+openlayers 加载多种形式Esri地图

第178个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers中绘制自定义图形,利用Geojson的writeFeatures,来生成geojson格式的数据,然后使用file-saver来导出geojson。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果; 注意如果OpenStreetM…

【论文阅读】半监督时序动作检测 Semi-Supervised Action Detection

文章目录1. Learning Temporal Action Proposals With Fewer Labels (ICCV 2019)论文目的——拟解决问题贡献——创新实现流程详细方法2. Self-Supervised Learning for Semi-Supervised Temporal Action Proposal (CVPR 2021)论文目的——拟解决问题贡献——创新实现流程详细方…

微服务之间,最佳的调用方式是什么?

在微服务架构中&#xff0c;需要调用很多服务才能完成一项功能。服务之间如何互相调用就变成微服务架构中的一个关键问题。服务调用有两种方式&#xff0c;一种是RPC方式&#xff0c;另一种是事件驱动&#xff08;Event-driven&#xff09;方式&#xff0c;也就是发消息方式。消…

多模态实战视频生成文本:基于VGG与LSTM实现图像对应的描述文本生成任务

任务描述:本教程将帮助你利用深度学习的方法为照片等图像自动生成文字描述,图像描述是结合计算机视觉与自然语言处理的综合任务,输入一幅图像, 输出一段描述该图像的文字,这一任务要求模型可以识别图片中的物体、理解物体间的关系,并用一句自然语言表达出来。 运行环境:在…

体系结构30_同步性能问题

栅栏&#xff08;barrier&#xff09;同步 栅栏强制所有到达该栅栏的进程进行等待&#xff0c;直到全部的进程到达栅栏&#xff0c;然后释放全部的进程&#xff0c;从而形成同步。 栅栏的典型实现是要用两个旋转锁&#xff1a;一个用来记录到达栅栏的进程数&#xff0c;另一个用…