bilateral filter双边滤波器的通俗理解
图像去噪的方法很多,如中值滤波,高斯滤波,维纳滤波等等。但这些降噪方法容易模糊图片的边缘细节,对于高频细节的保护效果并不明显。相比较而言,bilateral filter双边滤波器可以很好的边缘保护,即可以在去噪的同时,保护图像的边缘特性。双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的(不理解这几个概念没关系,后面会慢慢解释)。
1. 双边滤波(Bilateral filter)的原理
双边滤波器之所以能够做到在平滑去噪的同时还能够很好的保存边缘(Edge Preserve),是由于其滤波器的核由两个函数生成:空间域核和值域核
- (1)空间域核:由像素位置欧式距离决定的模板权值
为模板窗口的其他系数的坐标;其中
为模板窗口的中心坐标点;
为高斯函数的标准差。 使用该公式生成的滤波器模板和高斯滤波器使用的模板是没有区别的。
在一些博客和教程里,这个权值
称为定义域核,也称为空间系数,或
空间域(spatial domain S)
。显示由的计算公式可知,它是计算临近点
到中心点
临近程度,因此定义域核
是用于衡量空间临近的程度。
- (2)值域核:由像素值的差值决定的模板权值
其中,为模板窗口的其他系数的坐标,
表示图像在点
处的像素值;
为模板窗口的中心坐标点,对应的像素值为
;
为高斯函数的标准差。
一般将权值
称为值域核,或
像素值域(range domain R)
,不管是值域核还是空间域核
,其大小都在[0 1]之间
- (3)将上述两个模板相乘就得到了双边滤波器的模板权值:
因此,双边滤波器的数据公式可以表示如下:
2. 双边滤波(Bilateral filter)理解
双边滤波(Bilateral filter)其综合了高斯滤波器(Gaussian Filter)和α-截尾均值滤波器(Alpha-Trimmed mean Filter)的特点,同时考虑了空间域与值域的差别,而Gaussian Filter和α均值滤波分别只考虑了空间域和值域差别。高斯滤波器只考虑像素间的欧式距离,其使用的模板系数随着和窗口中心的距离增大而减小;α-截尾均值滤波器则只考虑了像素灰度值之间的差值,去掉α%的最小值和最大值后再计算均值。
2.1 空域权重
和值域权重
的意义:
- 空域权重
衡量的是
两点之间的距离,距离越远权重越低;
- 值域权重
衡量的是
两点之间的像素值相似程度,越相似权重越大
这里从图像的平坦区域和边缘区域定性分析双边滤波的降噪效果
- 在平坦区域,临近像素的像素值的差值较小,对应值域权重
接近于1,此时空域权重
起主要作用,相当于直接对此区域进行高斯模糊。因此,平坦区域相当于进行高斯模糊。
- 在边缘区域,临近像素的像素值的差值较大,对应值域权重
接近于0,导致此处核函数下降(因
),当前像素受到的影响就越小,从而保持了原始图像的边缘的细节信息。
3. Opencv双边滤波函数:
opencv中提供了bilateralFilter()函数来实现双边滤波操作,其原型如下:
bilateralFilter(InputArray src, OutputArray dst, int d,double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT)
- InputArray src: 输入图像,可以是Mat类型,图像必须是8位或浮点型单通道、三通道的图像。
- OutputArray dst: 输出图像,和原图像有相同的尺寸和类型。
- int d: 表示在过滤过程中每个像素邻域的直径范围。如果这个值是非正数,则函数会从第五个参数sigmaSpace计算该值。
- double sigmaColor: 颜色空间过滤器的sigma值,这个参数的值月大,表明该像素邻域内有越宽广的颜色会被混合到一起,产生较大的半相等颜色区域。 (这个参数可以理解为值域核
的
)
- double sigmaSpace: 坐标空间中滤波器的sigma值,如果该值较大,则意味着越远的像素将相互影响,从而使更大的区域中足够相似的颜色获取相同的颜色。当d>0时,d指定了邻域大小且与sigmaSpace无关,否则d正比于sigmaSpace. (这个参数可以理解为空间域核
的
)
- int borderType=BORDER_DEFAULT: 用于推断图像外部像素的某种边界模式,有默认值BORDER_DEFAULT.
双边滤波器可以很好的保存图像边缘细节而滤除掉低频分量的噪音,但是双边滤波器的效率不是太高,花费的时间相较于其他滤波器而言也比较长。
对于简单的滤波而言,可以将两个sigma值设置成相同的值,如果值<10,则对滤波器影响很小,如果值>150则会对滤波器产生较大的影响,会使图片看起来像卡通。
示例代码:
import cv2 as cv
import numpy as np
def bi_demo(image):
dst = cv.bilateralFilter(image, 0, 100, 15)
cv.imshow("bi_demo", dst)
def shift_demo(image):
dst = cv.pyrMeanShiftFiltering(image, 10, 50)
cv.imshow("shift_demo", dst)
print("--------- Hello Python ---------")
src = cv.imread("D:/vcprojects/images/example.png")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
bi_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()
【尊重原创,转载请注明出处】:https://blog.csdn.net/guyuealian/article/details/82660826
void pyrMeanShiftFiltering( InputArray src, OutputArray dst,
double sp, double sr, int maxLevel=1,
TermCriteria termcrit=TermCriteria(
TermCriteria::MAX_ITER+TermCriteria::EPS,5,1) );
第一个参数src,输入图像,8位,三通道的彩色图像,并不要求必须是RGB格式,HSV、YUV等Opencv中的彩色图像格式均可;
第二个参数dst,输出图像,跟输入src有同样的大小和数据格式;
第三个参数sp,定义的漂移物理空间半径大小;
第四个参数sr,定义的漂移色彩空间半径大小;
第五个参数maxLevel,定义金字塔的最大层数;
第六个参数termcrit,定义的漂移迭代终止条件,可以设置为迭代次数满足终止,迭代目标与中心点偏差满足终止,或者两者的结合;
pyrMeanShiftFiltering函数的执行过程是这样的:
- 迭代空间构建:
以输入图像上src上任一点P0为圆心,建立物理空间上半径为sp,色彩空间上半径为sr的球形空间,物理空间上坐标2个—x、y,色彩空间上坐标3个—R、G、B(或HSV),构成一个5维的空间球体。
其中物理空间的范围x和y是图像的长和宽,色彩空间的范围R、G、B分别是0~255。
- 求取迭代空间的向量并移动迭代空间球体后重新计算向量,直至收敛:
在1中构建的球形空间中,求得所有点相对于中心点的色彩向量之和后,移动迭代空间的中心点到该向量的终点,并再次计算该球形空间中所有点的向量之和,如此迭代,直到在最后一个空间球体中所求得的向量和的终点就是该空间球体的中心点Pn,迭代结束。
-
更新输出图像dst上对应的初始原点P0的色彩值为本轮迭代的终点Pn的色彩值,如此完成一个点的色彩均值漂移。
-
对输入图像src上其他点,依次执行步骤1,、2、3,遍历完所有点位后,整个均值偏移色彩滤波完成,这里忽略对金字塔的讨论。