【图像处理OpenCV(C++版)】——5.4 图像平滑之中值平滑(滤波)

news2024/11/18 9:23:53

前言

😊😊😊欢迎来到本博客😊😊😊

🌟🌟🌟 本专栏主要结合OpenCV和C++来实现一些基本的图像处理算法并详细解释各参数含义,适用于平时学习、工作快速查询等,随时更新。

😊😊😊 具体食用方式:可以点击本专栏【OpenCV快速查找(更新中)】–>搜索你要查询的算子名称或相关知识点,或者通过这篇博客👉通俗易懂OpenCV(C++版)详细教程——OpenCV函数快速查找(不断更新中)]查阅你想知道的知识,即可食用。

🎁🎁🎁支持:如果觉得博主的文章还不错或者您用得到的话,可以悄悄关注一下博主哈,如果三连收藏支持就更好啦!这就是给予我最大的支持!😙😙😙


文章目录

    • 学习目标
    • 一、中值平滑原理
      • 1.1 相关概念
      • 1.2 原理
      • 1.3 作用
    • 二、C++实现
      • 2.1 函数介绍
      • 2.2 具体实现
    • 三、 总结

学习目标

  • 了解中值平滑含义
  • 熟悉中值原理
  • C++实现中值平滑案例

  每一张图像都可能包含某种程度的噪声,噪声可以理解为由一种或者多种原因造成的灰度值的随机变化。
  在大多数情况下,通过平滑技术(也常称为滤波技术)进行抑制或者去除,其中具备保持边缘(Edge Preserving)作用的平滑技术得到了更多的关注。
  常用的平滑处理算法包括基于二维离散卷积高斯平滑、均值平滑,基于统计学方法的中值平滑,具备保持边缘作用的平滑算法的双边滤波、导向滤波等。

  下面将详细介绍中值平滑技术原理、常见应用及实现。


一、中值平滑原理

1.1 相关概念

  中值平滑,类似于卷积,也是一种邻域运算,但计算的不是加权求和,而是对邻域中的像素点按灰度值进行排序,然后选择该组的中值作为输出的灰度值

1.2 原理

  假设输入图像为I,高为R、宽为C,对于图像中的任意位置(r,c),0≤r≤R,0≤c≤C,取以(r,c)为中心、宽为W、高为H的邻域,其中WH均为奇数,对邻域中的像素点灰度值进行排序,然后取中值,作为输出图像O(r,c)位置处的灰度值。

  例如如下图像矩阵:

  取以位置(1,1)为中心的3×3邻域,对邻域中的像素点灰度值按从小到大进行排序:

  可以看出141是该组灰度值的中值,那么输出图像O(1,1)=141,依此类推,会得到输出图像的所有像素点的灰度值。当然,对边缘处的处理和前几章学的卷积运算一样,可采用多种策略,而对边界进行镜像补充是较为理想的一种选择

1.3 作用

  在图像处理中,中值滤波最重要的能力是去除椒盐噪声,常用来保护边缘信息,是经典的平滑噪声的方法,该方法法对消除椒盐噪音非常有效,椒盐噪声是指在图像传输系统中由于解码误差等原因,导致图像中出现孤立的白点或者黑点

二、C++实现

  接下来介绍中值平滑的实现及其效果。

2.1 函数介绍

  OpenCV并没有提供直接计算中数的函数,可以利用另外两个函数sort()reshape()间接计算中数。我们先了解下这两个函数:

  1、sort()

void cv::sort(InputArray src,
			OutputArray dst,
			int flags 
)	
参数解释
src输入单通道矩阵
dst输出矩阵,大小和数据类型与src一致
flags排序规则,CV_SORT_EVERY_ROW:对每行排序;CV_SORT_EVERY_COLUMN :对每列排序;CV_SORT_ASCENDING:升序排序;CV_SORT_DESCENDING :降序排序

  2、reshape()

  reshape()函数比较有意思,它既可以改变矩阵的通道数,又可以对矩阵元素进行序列化,非常有用的一个函数。

reshape	(int cn,
		int rows = 0 
)	

  这个函数参数比较少,但设置的时候却要千万小心。

参数解释
cn表示通道数(channels), 如果设为0,则表示保持通道数不变,否则则变为设置的通道数
rows表示矩阵行数。如果设为0,则表示保持原有的行数不变,否则则变为设置的行数

  
  对于取邻域的中值的方法,需要利用Mat的成员函数reshape()将矩阵变为一行或者一列,然后使用sort()函数进行排序,最后取中间位置的数即为中数,例如:

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include <cmath>
#include <opencv2/imgproc.hpp>
using namespace std;
using namespace cv;
int main(int argc, char** argv){
	Mat ImgMatrix = (Mat_<float>(3, 3) << 1, 2, 3, 4, 5, 6,7,8,9);
	
	//将ImgMatrix转为1行,通道数不变
	Mat ImgMatrix_R = ImgMatrix.reshape(1,1);

	//进行排序
	Mat dst;
	cv::sort(ImgMatrix_R,dst,CV_SORT_EVERY_ROW);

	//获取中值
	float medianvalue=dst.at<float>(0, (dst.cols-1) / 2);

	cout << "median value is:" << medianvalue << endl;

	waitKey(0);

	return 0;
	
}

2.2 具体实现

  对于图像的中值平滑,为了省去判断边界的问题,需要对输入的图像矩阵进行扩充边界的操作。具体代码如下:

Mat medianSmooth(const Mat &Image, Size size, int borderType = BORDER_DEFAULT){

	CV_Assert(Image.type() == CV_8UC1);
	int H = size.height;
	int W= size.width;
	
	//窗口的高、宽均为奇数,一般设置两者是相同的
	CV_Assert(H>0 && W>0);
	CV_Assert(H%2==1 && W%2== 1);

	//对原图像矩阵进行边界扩充
	int h=(H - 1)/2;
	int w=(W-1)/2;
	Mat ImagePadding;
	copyMakeBorder(Image, ImagePadding, h, h, w, w, borderType);
	//输入图像的高、宽
	int rows = Image.rows;
	int cols = Image.cols;
	//中值平滑后的输出图像
	Mat medianI(Image.size(),CV_8UC1);
	int i=0,j=0;
	//中数的位置
	int index=(H*W - 1)/ 2;
	for (int r=h;r< h+rows; r++)
	{
		for (int c=w;c<w+cols; c++)
		{
			//取以当前位置为中心、大小为 size 的邻域
			Mat region = ImagePadding(Rect(c-w,r-h, W,H)).clone();
	
			//将该邻域转换成行矩阵
			region = region.reshape(1,1);
	
			//排序
			cv::sort(region,region,CV_SORT_EVERY_ROW);
	
			//取中数
			uchar mValue = region.at<uchar>(0,index);
			medianI.at<uchar>(i,j) = mValue;
			j++;
		}
		i++;
		j=0;
	}
	return medianI;
}

  上述函数只能处理8位图,其他数据类型与之类似。利用该函数对图像进行中值平滑的主函数代码如下:

int main(int argc, char** argv) {
	cv::Mat src = cv::imread("D:/VSCodeFile/OpenCV_CSDN/image/logo_gray.jpeg");
	CV_Assert(!src.empty());
	src.convertTo(src, CV_8UC1);

	//中值滤波
	Mat medianImage=medianSmooth(src,Size(5,5));

	imshow("src", src);
	imshow("medianImage", medianImage);

	waitKey(0);

	return 0;
}

  一般来说,如果图像中出现较亮或者较暗的物体,若该物体大小小于中值平滑的窗口半径,那么它们基本上会被滤掉,而较大的目标则几乎会原封不动地保存下来。因此,中值平滑的窗口尺寸需要根据所遇到的不同问题而进行相应的调整

  中值平滑需要对邻域中的所有像素点按灰度值排序,一般比卷积运算要慢,有一些算法能够加速中值平滑。在OpenCV中提供了这样的函数:

void cv::medianBlur(InputArray src,
		OutputArray dst,
		int ksize 
)	
参数解释
src输入矩阵
dst输出矩阵,其大小与数据类型和src一致
ksize大于1且为奇数的核大小

  对于上述代码,这里仅需几行即可解决:

```cpp
int main(int argc, char** argv) {
	cv::Mat src = cv::imread("D:/VSCodeFile/OpenCV_CSDN/image/logo_gray.jpeg");
	CV_Assert(!src.empty());
	src.convertTo(src, CV_8UC1);

	//中值滤波
	Mat dst;
	cv::medianBlur(src, dst, 5);
	

	imshow("src", src);
	imshow("dst", dst);

	waitKey(0);

	return 0;
}

  中值平滑只是排序统计平滑中的一种,如果将取邻域的中值变为取邻域中的最小值或者最大值 ,显然会使图像变暗或者变亮。这类方法就是后面要介绍的形态学处理的基础。

  高斯平滑、均值平滑在去除图像噪声时,会使图像的边缘信息变得模糊,后面将介绍在图像平滑处理过程中可以保持边缘的平滑算法:双边滤波和导向滤波。


三、 总结

  最后,长话短说,大家看完就好好动手实践一下,切记不能三分钟热度、三天打鱼,两天晒网。OpenCV是学习图像处理理论知识比较好的一个途径,大家也可以自己尝试写写博客,来记录大家平时学习的进度,可以和网上众多学者一起交流、探讨,有什么问题希望大家可以积极评论交流,我也会及时更新,来督促自己学习进度。希望大家觉得不错的可以点赞、关注、收藏。


🚶🚶🚶 今天的文章就到这里啦~
喜欢的话,点赞👍、收藏⭐️、关注💟哦 ~

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

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

相关文章

IntelliJ IDEA - 一篇解决如何多模块项目提交到同一个 Git 仓库

问题描述 事情是这样的&#xff0c;最近新建了一个项目&#xff08;多模块&#xff09;&#xff0c;这个不必多说大家就知道长什么样子&#xff08;文件结构&#xff09;&#xff0c;问题是在我写完后想提交项目到 Git 仓库时&#xff0c;发现每个模块都要设置 Remote Git 地址…

Get “https://xx.xx.x.xx/v2/“: x509: certificate signed by unknown authority

问题描述 使用Windows docker客户端login docker私库&#xff0c;无法登录提示&#xff1a; Get "https://xx.xx.x.xx/v2/": x509: certificate signed by unknown authority原因分析&#xff1a; 由于harbor做了ssl&#xff0c;通常客户端连接需要配置证书 解决方…

Hbuilder打包android安装包流程

Hbuilder打包android安装包流程 第一步打开项目文件的manifest.json,在右侧填写具体项目应用信息&#xff0c;每次打包升级前版本号一定要设置的比上版本的高。 点击App图标配置&#xff0c;选择图标资源进行全量生成。 点击菜单”发行”&#xff0c;选择云打包&#xff0c…

十分钟实现 Android Camera2 相机预览

1. 前言 因为工作中要使用Android Camera2 API&#xff0c;但因为Camera2比较复杂&#xff0c;网上资料也比较乱&#xff0c;有一定入门门槛&#xff0c;所以花了几天时间系统研究了下&#xff0c;并在CSDN上记录了下&#xff0c;希望能帮助到更多的小伙伴。 2. Camera2 API …

Lenovo联想Yoga 14s 2021AMD平台ARH版(82LB)原装Win10系统镜像 恢复出厂OEM预装系统

lenovo联想笔记本电脑&#xff0c;Yoga 14s 2021AMD平台ARH版(82LB)原装出厂Windows10系统&#xff0c;原厂OEM预装自带系统镜像 系统自带所有驱动、出厂主题壁纸LOGO、Office办公软件、联想电脑管家等预装程序 所需要工具&#xff1a;16G或以上的U盘 文件格式&#xff1a;I…

轻松掌握财务报表的二十二个知识点

财务报表&#xff0c;一是会看资产负债表。知道所在企业的家底有多厚&#xff0c;都分布在什么地方;二是会看利润表。知道企业赚了多少钱&#xff0c;是盈利还是亏损了&#xff0c;赚钱赚在哪里&#xff0c;亏钱亏到了何地;知道企业总共赚了多少钱。三是会看现金流量表。知道企…

软件测试技能,JMeter压力测试教程,Plugins Manager插件管理器(十三)

前言 前面讲了JDBC连接数据库的时候&#xff0c;需下载mysql对应的jar包&#xff0c;放到lib\ext目录下就可以使用了 jmeter 有个插件管理器Plugins Manager&#xff0c;可以方便的管理其他插件的下载和更新 一、插件管理器Plugins Manager 下载地址&#xff1a;Install ::…

6.28黄金能否守住关键支撑,今日多空如何布局

近期有哪些消息面影响黄金走势&#xff1f;今日黄金多空该如何研判&#xff1f; ​黄金消息面解析&#xff1a;周三&#xff08;6月28日&#xff09;亚市盘中&#xff0c;现货黄金窄幅震荡&#xff0c;现交投于1916美元/盎司附近&#xff0c;隔夜公布的美国经济数据强劲&#…

CSS中常用的颜色格式

本文翻译自 Color Formats in CSS&#xff0c;作者&#xff1a;Joshwcomeau。 略有删改 CSS 中的颜色格式可以采用不同的表示方式&#xff0c;包括常用的十六进制、RGB、RGBA、HSL 和 HSLA 等格式。十六进制是最常用的格式&#xff0c;使用 6 个十六进制数字来表示颜色&#xf…

netwox网络工具的使用【网络工程】(保姆级图文)

目录 1. 打开工具功能菜单查看某方面的模块使用搜索功能得到要使用的模块功能编号 查询模块的帮助信息总结 欢迎关注 『网络工程专业』 系列&#xff0c;持续更新中 欢迎关注 『网络工程专业』 系列&#xff0c;持续更新中 温馨提示&#xff1a;对虚拟机做任何设置&#xff0c;…

世界人工智能大会与ICDAR有何不同?

从事人工智能领域的小伙伴对世界人工智能大会和ICDAR应该都不会陌生&#xff0c;它们似乎都是属于研究、讨论人工智能的一种会议&#xff0c;但其实它们的区别还是挺大的&#xff0c;具体来说&#xff0c;它们主要有以下的区别&#xff1a; 一、组织性质不同 ICDAR是Internati…

《计算机系统与网络安全》 第六章 密钥管理

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

viper读取etcd热更新

概述 项目启动肯定少不了配置文件&#xff0c;一般我们会放在单独的目录&#xff0c;例如config中&#xff0c;有yaml、ini、json等等格式&#xff0c;一般用开源的读取相应问的文件映射到结构体中。 但是当一个项目秒杀频繁控制库存和限流策略等、或者其他需要频繁的变更配置…

uniapp app端常见坑

文章目录 uniapp app端常见坑页面内容出现在状态栏数据持久化问题项目初始化跳转登录页闪屏的问题 总结 uniapp app端常见坑 本文主要记录在uniapp-vite-vue3项目app端出现的常见问题 页面内容出现在状态栏 当在page.json设置 “navigationStyle”:“custom” 取消原生导航栏…

Spring进阶学习(附面试快速答法)

文章目录 1、Bean线程安全问题小总结面试快速答法 2、AOP小总结面试快速答法 3、bean的生命周期小总结面试快速答法 4、循环引用小总结面试快速答法 &#xff15;、SpringMVC的执行流程小总结面试快速答法 6、Springboot自动配置原理小总结面试快速答法 7、Spring框架常见注解面…

初步学习使用Mybatis框架

mybatis框架是一款半自动的ORM持久层框架&#xff0c;具有较高的SQL灵活性 所谓半自动的ORM持久层框架&#xff0c;是因为用mybatis进行开发&#xff0c;需要手动编写。而全自动的ORM框架&#xff0c;如hibernate&#xff0c;则不需要编写SQL语句。 对于mybatis&#xff0c;就…

五、云尚办公-菜单管理

云尚办公系统&#xff1a;菜单管理 B站直达【为尚硅谷点赞】: https://www.bilibili.com/video/BV1Ya411S7aT 本博文以课程相关为主发布&#xff0c;并且融入了自己的一些看法以及对学习过程中遇见的问题给出相关的解决方法。一起学习一起进步&#xff01;&#xff01;&#x…

PLC选择指南:西门子还是三菱?

选择适合自己的PLC涉及多个因素&#xff0c;包括项目要求、技术要求、可用性、支持和个人偏好。西门子和三菱是两个知名的PLC制造商&#xff0c;它们都有自己的优势和特点。以下是一些考虑因素&#xff1a; 我这里刚好有plc、嵌入式、单片机的资料需要的可以私我或在评论区扣6…

tp使用layui友好显示修改状态功能

之前找了很多次,然后经过自己的总结,这里记录一下 html部分 <a href"{:url(admin/merchant/make_merchant_erweima,[id>$vo[id]])}" class"layui-btn layui-btn-normal layui-btn-sm ajax-change">二维码</a> 重点是添加上ajax-change的…

别再用查询count,判断数据是否存在了

目录 一、目前多数人的写法 二、优化方案 三、总结 大家在实际的开发过程中&#xff0c;会根据某些条件&#xff0c;从数据库表中查询出是否存在符合该条件的数据。无论是刚入行的程序员小白&#xff0c;还是久经沙场多年的程序员老白&#xff0c;都是一如既往的SELECT count(*…