双边滤波

双边滤波

   高斯滤波是最常用的图像去噪方法之一,它能很好地滤除掉图像中随机出现的高斯噪声,但是在之前的博客中提到过,高斯滤波是一种低通滤波(有兴趣的点击这里,查看之前的博客),它在滤除图像中噪声信号的同时,也会对图像中的边缘信息进行平滑,表现出来的结果就是图像变得模糊,如下图所示;
在这里插入图片描述
   高斯滤波之所以会导致图像变得模糊,是因为它在滤波过程中只关注了位置信息;例如,以 qq q q 为中心的窗口中,某一点 pp p p 在高斯滤波过程中的权重的计算方法如下式;
G(p)=12πσ2e−∥p−q∥22σ2G(p)=12πσ2e−∥p−q∥22σ2 G(p)=\frac{1}{2\pi \sigma ^{2}} e^{-\frac{\left \| p-q \right \|^{2}}{2\sigma ^{2}}} G(p)=2πσ21​e−2σ2∥p−q∥2​
  即在滤波窗口内,距离中心点越近的点的权重越大;这种只关注距离的思想在某些情况下是可行的,例如在平坦的区域,距离越近的区域其像素分布也越相近,自然地,这些点的像素值对滤波中心点的像素值更有参考价值。但是在像素值出现跃变的边缘区域,这种方法会适得其反,损失掉有用的边缘信息。此时就出现了一类算法——边缘保护滤波方法双边滤波就是最常用的边缘保护滤波方法(另一种常用来与双边滤波对比的边缘保护滤波方法——引导滤波)。

  双边滤波的思想很简单,在高斯滤波的基础上加入了像素值权重项,也就是说既要考虑距离因素,也要考虑像素值差异的影响,像素值越相近,权重越大。将像素值权重表示为 GrGr G_{r} Gr​ ,空间距离权重表示为 GsGs G_{s} Gs​。

Gs=exp(−∥p−q∥22σ2s)Gs=exp(−∥p−q∥22σs2) G_{s}=exp(-\frac{\left \| p-q \right \|^{2}}{2\sigma _{s}^{2}}) Gs​=exp(−2σs2​∥p−q∥2​)
Gr=exp(−∥Ip−Iq∥22σ2r)Gr=exp(−∥Ip−Iq∥22σr2) G_{r}=exp(-\frac{\left \| I_{p}-I_{q} \right \|^{2}}{2\sigma _{r}^{2}}) Gr​=exp(−2σr2​∥Ip​−Iq​∥2​)

  那么整个滤波器可以表示为BFBF BF BF,那么滤波结果为;
BF=1Wq∑p∈SGs(p)Gr(p)∗Ip=1Wq∑p∈Sexp(−∥p−q∥22σ2s)exp(−∥Ip−Iq∥22σ2r)∗IpBF=1Wq∑p∈SGs(p)Gr(p)∗Ip=1Wq∑p∈Sexp(−∥p−q∥22σs2)exp(−∥Ip−Iq∥22σr2)∗Ip \begin{aligned} BF&=\frac{1}{W_{q}}\sum_{p\in S}G_{s}(p)G_{r}(p)*I_{p}\\&=\frac{1}{W_{q}}\sum_{p\in S}exp(-\frac{\left \| p-q \right \|^{2}}{2\sigma _{s}^{2}})exp(-\frac{\left \| I_{p}-I_{q} \right \|^{2}}{2\sigma _{r}^{2}})*I_{p}\end{aligned} BF​=Wq​1​p∈S∑​Gs​(p)Gr​(p)∗Ip​=Wq​1​p∈S∑​exp(−2σs2​∥p−q∥2​)exp(−2σr2​∥Ip​−Iq​∥2​)∗Ip​​
  其中WqWq {W_{q}} Wq​ 为滤波窗口内每个像素值的权重和,用于权重的归一化;
Wq=∑p∈SGs(p)Gr(p)=∑p∈Sexp(−∥p−q∥22σ2s)exp(−∥Ip−Iq∥22σ2r)Wq=∑p∈SGs(p)Gr(p)=∑p∈Sexp(−∥p−q∥22σs2)exp(−∥Ip−Iq∥22σr2) {W_{q}}=\sum_{p\in S}G_{s}(p)G_{r}(p)=\sum_{p\in S}exp(-\frac{\left \| p-q \right \|^{2}}{2\sigma _{s}^{2}})exp(-\frac{\left \| I_{p}-I_{q} \right \|^{2}}{2\sigma _{r}^{2}}) Wq​=p∈S∑​Gs​(p)Gr​(p)=p∈S∑​exp(−2σs2​∥p−q∥2​)exp(−2σr2​∥Ip​−Iq​∥2​)
  在平坦区域,滤波器中每个像素点的GrGr G_{r} Gr​ 值相近,空间距离权重GsGs G_{s} Gs​主导滤波效果。在边缘区域,边缘同侧的GrGr G_{r} Gr​ 值相近,且远大于边缘另一侧的GrGr G_{r} Gr​ 值,此时另一侧的像素点的权重对滤波结果几乎不影响,边缘信息得到保护。表现出了一定的自适应性。

  在平坦区域出现噪声点时,噪声点周围的信号的权值都很小,在进行归一化后,这些权值得到了提升,因此对噪声点也有滤除效果。
双边滤波示意图

双边滤波OpenCV实现

  在OpenCV中已经有编辑好的双边滤波的函数;

void bilateralFilter( InputArray src, OutputArray dst, int d,double sigmaColor, double sigmaSpace,int borderType = BORDER_DEFAULT );
  • 1
  • 2
  • 3

  函数中的参数依次表示src:输入图像,dst: 输出图像,d:滤波窗口的直径(函数注释中使用的是Diameter,那么很可能函数中选取的窗口是圆形窗口),sigmaColor:像素值域方差,sigmaSpace:空间域方差,以及边缘处理方式。

  根据算法原理,我编写了自己的双边滤波函数;其中的核心部分如下;

//-------------------------------------------------------------
//作者:不用先生,2018.11.26
//自实现的图像双边滤波算法
//bilateral.cpp
//-------------------------------------------------------------
for (int i = 0; i < row; i++)    //对每一个点进行处理
{for (int j = 0; j < col; j++){double weightSum = 0;double filterValue = 0;for (int row_d = -(d / 2); row_d <= (d / 2); row_d++)   //以图像中的一点为中心,d为边长的方形区域内进行计算{for (int col_d = -(d / 2); col_d <= (d / 2); col_d++){double distance_Square = row_d*row_d + col_d*col_d;double value_Square = pow((scr.at<uchar>(i, j) - copyBorder_dst.at<uchar>(i + (d / 2) + row_d, j + (d / 2) + col_d)), 2);double weight = exp(-1 * (distance_Square / (2 * sigmaSpace*sigmaSpace) + value_Square / (2 * sigmaColor*sigmaColor)));weightSum += weight;               //求滤波窗口内的权重和,用于归一化;filterValue += (weight*copyBorder_dst.at<uchar>(i + (d / 2) + row_d, j + (d / 2) + col_d));}}dst.at<uchar>(i, j) = filterValue / weightSum;}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

  从代码中可以看出,我选择的是一个方形区域而不是圆形区域进行滤波计算,大家如果觉得欠妥,在自己编写代码时可以修改成圆形区域,也很简单。完整代码,可以到这里下载,或者直接在评论区留下自己的邮箱,我看到留言后会尽快发的您的邮箱。

测试结果

  用自己编写的代码、OpenCV自带的双边滤波函数以及高斯滤波函数分别对一张彩色图像今进行处理,并对比了结果。
在这里插入图片描述
  这里出现了很奇怪的现象,所有输入参数相同时(我选取参数的是d=21;sigmaColor=10;sigmaSpace = 10;),我的函数计算的结果比OpenCV自带的 bilateralFilter 函数的处理结果更加平滑。当把 bilateralFilter 函数的sigmaColorsigmaSpace参数调整为两到三倍的时候, bilateralFilter 函数的结果与我的计算结果相近。这种差异性的结果不应该是窗口选取方式不同导致的。具体原因,我觉得可能与 bilateralFilter 函数中方差的应用有关。但是总的来说,两个函数都对图像有一定的平滑效果,并很好地保护了边缘信息。

  本博客中只讲述了双边滤波最基础的原理以及实现过程,这种计算方法比较耗时,后续的人们做了一系列的工作,用于提升双边滤波的计算效率。大家感兴趣的可以去了解一下。

参考

  1. Tomasi C, Manduchi R. Bilateral filtering for gray and color images[C]//Computer Vision, 1998. Sixth International Conference on. IEEE, 1998: 839-846.
  2. He K, Sun J, Tang X. Guided image filtering[J]. IEEE transactions on pattern analysis & machine intelligence, 2013 (6): 1397-1409.

  已完。。

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

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

相关文章

java代码做repeat次运算,从键盘输入几个数,比最值

总结&#xff1a;今天这个题目有点灵活&#xff0c;因为它不但要求输出结果&#xff0c;还要进行几次相同的输入&#xff0c;不退出循环 import java.util.Scanner;//从键盘一次输入更多的数&#xff0c;然后把每一次的数进行---可比较&#xff0c;或输出 public class ertyw {…

与C语言有关的面试题目

1. 用预处理指令#define 声明一个常数&#xff0c;用以表明1年中有多少秒&#xff08;忽略闰年问题&#xff09; #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 2. 写一个“标准”宏MIN&#xff0c;这个宏输入两个参数并返回较小的一个。 #define MIN(A,B) ((A) < (B) …

用SQL语句更改数据库名,表名,列名

参考SQL Server联机丛书的 sp_renamedb与sp_rename一、更改数据库名sp_renamedb更改数据库的名称。语法sp_renamedb [ dbname ] old_name ,[ newname ] new_name 参数[ dbname ] old_name 是数据库的当前名称。old_name 为 sysname 类型&#xff0c;无默认值…

将区块链哈希转化为文字标题?IPSE哈希技术Hashlink解释

前言 在人类历史中&#xff0c;有多次的转化改变了信息文明走向。第一个是人类语言的诞生。将人类从抽象的声音识别交流转化为具体的文字交流。第二个是二进制的广泛使用。二进制是电子信息技术的巨大进步&#xff0c;让机器用0和1就能处理各类信息&#xff0c;二进制成就了今天…

Gabor滤波器原理

一、什么是Gabor函数&#xff08;以下内容含部分翻译自维基百科&#xff09; 在图像处理中&#xff0c;Gabor函数是一个用于边缘提取的线性滤波器。Gabor滤波器的频率和方向表达同人类视觉系统类似。研究发现&#xff0c;Gabor滤波器十分适合纹理表达和分离。在空间域中&#x…

Linux中的MAN命令

学习Linux的同学&#xff0c;都会使用man来查阅一些命令的帮助信息&#xff0c;常见的使用方法就是“man 命令名称”这样简单的格式。本文就对man命令简要介绍一下。 l man命令的章节 man就是manual的缩写&#xff0c;用来查看系统中自带的各种参考手册&#xff0c;但是手册页分…

java程序调用Oracle 存储过程 获取返回值(无返回,非结果集,结果集)

oracle中procedure是不能有返回值的&#xff0c;要想返回值&#xff0c;就得有输出参数&#xff0c;同样要想返回记录集&#xff0c;可以把游标类型作为输出参数。 下面是详细情况说明&#xff1a; 一&#xff1a;无返回值的存储过程调用 存储过程&#xff1a; create or repl…

jeecms附件标签用法

[#if content.attachments?size gt 0] [#list content.attachments as attach] <a id"attach${attach_index}">附件下载</a> [/#list] [/#if] 转载于:https://www.cnblogs.com/Jeely/p/11195310.html

递归的理解

其实就解决两个问题 1、当前应该怎么做&#xff1b; 2、下一步应该怎么做&#xff1b; 见下面的一个短小的例子&#xff1a;倒着输出刚才输入的整数。 #include<stdio.h>void fun(int);int main(void) {int a 0;printf("value of a \n");scanf("%d&quo…

点云配准

https://www.cnblogs.com/endlesscoding/p/10033527.html https://www.cnblogs.com/yhlx125/p/4955337.html https://blog.csdn.net/qq_41581769/article/details/89460153

支持多并发的单例有哪几种写法

一.什么是单例以及单例的使用场景就不多说了&#xff0c;不清楚的可以看我上篇文章或者自行查找 二.单例和多并发之间的规则 单例就是只能创建一个实例对象&#xff0c;而多并发情况下如果不处理一下单例的写法很难保证只创建一个实例对象&#xff0c;所以后面会出问题 处理的思…

兼容各种浏览器的自动左右滚动兼左右点击滚动代码

直接切入正题 红色表示要统一&#xff08;所有的id&#xff09; 演示地址&#xff1a;http://www.er-china.com/index.php?mcontent&cindex&alists&catid772 本框架为phpcms&#xff0c;大家可根据自己的框架更改循环。 <div class"rollBox"> <…

同步数据库仅在Worker内,目前只有Chrome6支持

Database.html <!DOCTYPE HTML><html> <head> <meta charset"UTF-8"> <title></title> </head> <body> <script> if(window.Worker){ var workernew Worker(worker.js); //向worker发送消息 wo…

全局曝光和卷帘曝光的区别

全局曝光和卷帘曝光是常见的相机曝光方式。一般来说&#xff0c;CCD相机是全局曝光&#xff0c;而CMOS相机则存在卷帘曝光。那么&#xff0c;这两种方式孰优孰劣呢&#xff1f;或者说&#xff0c;他们两者的差别在哪里呢&#xff1f;那么&#xff0c;先从两者的定义说起。 全局…

*p++、*(p++)、*++p、*(++p)的区别

1、*p 与 *(p)的区别 因为“”的优先级大于“*”&#xff0c;所以*p 相当于*(p)。 但是p表示先运算再&#xff0c;所以*p或者*(p)&#xff0c;其实等价于“先(*p)&#xff0c;然后再p”。 注意&#xff0c;“先(*p)&#xff0c;然后再p”不能表示成“ (*p)”&#xff0c;因为(*…

MySQL常用总结

创建数据库&#xff0c;指定编码utf8 create database wish charset utf8; 删除库 drop database wish; 使用库 use wish; 查看有什么表 show tables; 删除表 drop table wish; 清空表所有数据(主键从1开始) truncate stu; 显示表结构 desc wish; show create table wish; 设置…

Titanium 列表显示TableView

效果&#xff1a; Titanium中列表显示需要创建TableView var tableView Ti.UI.createTableView({style: Ti.UI.iPhone.TableViewCellSelectionStyle.NONE //TableView样式}); TableView的每一个行叫做TableViewRow 设置TableViewRow的hasChild为true便可显示这样的效果&#x…

Matlab的fspecial函数

函数原型 h fspecial(type) h fspecial(type&#xff0c;para) 根据函数原型对fspecial函数作个说明&#xff0c;fspecial是用来生成滤波器&#xff08;也叫算子&#xff09;的函数&#xff0c;使用type参数来指定滤波器的种类&#xff0c;使用para来对具体的滤波器种类添…

discuz x2.5插件开发傻瓜图文教程,用demo说话

2019独角兽企业重金招聘Python工程师标准>>> 刚刚接触DZ的插件开发&#xff0c;记个傻瓜图文教程&#xff0c;一是分享给初学者&#xff0c;二是方便自己以后回忆。 本篇文章适合人群&#xff1a;有一定的PHP开发经验&#xff0c;想通过一个简单明了的demo快速了解…

uboot源码——gd_t 类型、bd_t 类型

bd_t、gd_t是u-boot中两个重要的数据结构&#xff0c;初始化操作中很多全局变量都要靠这两个数据结构来保存或传递。 两者分别定义在include/asm-arm/u-boot.h、include/asm-arm/global_data.h中。 一、bd_t 类型 struct bd_info 这个结构体类型&#xff0c;主要是用来保存板子…