高斯滤波和双向滤波的区别与联系

1. 简介

          图像平滑是一个重要的操作,而且有多种成熟的算法。这里主要简单介绍一下Bilateral方法(双边滤波),这主要是由于前段时间做了SSAO,需要用bilateral blur 算法进行降噪。Bilateral blur相对于传统的高斯blur来说很重要的一个特性即可可以保持边缘(Edge Perseving),这个特点对于一些图像模糊来说很有用。一般的高斯模糊在进行采样时主要考虑了像素间的空间距离关系,但是却并没有考虑像素值之间的相似程度,因此这样我们得到的模糊结果通常是整张图片一团模糊。Bilateral blur的改进就在于在采样时不仅考虑像素在空间距离上的关系,同时加入了像素间的相似程度考虑,因而可以保持原始图像的大体分块进而保持边缘。在于游戏引擎的post blur算法中,bilateral blur常常被用到,比如对SSAO的降噪。

2. 原理

          滤波算法中,目标点上的像素值通常是由其所在位置上的周围的一个小局部邻居像素的值所决定。在2D高斯滤波中的具体实现就是对周围的一定范围内的像素值分别赋以不同的高斯权重值,并在加权平均后得到当前点的最终结果。而这里的高斯权重因子是利用两个像素之间的空间距离(在图像中为2D)关系来生成。通过高斯分布的曲线可以发现,离目标像素越近的点对最终结果的贡献越大,反之则越小。其公式化的描述一般如下所述:

其中的c即为基于空间距离的高斯权重,而用来对结果进行单位化。

         高斯滤波在低通滤波算法中有不错的表现,但是其却有另外一个问题,那就是只考虑了像素间的空间位置上的关系,因此滤波的结果会丢失边缘的信息。这里的边缘主要是指图像中主要的不同颜色区域(比如蓝色的天空,黑色的头发等),而Bilateral就是在Gaussian blur中加入了另外的一个权重分部来解决这一问题。Bilateral滤波中对于边缘的保持通过下述表达式来实现:

        其中的s为基于像素间相似程度的高斯权重,同样用来对结果进行单位化。对两者进行结合即可以得到基于空间距离、相似程度综合考量的Bilateral滤波:

        上式中的单位化分部综合了两种高斯权重于一起而得到,其中的cs计算可以详细描述如下:

且有

且有

        上述给出的表达式均是在空间上的无限积分,而在像素化的图像中当然无法这么做,而且也没必要如此做,因而在使用前需要对其进行离散化。而且也不需要对于每个局部像素从整张图像上进行加权操作,距离超过一定程度的像素实际上对当前的目标像素影响很小,可以忽略的。限定局部子区域后的离散化公就可以简化为如下形式:

        上述理论公式就构成了Bilateral滤波实现的基础。为了直观地了解高斯滤波与双边滤波的区别,我们可以从下列图示中看出依据。假设目标源图像为下述左右区域分明的带有噪声的图像(由程序自动生成),蓝色框的中心即为目标像素所在的位置,那么当前像素处所对应的高斯权重与双边权重因子3D可视化后的形状如后边两图所示:            

左图为原始的噪声图像;中间为高斯采样的权重;右图为Bilateral采样的权重。从图中可以看出Bilateral加入了相似程度分部以后可以将源图像左侧那些跟当前像素差值过大的点给滤去,这样就很好地保持了边缘。为了更加形象地观察两者间的区别,使用Matlab将该图在两种不同方式下的高度图3D绘制出来,如下:

  

上述三图从左到右依次为:双边滤波,原始图像,高斯滤波。从高度图中可以明显看出Bilateral和Gaussian两种方法的区别,前者较好地保持了边缘处的梯度,而在高斯滤波中,由于其在边缘处的变化是线性的,因而就使用连累的梯度呈现出渐变的状态,而这表现在图像中的话就是边界的丢失(图像的示例可见于后述)。                                              

3. 代码实现

有了上述理论以后实现Bilateral Filter就比较简单了,其实它也与普通的Gaussian Blur没有太大的区别。这里主要包括3部分的操作: 基于空间距离的权重因子生成;基于相似度的权重因子的生成;最终filter颜色的计算。

3.1 Spatial Weight

这就是通常的Gaussian Blur中使用的计算高斯权重的方法,其主要通过两个pixel之间的距离并使用如下公式计算而来:

其中的就表示两个像素间的距离,比如当前像素与其右边紧邻的一个像素之间的距离我们就可以用来计算,也即两个二维向量{0 , 0}以及{0 , 1}之间的欧氏距离。直接计算一个区域上的高斯权重并单位化后就可以进行高斯模糊了。

3.2 Similarity Weight

与基于距离的高斯权重计算类似,只不过此处不再根据两个pixel之间的空间距离,而是根据其相似程度(或者两个pixel的值之间的距离)。

其中的表示两个像素值之间的距离,可以直接使用其灰度值之间的差值或者RGB向量之间的欧氏距离。

3.3 Color Filtering

有了上述两部分所必需的权重因子之后,那么具体的双边滤波的实现即与普通的高斯滤波无异。主要部分代码如下述:

[cpp] view plaincopy
  1. UCHAR3 BBColor(int posX , int posY)  
  2. {  
  3.     int centerItemIndex = posY * picWidth4 + posX * 3 , neighbourItemIndex;  
  4.     int weightIndex;  
  5.     double gsAccumWeight = 0;  
  6.     double accumColor = 0;  
  7.   
  8.     // 计算各个采样点处的Gaussian权重,包括closeness,similarity  
  9.     for(int i = -number ; i <= number ; ++i)  
  10.     {  
  11.         for(int j = -number ; j <= number ; ++j)  
  12.         {  
  13.             weightIndex = (i + number) * (number * 2 + 1) + (j + number);  
  14.             neighbourItemIndex = min(noiseImageHeight - 1 , max(0 , posY + j * radius)) * picWidth4 +  
  15.                              min(noiseImageWidth - 1  , max(0 , posX + i * radius)) * 3;  
  16.               
  17.             pCSWeight[weightIndex] = LookupGSWeightTable(pSrcDataBuffer[neighbourItemIndex] , pSrcDataBuffer[centerItemIndex]);  
  18.             pCSWeight[weightIndex] = pGSWeight[weightIndex] * pGCWeight[weightIndex];  
  19.             gsAccumWeight += pCSWeight[weightIndex];  
  20.         }  
  21.     }  
  22.       
  23.     // 单位化权重因子  
  24.     gsAccumWeight = 1 / gsAccumWeight;  
  25.     for(int i = -number ; i <= number ; ++i)  
  26.     {  
  27.         for(int j = -number ; j <= number ; ++j)  
  28.         {  
  29.             weightIndex = (i + number) * (number * 2 + 1) + (j + number);  
  30.             pCSWeight[weightIndex] *= gsAccumWeight;  
  31.         }  
  32.     }  
  33.       
  34.     // 计算最终的颜色并返回  
  35.     for(int i = -number ; i <= number ; ++i)  
  36.     {  
  37.         for(int j = -number ; j <= number ; ++j)  
  38.         {  
  39.             weightIndex = (i + number) * (number * 2 + 1) + (j + number);  
  40.             neighbourItemIndex = min(noiseImageHeight - 1 , max(0 , posY + j * radius)) * picWidth4 +  
  41.                                  min(noiseImageWidth - 1  , max(0 , posX + i * radius)) * 3;  
  42.             accumColor += pSrcDataBuffer[neighbourItemIndex + 0] * pCSWeight[weightIndex];  
  43.         }  
  44.     }  
  45.   
  46.     return UCHAR3(accumColor , accumColor , accumColor);  
  47. }  

 其中的相似度分部的权重s主要根据两个Pixel之间的颜色差值计算面来。对于灰度图而言,这个差值的范围是可以预知的,即[-255, 255],因而为了提高计算的效率我们可以将该部分权重因子预计算生成并存表,在使用时快速查询即可。使用上述实现的算法对几张带有噪声的图像进行滤波后的结果如下所示:

   

    

上图从左到右分别为:双边滤波;原始图像;高斯滤波。从图片中可以较为明显地看出两种算法的区别,最直观的感受差别就是使用高斯算法后整张图片都是一团模糊的状态;而双边滤波则可以较好地保持原始图像中的区域信息,看起来仍然嘴是嘴、眼是眼(特别是在第一张美女图像上的效果!看来PS是灰常重要啊~~^o^)。

4. 在SSAO中的使用

在上述实现中的边缘判定函数主要是通过两个像素值之间的差异来决定,这也是我们观察普通图片的一种普遍感知方式。当然,也可以根据使用的需求情况来使用其它的方式判断其它定义下的边缘,比如使用场景的depth或是normal。比如在对SSAO进行滤波时可以直接使用Depth值来行边缘判断。首先,设置一个深度的阈值,在作边缘检测时比较两点间的depth差值,如果差值大于阈值,则认为其属于不同的区域,则此处就应为边界。使用此方法得到的效果可见于下图所示:

高斯滤波

双边滤波

在得到滤波之后的SSAO图像之后,与原始图像进行直接的整合就可以得到最终的渲染效果,如下图所示:

SSAO关闭

SSAO开启

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

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

相关文章

Eclipse变量名自动补全问题 自定义上屏按键为TAB

Eclipse空格等号等都可以上屏&#xff0c;这样有时候输入变量名再按空格就会自动补全&#xff0c;非常讨厌。那么怎么办呢&#xff1f; 1.首先你的Eclipse需要装有 Eclipse plug-in development environment 和 Eclipse JDT Plug-in Developer Resources 或者直接去下载一个和…

Dreamweaver CS6 Mac破解版

介于之前小子分享的Mac版的Adobe的PS CS6和Illustrator CS6&#xff0c;有用户要求小子分享下Dreamweaver&#xff0c;小子当然乐意效劳。 Dreamweaver CS6 是世界顶级软件厂商Adobe推出的一套拥有可视化编辑界面&#xff0c;用于制作并编辑网站和移动应用程序的网页设计软件。…

【pyqt5学习】——graphicView显示matplotlib图像

目录 一、导入模块 二、自定义一个matplotlib窗口类Figure 三、利用QT_designer绘制窗口 四、写逻辑代码 五、结果展示 一、导入模块 import matplotlibmatplotlib.use("Qt5Agg") from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg from matplo…

what is ssao

说到ssao 就要从ao说起&#xff0c;ao&#xff0c;即间接环境光遮蔽技术。我们知道现实中的光线&#xff0c;除了来自太阳和电灯的直射光线以外&#xff0c;光线碰到物体以后&#xff0c;还会再次反射&#xff0c;折射&#xff0c;而再次反射折射的过程中&#xff0c;又会被其他…

【pyqt5学习】——groupBox显示matplotlib图像

目录 一、导入模块 二、创建matplotlib窗口类 三、qt_designer设计窗口 四、逻辑代码 五、结果展示 一、导入模块 import matplotlibmatplotlib.use("Qt5Agg") from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg from matplotlib.figure impor…

杭电1027Ignatius and the Princess II模拟

地址&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1027 题目&#xff1a; Problem DescriptionNow our hero finds the door to the BEelzebub feng5166. He opens the door and finds feng5166 is about to kill our pretty Princess. But now the BEelzebub has t…

angular 使用rxjs 监听同级兄弟组件数据变化

angular 的官网给出了父子组件之间数据交互的方法&#xff0c;如ViewChild、EventEmitter 但是如果要在同级组件之间进行数据同步&#xff0c;似乎并没有给出太多的信息。 有时候我们想&#xff0c;在一个组件中修改数据之后&#xff0c;马上反映到另外一个组件中&#xff0c; …

pic

转载于:https://www.cnblogs.com/edisonxiang/p/5392651.html

OpenCV之cvSmooth函数平滑滤波

1、cvSmooth函数用法 定义原型 <span style"font-size:12px;"> void cvSmooth( const CvArr* src, CvArr* dst,int smoothtypeCV_GAUSSIAN,int param1, int param2, double param3, double param4 );</span>src:输入图像. dst:输出图像. smoot…

【python数字信号处理】——DFT、DTFT(频谱图、幅度图、相位图)

目录 一、离散时间傅里叶变换DTFT 二、离散傅里叶变换DFT 三、DFT与DTFT的关系 ​ 参考&#xff1a; 《数字信号处理》——&#xff08;一&#xff09;.DTFT、DFT(python实现)_远行者223的博客-CSDN博客python绘制频谱图DTFT&#xff0c;DFTpython绘制频谱图&#xff1a;…

ERROR:Tried to register widget id ==basemapGalleryDiv but that id is already registered解决办法

在ArcGIS Server开发中&#xff0c;遇到DIV已经被注册的情况&#xff0c;不能对原DIV内容进行更新。这里需要调用Dojo的destroyRecursive&#xff08;&#xff09;方法&#xff0c;逐个销毁该Widget下的子元素及其后代元素。然后就可以在原DIV上注册新的小部件。 示例代码&…

图像金字塔

图像金字塔被广泛用于各种视觉应用中。图像金字塔是一个图像集合&#xff0c;集合中所有的图像都源于同一个原始图像&#xff0c;而且是通过对原始图像连续降采样活得&#xff0c;直到达到某个中止条件才停止降采样。&#xff08;当然&#xff0c;降为一个像素肯定是中止条件。…

【python数字信号处理】——Z变换

目录 一、公式 二、代码 三、结果 一、公式 频域变量&#xff1a;z 时域变量&#xff1a;n 常见序列的Z变换&#xff1a;信号与系统复习归纳&#xff08;十一&#xff09;&#xff1a;Z变换例题_百把人的博客-CSDN博客_z变换例题基于东南大学陈从颜译《信号、系统和变换》和…

九宫格拼图 支持44 55等

代码下载转载于:https://www.cnblogs.com/ygcool/p/5395343.html

一体化点焊机将要取代分体式焊钳在汽车制造生产线上的使用

目前大多数汽车制造厂及相关配套钣金件厂家选用的是悬挂式点焊机及分体式焊钳&#xff0c;从焊接变压器的功率参数看&#xff0c;约70 % 为160KVA 的&#xff0c;约30 % 为200 kVA 的。原因主要有两方面&#xff0c;一是新材料如镀锌钢板、高强度钢板、铝合金板的应用&#xff…

【python数字信号处理】——线性卷积

目录 一、公式概念 二、代码 1、numpy库 2、自定义打印出每一步结果 三、结果 一、公式概念 线性卷积_百度百科线性卷积(linear convolution) 在时域描述线性系统输入和输出之间关系的一种运算。这种运算在线性系统分析和信号处理中应用很多&#xff0c;通常简称卷积。中文…

第五章 - 图像形态学 - 基于图像金字塔的图像分割(cvPyrSegmentation)

本例程涉及到几个数据结构及方法&#xff0c;CvMemStorage、cvPyrSegmentation()、CvConnectedComp、cvGetSeqElem(). CvMemStorage CvMemStorage Growing memory storage typedef struct CvMemStorage { struct CvMemBlock* bottom;/* first allocated block */ struct CvM…

【调试】Linux下超强内存检测工具Valgrind

【调试】Linux下超强内存检测工具Valgrind 内容简介 Valgrind是什么&#xff1f;Valgrind的使用Valgrind详细教程1. Valgrind是什么&#xff1f; Valgrind是一套Linux下&#xff0c;开放源代码&#xff08;GPLV2&#xff09;的仿真调试工具的集合。Valgrind由内核&#xff08;c…

机器学习实战(python)-Ch02KNN-Notes

Chapter2 KNN 1.numpy.tile函数 格式&#xff1a;tile&#xff08;A,reps&#xff09; * A&#xff1a;array_like * 输入的array * reps&#xff1a;array_like * A沿各个维度重复的次数 举例&#xff1a;A[1,2] 1. tile(A,2) 结果&#xff1a;[1,2,1,2] 2. tile(A,(2,3)) 结果…

猜1-10的数字python脚本

#!/usr/bin/python#coding:utf-8import randomnumrandom.randint(1,10)while True:caiint(raw_input(请输入随机数字:))if cai num:print 猜对了exit()elif cai > num:print 猜大了else:print 猜小了非交互式的cp脚本#!/usr/bin/python#coding:utf-8import sysfile1sys.arg…