10篇--图像噪点消除

概念

何为噪点?

噪点:指图像收到的一些干扰因素,通常是由图像采集设备、传输信道等因素造成的,表现为图像中随机的亮度,也可以理解为有那么一些点的像素值与周围的像素值格格不入。

常见的噪声类型

  • 高斯噪声:一种分布符合正态分布的噪声,会使图像变得模糊或有噪点。
  • 椒盐噪声:一些黑白色的像素值分布在原图像中

左侧为高斯噪声                    上面为原图                       右侧为椒盐噪声

如何消除噪点

滤波器

使用滤波器,其主要功能是去除信号中的噪声或干扰,从而提高信号的信噪比。根据同频率区域中噪声信号和真实信号所在频率段的不同,将噪音所在的频率段进行屏蔽或改变其幅值。

下面我们来了解一下滤波器是如何工作的

滤波器:也可以叫做卷积核,与自适应二值化中的核一样,本身是一个小的区域,有着特定的核值,并且工作原理也是在原图上进行滑动并计算中心像素点的像素值。

  • 滤波器可分为线性滤波和非线性滤波
  • 线性滤波对邻域中的像素进行线性运算,如在核的范围内进行加权求和。
    • 常见的线性滤波器有均值滤波方框滤波高斯滤波等。
  • 非线性滤波则是利用原始图像与模板之间的一种逻辑关系得到结果。
    • 常见的非线性滤波器有中值滤波器双边滤波器等。

滤波与模糊在图像处理上有一定的联系与区别:

  • 它们都属于卷积,不同滤波方法之间只是卷积核不同(对线性滤波而言
  • 低通滤波器是模糊,高通滤波器是锐化
    • 低通滤波器就是允许低频信号通过,在图像中边缘和噪点都相当于高频部分,所以低通滤波器用于去除噪点、平滑和模糊图像。
    • 高通滤波器则反之,用来增强图像边缘,进行锐化处理。

注意:椒盐噪声可以理解为斑点,随机出现在图像中的黑点或白点;高斯噪声可以理解为拍摄图片时由于光照等原因造成的噪声。

上面介绍了5种常见的滤波方式,现在我们来学习一下

线性滤波(模糊)方式

1. 均值滤波

均值滤波是一种最简单的滤波处理,它取的是卷积核区域内元素的均值,如3×3的卷积核:

 比如有一张4*4的图片,现在使用一个3*3的卷积核进行均值滤波时,其过程如下所示:

对于边界的像素点,则会进行边界填充,以确保卷积核的中心能够对准边界的像素点进行滤波操作。默认使用BORDER_REFLECT_101的方式进行填充。

通过卷积核在原图上从左上角滑动计算到右下角,从而得到新的4*4的图像的像素值。

卷积核的中心点(3*3的中间像素点)会依次滑过1,2,3......,并计算出对应值

cv2.blur()函数

功能:用于对图像进行均值滤波(也称为平滑或模糊处理)的函数。均值滤波是一种简单的图像平滑技术,它通过替换图像中每个像素的值为其邻域像素值的平均值来减少图像噪声和细节。

参数:

  • src: 输入图像,即你想要进行模糊处理的源图像。
  • ksize: 核大小,用于指定均值滤波器的尺寸。它是一个元组 (width, height),表示滤波器在水平和垂直方向上的大小。通常,width 和 height 应该是奇数,以确保滤波器有一个中心像素。
  • dst: 输出图像,这是一个可选参数。
  • anchor: 锚点,这是一个可选参数,表示滤波器在源图像中应用的起始位置。默认值是 (-1, -1),这意味着锚点位于滤波器的中心。在大多数情况下,你不需要改变这个参数。
  • borderType: 边界类型,这是一个可选参数,用于指定边界像素的外推方法。当滤波器应用到图像边缘时,需要一些额外的像素来计算边界像素的邻域平均值。OpenCV 提供了多种边界类型,如 cv2.BORDER_DEFAULT(默认)、cv2.BORDER_CONSTANT(用常数填充)、cv2.BORDER_REFLECT(反射边界)等。在大多数情况下,默认边界类型就足够了。

 2. 方框滤波

方框滤波跟均值滤波很像,如3×3的滤波核如下:

比如有一张4*4的图片,现在使用一个3*3的卷积核进行均值滤波时,其过程如下所示:

对于边界的像素点,默认使用BORDER_REFLECT_101的方式进行填充。

其滤波的过程与均值滤波一模一样,都采用卷积核从图像左上角开始,逐个计算对应位置的像素值,并从左至右、从上至下滑动卷积核,并计算出对应值,直至到达图像右下角,唯一的区别就是核值可能会不同。

cv2.boxFilter()函数

功能:用于对图像进行盒式滤波(也称为均值滤波或平均滤波)的函数。这个函数使用一个矩形窗口对图像进行卷积,窗口内所有像素值的平均值将替代锚点位置的像素值。

参数:

  • src: 输入图像,它可以是多通道的。
  • ddepth: 输出图像的所需深度。当参数值为 -1 时,表示输出图像与输入图像有相同的深度。
  • ksize: 核的大小。它是一个元组,表示滤波窗口的宽度和高度(如 (3, 3) 表示一个 3x3 的窗口)。核的大小必须是正奇数。
  • dst: 输出图像,它应该与输入图像有相同的大小和类型。这是一个可选参数。
  • anchor: 表示核的锚点(即核的中心点)在窗口中的位置。默认值是 (-1, -1),这意味着锚点位于窗口的中心。
  • normalize: 一个标志,指示在滤波时是否对窗口内的像素值进行归一化。如果设置为 True(默认值),则会对窗口内的像素值求和并除以窗口的面积,从而得到平均值。如果设置为 False,则直接对窗口内的像素值求和,不进行除法运算。
  • borderType: 边界类型,用于指定图像边界外像素的外推方法。这个参数在需要处理图像边界时很有用。它可以是诸如 cv2.BORDER_CONSTANT、cv2.BORDER_REFLECT 等的边界类型之一。当不指定时,默认使用 cv2.BORDER_DEFAULT。 

注意:当normalize设置为Ture时,那么均值滤波与方框滤波就毫无差别

3. 高斯滤波

前面两种滤波方式,卷积核内的每个值都一样,也就是说图像区域中每个像素的权重也就一样。高斯滤波的卷积核权重并不相同:中间像素点权重最高,越远离中心的像素权重越小。

还记得我们在自适应二值化里是怎么生成高斯核的吗?这里跟自适应二值化里生成高斯核的步骤是一样的,都是以核的中心位置为坐标原点,然后计算周围点的坐标,然后带入下面的高斯公式中。

下面公式看看就行,只需关注最后的卷积核:

比如有一张4*4的图片,现在使用一个3*3的卷积核进行均值滤波时,其过程如下所示:

对于边界的像素点,则会进行边界填充,以确保卷积核的中心能够对准边界的像素点进行滤波操作。默认使用BORDER_REFLECT_101的方式进行填充。

其滤波过程与上面两种滤波方式的滤波过程一样,都是用卷积核从图像左上角开始,逐个计算对应位置的像素值,并从左至右、从上至下滑动卷积核,直至到达图像右下角,唯一的区别就是核值不同。

cv2.GaussianBlur() 函数

功能:用于对图像进行高斯模糊处理的函数。该函数通过高斯核对图像进行卷积操作,从而达到模糊图像的效果。

参数:

  • src:输入图像,可以是灰度图像或彩色图像。它应该是一个 NumPy 数组,通常是通过 OpenCV 读取图像函数(如 cv2.imread())获得的。
  • ksize:高斯核的大小。它应该是一个正奇数,表示高斯核的宽和高。例如,(3, 3) 或 (5, 5)。通常,核大小越大,模糊效果越明显。
  • sigmaX:高斯核函数在 X 方向的标准偏差。这个参数控制着模糊的程度。标准偏差越大,模糊效果越强。通常,sigmaX 的值会设置为一个正数。
  • sigmaY:(可选)高斯核函数在 Y 方向的标准偏差。如果 sigmaY 为 0,则函数会根据 sigmaX 的值来计算 Y 方向的标准偏差,即 sigmaY = sigmaX。如果提供了 sigmaY,则它会独立地控制 Y 方向的模糊程度。
  • dst:(可选)输出图像。
  • borderType:(可选)边界类型。

效果对比

 非线性滤波方式

1. 中值滤波

中值又叫中位数,是所有数排序后取中间的值。中值滤波没有核值,而是在原图中从左上角开始,将卷积核区域内的像素值进行排序,并选取中值作为卷积核的中点的像素值。

 比如有一张4*4的图片,现在使用一个3*3的卷积核进行均值滤波时,其过程如下所示:

对于边界的像素点,则会进行边界填充,以确保卷积核的中心能够对准边界的像素点进行滤波操作。中值滤波使用的是BORDER_REPLICATE进行填充

通过卷积核在原图上从左上角滑动计算到右下角,从而得到新的4*4的图像的像素值。

cv2.medianBlur()函数

功能:用于对图像进行中值滤波的函数。中值滤波是一种非线性的滤波方法,它用像素点邻域内的中值替代该像素点的值,从而起到平滑图像、去除噪声的作用,特别是对于去除椒盐噪声(即图像中随机出现的黑色或白色像素点)非常有效。

参数:

  • src: 输入图像,可以是单通道、三通道等任意通道数的图像。图像的数据类型应该是 uint8、uint16 或 float32 之一。
  • ksize: 滤波器的大小(即邻域的大小),必须是一个大于 1 的奇数。例如,3、5、7 等。这个参数决定了在进行中值计算时考虑的像素范围。
  • dst:(可选)输出图像。

2. 双边滤波

模糊操作(一般为低通滤波器)基本都会损失掉图像细节信息。

锐化操作(一般为高通滤波器),如果处理不当或过度锐化,也容易损坏边缘信息。

尤其前面介绍的线性滤波器,图像的边缘信息很难保留下来。然而,边缘(edge)信息是图像中很重要的一个特征,所以这才有了双边滤波。

换而言之,双边滤波器可以保留更多 线性滤波器 无法保留的 边缘信息

双边滤波的基本思路是同时考虑将要被滤波的像素点的空域信息(周围像素点的位置的权重)和值域信息(周围像素点的像素值的权重)。为什么要添加值域信息呢?是因为假设图像在空间中是缓慢变化的话,那么临近的像素点会更相近,但是这个假设在图像的边缘处会不成立,因为图像的边缘处的像素点必不会相近。因此在边缘处如果只是使用空域信息来进行滤波的话,得到的结果必然是边缘被模糊了,这样我们就丢掉了边缘信息,因此添加了值域信息。

双边滤波采用了两个高斯滤波的结合,一个负责计算空间邻近度的权值(也就是空域信息),也就是上面的高斯滤波器,另一个负责计算像素值相似度的权值(也就是值域信息),也是一个高斯滤波器。其公式如下所示:

看不懂没关系,这些公式我们不需要关心,我贴着玩的,能看就看,看不了拉倒,嘿嘿~。

采用两个高斯滤波器,边缘像素填充时自然使用的是BORDER_REFLECT_101进行填充

cv2.bilateralFilter()函数

功能:用于图像去噪的一个函数,它能够在保留边缘特征的同时去除噪声。这个函数实现了双边滤波,这是一种非线性的、边缘保留的、降噪的滤波器。双边滤波器的关键思想是在空域上进行邻域加权平均,同时考虑像素之间的空间邻近关系和颜色(或强度)相似性,从而避免模糊边缘。

参数:

  • src‌ (InputArray): 输入图像,可以是灰度图像或彩色图像。
  • ‌d‌ (int): 邻域直径。如果它是非正数,则会被计算为 (sigmaSpace*2)。这个参数决定了滤波过程中每个像素的邻域大小。邻域是一个圆形区域,其半径等于 d/2(当 d 为奇数时)或 (d-1)/2(当 d 为偶数时,向下取整)。
  • ‌sigmaColor‌ (double): 颜色空间滤波器的 sigma 值。这个参数决定了滤波函数在颜色(或强度)空间上的标准差。较大的 sigmaColor 值意味着更宽的颜色范围将被视为相似,从而增强去噪效果,但也可能导致边缘模糊。参数越大,临近像素将会在越远的地方mix。
  • ‌sigmaSpace‌ (double): 坐标空间滤波器的 sigma 值。这个参数决定了滤波函数在空间(或位置)上的标准差。较大的 sigmaSpace 值意味着更远的像素将被纳入加权平均,从而增强平滑效果,但也可能导致边缘模糊。如果 d > 0,则 sigmaSpace 会根据 d 的值自动计算(尽管用户可以覆盖这个默认值)。参数越大,那些颜色足够相近的的颜色的影响越大。
  • ‌dst‌ (OutputArray): 输出图像,与输入图像具有相同的尺寸和类型。
  • ‌borderType‌ (int, optional): 边界像素的插值方法。

关于参数的选取:

  • 关于2个sigma参数:
    • 简单起见,可以令2个sigma的值相等;
      • 如果他们很小(小于10),那么滤波器几乎没有什么效果;
      • 如果他们很大(大于150),那么滤波器的效果会很强,使图像显得非常卡通化。
  • 关于参数d:
    • 过大的滤波器(d>5)执行效率低。
    • 对于实时应用,建议取d=5;
    • 对于需要过滤严重噪声的离线应用,可取d=9;

对比总结

  1. 在不知道用什么滤波器好的时候,优先高斯滤波,然后均值滤波
  2. 斑点和椒盐噪声优先使用中值滤波
    • 比如下面这张斑点噪声图,用中值滤波显然更好:

  3. 要去除噪点的同时尽可能保留更多的边缘信息,使用双边滤波
  4. 线性滤波方式(速度相对快):均值滤波、方框滤波、高斯滤波。
  5. 非线性滤波方式(速度相对慢):中值滤波、双边滤波。
  6. 在OpenCV中,除了中值滤波使用的是BORDER_REPLICATE进行填充之外,其他的滤波方法默认的是使用BORDER_REFLECT_101的方式进行填充。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【开源免费】基于Vue和SpringBoot的渔具租赁系统(附论文)

本文项目编号 T 005 ,文末自助获取源码 \color{red}{T005,文末自助获取源码} T005,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 渔…

Linux网络基础-----传输层UDP协议

目录 端口号: 查询各类服务的端口号 加深理解端口号: UDP协议 UDP协议特点: 关于缓冲区: 内核层面理解UDP报文 端口号: 知名端口号:0 ~ 1023:被HTTP、SSH等应用层协议广泛使用的端口号&…

XXE靶场

XXE-lab 靶场 靶场网址&#xff1a;http://172.16.0.87/ 第一步我们看到网站有登录框我们试着用 bp 去抓一下包 将抓到的包发到重放器中 然后我们构建palody <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "php://filter/readconvert.base64-encode/resourceC:/flag/fla…

ubuntu+ros新手笔记(三):21讲没讲到的MoveIt2

1 安装MoveIt2 安装参照在ROS2中&#xff0c;通过MoveIt2控制Gazebo中的自定义机械手 安装 MoveIt2可以选择自己编译源码安装&#xff0c;或者直接从二进制安装。 个人建议直接二进制安装&#xff0c;可以省很多事。 sudo apt install ros-humble-moveitmoveit-setup-assistan…

运维 mysql、redis 、RocketMQ性能排查

MySQL查看数据库连接数 1. SHOW STATUS命令-查询当前的连接数 MySQL 提供了一个 SHOW STATUS 命令&#xff0c;可以用来查看服务器的状态信息&#xff0c;包括当前的连接数。 SHOW STATUS LIKE Threads_connected;这个命令会返回当前连接到服务器的线程数&#xff0c;即当前…

jmeter连接mysql

查询mysql数据库版本 SELECT VERSION(); 下载jmeter mysql 驱动jar包&#xff0c;版本低于mysql版本&#xff0c;放在jmeter的lib 路径下 MySQL :: Download MySQL Connector/J (Archived Versions) 添加JDBC Connection Configuration 填写 variable name 及数据库信息 注意…

Docker的容器

目录 1. 什么是容器&#xff1f;2. 容器的生命周期2.1 容器处理OOM事件2.2 容器异常退出2.3 容器暂停 3. 容器命令详解3.1 容器命令清单3.2 docker create命令3.3 docker run命令3.4 docker ps命令3.5 docker logs命令3.6 docker attach命令3.7 docker exec命令3.8 docker stat…

JAVA题目笔记(二十六)反射

一、保存信息 Student类&#xff1a; package testpackage;import java.io.IOException;public class Student {private String name;private String area;public String testfield;private int age;public Student() {}public Student(String name, String area, int age) {t…

python 配置 oracle instant client

1.问题描述 想用python连接oracle数据库&#xff0c;百度得知需要cx_Oracle这个第三方库 import cx_Oracle# 设置Oracle数据源名称 dsn cx_Oracle.makedsn(host, port, service_nameservice_name)# 创建数据库连接 connection cx_Oracle.connect(userusername, passwordpas…

皮肤伤口分割数据集labelme格式248张5类别

数据集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数)&#xff1a;284 标注数量(json文件个数)&#xff1a;284 标注类别数&#xff1a;5 标注类别名称:["bruises","burns","cu…

Ollama配置与webUI本地部署-学习记录

Ollama 前言一、Ollama的下载与安装设置(windows)1.下载2.安装与配置1.查看环境变量&#xff1a;2.设置环境变量&#xff1a;3.设置变量 二、使用步骤1.查找模型2.使用Ollama1.下载模型2.使用 三、WebUI部署WebUI 总结 前言 Ollama是一款可以开始使用本地的大型语言模型。启动…

vscode不同项目使用不同插件

转载请注明出处&#xff1a;小帆的帆的博客 在使用vscode开发不同项目时可能会用到不同的插件。手动管理不够优雅&#xff0c;本文介绍使用Profiles的方式的来管理不同项目的插件。 手动管理不同项目的插件 本来vscode安装了有三个插件 这时需要新建一个项目&#xff0c;新…

数据结构 ——前缀树查词典的实现

数据结构 ——前缀树查词典的实现 一、前缀树的概念 前缀树是一种多叉树结构&#xff0c;主要用于存储字符串。每个节点代表一个字符&#xff0c;路径从根节点到叶节点表示一个完整的字符串。前缀树的关键特征是 共享前缀&#xff0c;也就是说&#xff0c;如果两个字符串有相…

H5 中 van-popup 的使用以及题目的切换

H5 中 van-popup 的使用以及题目的切换 在移动端开发中&#xff0c;弹窗组件是一个常见的需求。vant 是一个轻量、可靠的移动端 Vue 组件库&#xff0c;其中的 van-popup 组件可以方便地实现弹窗效果。本文将介绍如何使用 van-popup 实现题目详情的弹窗展示&#xff0c;并实现…

leetcode 36.有效的数独

1.题目要求: 2.题目步骤: 写好判断函数 3.题目代码: class Solution { public:bool isvalid(vector<vector<char>>& board,char num,int row,int col){//先找左下标int leftrow row - 1;while(leftrow > 0){if(board[leftrow][col] num){return fals…

ElasticSearch中的深度分页问题

在使用 ElasticSearch 进行搜索时&#xff0c;很多小伙伴会遇到“深度分页”问题。当需要获取大量的分页数据时&#xff0c;查询性能会急剧下降&#xff0c;甚至导致集群负载过高。这篇文章将深入剖析 ElasticSearch 深度分页的成因、危害&#xff0c;并提供一些常用的优化方案…

Eureka学习笔记-服务端

Eureka学习笔记 服务端 模块设计 Resources &#xff1a;这部分对外暴露了一系列的 Restful 接口。Eureka Client 的注册、心跳、获取服务列表等操作都需要调用这些接口。另外&#xff0c;其他的 Server 在同步 Registry 时也需要调用这些接口。Controller &#xff1a;这里提…

快速上手:利用 FFmpeg 合并音频文件的实用教程

FFmpeg 是一个强大的多媒体处理工具&#xff0c;能够轻松地对音频、视频进行编辑和转换。本文将介绍如何使用 FFmpeg 来合并&#xff08;拼接&#xff09;多个音频文件为一个单一文件。无论您是想要创建播客、音乐混音还是其他任何形式的音频项目&#xff0c;这都是一个非常实用…

在 CUDA C/C++ 中使用共享內存

文章结尾有最新热度的文章,感兴趣的可以去看看。 本文是经过严格查阅相关权威文献和资料,形成的专业的可靠的内容。全文数据都有据可依,可回溯。特别申明:数据和资料已获得授权。本文内容,不涉及任何偏颇观点,用中立态度客观事实描述事情本身 文章有点长(4700字),期望您…

Linux文件属性 --- 硬链接、所有者、所属组

三、硬链接数 1.目录 使用“ll”命令查看&#xff0c;在文件权限的后面有一列数字&#xff0c;这是文件的硬链接数。 对于目录&#xff0c;硬链接的数量是它具有的直接子目录的数量加上其父目录和自身。 下图的“qwe”目录就是“abc”目录的直接子目录。 2.文件 对于文件可…