双边滤波与引导滤波

article/2025/10/26 3:30:35

双边滤波与引导滤波

分类: AI and Computer Vision 344人阅读 评论(0) 收藏 举报
图像处理 滤波

双边滤波

双边滤波很有名,使用广泛,简单的说就是一种同时考虑了像素空间差异与强度差异的滤波器,因此具有保持图像边缘的特性。

先看看我们熟悉的高斯滤波器


其中W是权重,i和j是像素索引,K是归一化常量。公式中可以看出,权重只和像素之间的空间距离有关系,无论图像的内容是什么,都有相同的滤波效果。

再来看看双边滤波器,它只是在原有高斯函数的基础上加了一项,如下


其中 I 是像素的强度值,所以在强度差距大的地方(边缘),权重会减小,滤波效应也就变小。总体而言,在像素强度变换不大的区域,双边滤波有类似于高斯滤波的效果,而在图像边缘等强度梯度较大的地方,可以保持梯度。


引导滤波

引导滤波是近三年才出现的滤波技术,知道的人还不多。它与双边滤波最大的相似之处,就是同样具有保持边缘特性。在引导滤波的定义中,用到了局部线性模型,至于该模型,可以暂时用下图简单的理解


该模型认为,某函数上一点与其邻近部分的点成线性关系,一个复杂的函数就可以用很多局部的线性函数来表示,当需要求该函数上某一点的值时,只需计算所有包含该点的线性函数的值并做平均即可。这种模型,在表示非解析函数上,非常有用。

同理,我们可以认为图像是一个二维函数,而且没法写出解析表达式,因此我们假设该函数的输出与输入在一个二维窗口内满足线性关系,如下


其中,q是输出像素的值,I是输入图像的值,i和k是像素索引,a和b是当窗口中心位于k时该线性函数的系数。其实,输入图像不一定是待滤波的图像本身,也可以是其他图像即引导图像,这也是为何称为引导滤波的原因。对上式两边取梯度,可以得到


即当输入图像I有梯度时,输出q也有类似的梯度,现在可以解释为什么引导滤波有边缘保持特性了。

下一步是求出线性函数的系数,也就是线性回归,即希望拟合函数的输出值与真实值p之间的差距最小,也就是让下式最小


这里p只能是待滤波图像,并不像I那样可以是其他图像。同时,a之前的系数(以后都写为e)用于防止求得的a过大,也是调节滤波器滤波效果的重要参数。通过最小二乘法,我们可以得到


其中,是I在窗口w_k中的平均值,是I在窗口w_k中的方差,是窗口w_k中像素的数量,是待滤波图像p在窗口w_k中的均值。

在计算每个窗口的线性系数时,我们可以发现一个像素会被多个窗口包含,也就是说,每个像素都由多个线性函数所描述。因此,如之前所说,要具体求某一点的输出值时,只需将所有包含该点的线性函数值平均即可,如下


这里,w_k是所有包含像素i的窗口,k是其中心位置。

当把引导滤波用作边缘保持滤波器时,往往有 I = p ,如果e=0,显然a=1, b=0是E(a,b)为最小值的解,从上式可以看出,这时的滤波器没有任何作用,将输入原封不动的输出。如果e>0,在像素强度变化小的区域(或单色区域),有a近似于(或等于)0,而b近似于(或等于),即做了一个加权均值滤波;而在变化大的区域,a近似于1,b近似于0,对图像的滤波效果很弱,有助于保持边缘。而e的作用就是界定什么是变化大,什么是变化小。在窗口大小不变的情况下,随着e的增大,滤波效果越明显。

在滤波效果上,引导滤波和双边滤波差不多,在一些细节上,引导滤波较好。引导滤波最大的优势在于,可以写出时间复杂度与窗口大小无关的算法(打算在之后的文章中讨论),因此在使用大窗口处理图片时,其效率更高。

关于引导滤波更多的讨论和应用,可以参看下面的论文

GuidedFilter_ECCV10.pdf

引导滤波的OpenCV实现

分类: AI and Computer Vision 414人阅读 评论(3) 收藏 举报
OpenCV 图像处理 算法 C++

上一篇文章已经说了引导滤波的基本理论,而且我们也知道引导滤波可以写出时间复杂度与窗口大小无关的算法,现在就来使用C++并借助OpenCV实现这一算法。

实现这种算法的关键思想是盒式滤波(box filter),而且必须是通过积分图来实现的盒式滤波,否则不可能与窗口大小无关,好在OpenCV的boxFilter函数满足这个要求。

再看看引导滤波的公式


先计算a_k的分子,Ip 在窗口w_k中的和,再除以窗口中像素的个数,刚好就是盒式滤波,因此我们可以将输入的引导图像 I 和滤波图像 p 相乘,并对相乘后的图像做box filtering,即得第一项的结果。后面的分别为 I 和 p 在窗口w_k中均值,因此分别对 I 和 p 进行box filtering,再将box filtering之后的结果相乘即可。实际上,a_k的分子就是 Ip 在窗口w_k中的协方差。

接下来计算a_k的分母部分。是引导图 I 在窗口w_k中的方差,学过概率论与数理统计的朋友应该知道,方差和期望(均值)之间是有关系的,如下式


因此在计算 I 的方差时,我们可以先计算 I*I 的均值,再减去 I 均值的平方即的平方。在方法上,计算 I*I 的均值和计算 Ip 的均值是一样的。最后,对计算出来的方差图像,加上常量e(每个元素都加e),分母就计算完了,自然,a_k在所有窗口中的值也就得到了。b_k的计算太简单了,大家都懂的。

注意,我们的计算都是对整个图像的,以图像为单位进行计算,所以最后算出的也是两张图,a_k的图(左边)和b_k的图(右边),如下


在图中可以看到,在边缘部分或变化剧烈的部分,a的值接近于1(白色),b的值接近为0(黑色),而在变化平坦的区域,a的值接近0(黑色),b的值为平坦区域像素的均值。这与上一篇文章中所说的规律是一致的。

下面看第二个公式


输出值q又与两个均值有关,分别为a和b在窗口w_i中的均值(不是w_k),所以还是box filtering,我们将上一步得到两个图像都进行盒式滤波,得到两个新图:a_i和b_i,然后用a_i乘以引导图像 I ,再加上b_i,即得最终滤波之后的输出,如下(左边为原图,右边为滤波之后的图像,其中滤波窗口半径为8,e的值为500):



下面是整个算法的代码,仅供参考

[cpp] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. void guidedFilter(Mat& source, Mat& guided_image, Mat& output, int radius, float epsilon)
  2. {
  3. CV_Assert(radius >= 2 && epsilon > 0);
  4. CV_Assert(source.data != NULL && source.channels() == 1);
  5. CV_Assert(guided_image.channels() == 1);
  6. CV_Assert(source.rows == guided_image.rows && source.cols == guided_image.cols);
  7. Mat guided;
  8. if (guided_image.data == source.data)
  9. {
  10. //make a copy
  11. guided_image.copyTo(guided);
  12. }
  13. else
  14. {
  15. guided = guided_image;
  16. }
  17. //将输入扩展为32位浮点型,以便以后做乘法
  18. Mat source_32f, guided_32f;
  19. makeDepth32f(source, source_32f);
  20. makeDepth32f(guided, guided_32f);
  21. //计算I*p和I*I
  22. Mat mat_Ip, mat_I2;
  23. multiply(guided_32f, source_32f, mat_Ip);
  24. multiply(guided_32f, guided_32f, mat_I2);
  25. //计算各种均值
  26. Mat mean_p, mean_I, mean_Ip, mean_I2;
  27. Size win_size(2*radius + 1, 2*radius + 1);
  28. boxFilter(source_32f, mean_p, CV_32F, win_size);
  29. boxFilter(guided_32f, mean_I, CV_32F, win_size);
  30. boxFilter(mat_Ip, mean_Ip, CV_32F, win_size);
  31. boxFilter(mat_I2, mean_I2, CV_32F, win_size);
  32. //计算Ip的协方差和I的方差
  33. Mat cov_Ip = mean_Ip - mean_I.mul(mean_p);
  34. Mat var_I = mean_I2 - mean_I.mul(mean_I);
  35. var_I += epsilon;
  36. //求a和b
  37. Mat a, b;
  38. divide(cov_Ip, var_I, a);
  39. b = mean_p - a.mul(mean_I);
  40. //对包含像素i的所有a、b做平均
  41. Mat mean_a, mean_b;
  42. boxFilter(a, mean_a, CV_32F, win_size);
  43. boxFilter(b, mean_b, CV_32F, win_size);
  44. //计算输出 (depth == CV_32F)
  45. output = mean_a.mul(guided_32f) + mean_b;
  46. }
void guidedFilter(Mat& source, Mat& guided_image, Mat& output, int radius, float epsilon)
{CV_Assert(radius >= 2 && epsilon > 0);CV_Assert(source.data != NULL && source.channels() == 1);CV_Assert(guided_image.channels() == 1);CV_Assert(source.rows == guided_image.rows && source.cols == guided_image.cols);Mat guided;if (guided_image.data == source.data){//make a copyguided_image.copyTo(guided);}else{guided = guided_image;}//将输入扩展为32位浮点型,以便以后做乘法Mat source_32f, guided_32f;makeDepth32f(source, source_32f);makeDepth32f(guided, guided_32f);//计算I*p和I*IMat mat_Ip, mat_I2;multiply(guided_32f, source_32f, mat_Ip);multiply(guided_32f, guided_32f, mat_I2);//计算各种均值Mat mean_p, mean_I, mean_Ip, mean_I2;Size win_size(2*radius + 1, 2*radius + 1);boxFilter(source_32f, mean_p, CV_32F, win_size);boxFilter(guided_32f, mean_I, CV_32F, win_size);boxFilter(mat_Ip, mean_Ip, CV_32F, win_size);boxFilter(mat_I2, mean_I2, CV_32F, win_size);//计算Ip的协方差和I的方差Mat cov_Ip = mean_Ip - mean_I.mul(mean_p);Mat var_I = mean_I2 - mean_I.mul(mean_I);var_I += epsilon;//求a和bMat a, b;divide(cov_Ip, var_I, a);b = mean_p - a.mul(mean_I);//对包含像素i的所有a、b做平均Mat mean_a, mean_b;boxFilter(a, mean_a, CV_32F, win_size);boxFilter(b, mean_b, CV_32F, win_size);//计算输出 (depth == CV_32F)output = mean_a.mul(guided_32f) + mean_b;
}
[cpp] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. void makeDepth32f(Mat& source, Mat& output)
  2. {
  3. if (source.depth() != CV_32F ) > FLT_EPSILON)
  4. source.convertTo(output, CV_32F);
  5. else
  6. output = source;
  7. }
void makeDepth32f(Mat& source, Mat& output)
{if (source.depth() != CV_32F ) > FLT_EPSILON)source.convertTo(output, CV_32F);elseoutput = source;
}


(本文图片均来自网络)


http://chatgpt.dhexx.cn/article/Q4kiSGZX.shtml

相关文章

【图像处理】——双边滤波

【fishing-pan:https://blog.csdn.net/u013921430 转载请注明出处】 双边滤波 高斯滤波是最常用的图像去噪方法之一,它能很好地滤除掉图像中随机出现的高斯噪声,但是在之前的博客中提到过,高斯滤波是一种低通滤波(有兴…

【八】双边滤波

1.高斯滤波 高斯滤波的定义如下: 其中高斯函数为: 高斯滤波是领域内相邻像素的加权平均,权重值为G(||p-q||),和均值滤波,中值滤波一样,都是将噪声(高频信息)滤除,但是边…

双边滤波原理和实现

双边滤波原理 双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。 双边滤波器之所以能够做到在平滑去噪的同…

双边滤波

1 双边滤波简介 双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。具有简单、非迭代、局部的特点。 双边滤…

数字图像处理(九)双边滤波

文章目录 一、何为双边滤波?二、为什么要使用双边滤波?三、双边滤波原理1.空间域核2.值域核3.模板相乘 四、 w d w_d wd​和 w r w_r wr​和 σ \sigma σ的理解五、C代码实现1.opencv中Mat的一点小知识2.关于边界的处理3.双边滤波代码 一、何为双边滤波…

双边滤波(Bilateral Filtering)

双边滤波(Bilateral Filtering) 1、基本思路 双边滤波(Bilateral Filtering)的基本思路是同时考虑像素点的空域信息和值域信息。即先根据像素值对要用来进行滤波的邻域做一个分割或分类,再给该点所属的类别相对较高的…

三种经典图像滤波方法介绍——双边滤波(Bilateral filter)、导向滤波(Guided Fliter)、滚动导向滤波(RollingGuidedFilter)

文章目录 一、前言二、双边滤波(Bilateral filter)2.1 双边滤波的理论介绍及公式推导2.2 双边滤波的matlab程序实现 三、导向滤波(Guided Fliter)3.1 导向滤波的理论介绍及公式推导3.2 导向滤波matlab代码实现 四、滚动导向滤波(RollingGuidedFilter)4.1 滚动导向滤波的理论介绍…

图像处理:双边滤波算法

今天主要是回顾一下双边滤波,我曾经在这篇——图像处理:推导五种滤波算法中推导过它,其中包含了我自己写的草稿图。 目录 双边滤波算法原理 (1)空间域核 (2)值域核 理解双边滤波 空域权重​…

Bilateral Filters(双边滤波算法)的超简单原理,学不会你打我。

摘要: 双边滤波(Bilateral Filters)是非常常用的一种滤波,它可以达到保持边缘、降噪平滑的效果。和其他滤波原理一样,双边滤波也是采用加权平均的方法,用周边像素亮度值的加权平均代表某个像素的强度,所用的加权平均基…

jQuery源码分析理解

1: 首先我们先来看一下jquery代码的整体结构 代码从16行开始为真正的jquery源码,我们看到Jquery源码第一个()中是定义了一个匿名function( window, undefined ) {};接着末尾有个(window),就表示执行这个匿名function,…

jQuery源码分析(一)

jQuery源码分析(一) 我们知道在jQuery中在使用选择器或者给元素绑定事件的时候都是通过$来操作的。那么基于JavaScript面向对象的思想,我们可以把jQuery看做一个函数或者对象,它里边存储了大量的方法,是一个类库。 $代…

jQuery源码阅读(一)---jQuery源码整体架构

之前用jQuery库写了两个小例子(结合Apache、PHP实现的简易聊天室以及音乐播放器),详见我的上两篇博客jQuery aJax技术以及PHP实现简单聊天室、 利用jQuery实现音乐播放器。为了更加深入了解jQuery库的架构以及巩固原生JS的基础和深度&#xf…

jquery源码解析

(function(a,b){})() JQuery源码的开头 (function(a,b){})(window)通常(function(){})()用来封装一些私有成员或者公共成员的导出。 1. 定义一个匿名函数,创建了一个“私有”的命名空间,该命名空间的变量和方法,不会破坏全局的命名空间。确…

jQuery源码下载和编译

下载 git clone https://github.com/jquery/jquery.git编译 下载完成后,进入jquery文件夹,运行如下命令: npm run build最后全部编译完成,生成的文件在目录dist文件夹下: 有兴趣的就可以开始研究源码了。

jQuery源码阅读

1. 立即执行函数 简化后的代码就是这样 (function(global, factory) {... })(window, function () {}); Q:采用立即执行函数的好处是什么呢? A: 通过定义一个匿名函数,创建了一个新的函数作用域,相当于创建了一个私有的命名空…

jQuery -- jQuery源码(一):核心功能

一、jQuery无new构建实例 1、$就是jQuery的别称 可以在$和jQuery对象挂在在window中,实现全局引用。 给Windows对象扩展一个$的属性,让它拿到jQuery构造函数的引用 可以用$访问到jQuery的构造函数 // jQuery.js (function(root) {var jQuery functio…

制作一个游戏编辑器玩玩(1)

今天准备着手例用空闲时间制作一个游戏编辑器,一是因为这些年来积累了不少的算法和制作经验,它们是分散的,零乱的,想搞一次规整。二是自己一起想做一个简单点的游戏编辑器,可以让自己的小朋友把自己的想法在上面实现&a…

游戏策划的软件与工具

游戏策划的软件与工具 UXplayer https://www.jianshu.com/p/ceddde705933 gongjutitle.png 本文修改自前公司的一份交接文档,分享了工作中一些常用的软件。 Axure 界面示意图/流程图制作软件 大前提:Windows系统、无法直连外网 Mac系统的话,…

Tiled游戏地图编辑器

下载 软件是免费的,直接官网下载就好了 下载链接:https://www.mapeditor.org/ 新建地图 左上角 >> 文件 >> 创建新地图 快捷键:ctrln 根据你的需求设置地图大小 导入素材新建图块集 左上角 >> 文件 >> 新图块 新建你的图集文件.png 如果你已…

Android游戏开发之地图编辑器的使用以及绘制地图 (四)

雨松MOMO带你走进游戏开发的世界之地图编辑器的使用以及绘制地图 雨松MOMO原创文章如转载,请注明:转载至我的独立域名博客雨松MOMO程序研究院,原文地址:http://www.xuanyusong.com/archives/211 Mappy中文地图编辑器的使用说明下载地址&#…