值域核的定义如公式(3)所示。
两者相乘之后,就会产生依赖于数据的双边滤波权重函数,如下所示:
从式子(4)可以看出,双边滤波器的加权系数是空间邻近度因子和像素亮度相似因子的非线性组合。前者随着像素点与中心点之间欧几里德距离的增加而减小,后者随着像素亮度之差的增大而减小[5-6]。
在图像变化平缓的区域,邻域内亮度值相差不大,双边滤波器转化为高斯低通滤波器;在图像变化剧烈的区域,邻域内像素亮度值相差较大,滤波器利用边缘点附近亮度值相近的像素点的亮度平均值替代原亮度值。因此,双边滤波器既平滑了图像,又保持了图像边缘,其原理图如图3所示。
OpenCV将中值滤波封装在bilateralFilter()函数中,其函数原型如下所示:
- dst = bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, BORDERType]])
– src表示待处理的输入图像
– dst表示输出图像,其大小和类型与输入图像相同
– d表示在过滤期间使用的每个像素邻域的直径。如果这个值我们设其为非正数,则它会由sigmaSpace计算得出
– sigmaColor表示颜色空间的标准方差。该值越大,表明像素邻域内较远的颜色会混合在一起,从而产生更大面积的半相等颜色区域
– sigmaSpace表示坐标空间的标准方差。该值越大,表明像素的颜色足够接近,从而使得越远的像素会相互影响,更大的区域中相似的颜色获取相同的颜色,当d>0,d指定了邻域大小且与sigmaSpace无关。否则,d正比于sigmaSpace
– borderType表示边框模式,用于推断图像外部像素的某种边界模式,默认值为BORDER_DEFAULT,可省略
下面是调用bilateralFilter()函数实现双边滤波的代码,其中d为15,sigmaColor设置为150,sigmaSpace设置为150。
# -*- coding: utf-8 -*-
# By:Eastmount
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取图片
img = cv2.imread('lena-zs.png')
source = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#双边滤波
result = cv2.bilateralFilter(source, 15, 150, 150)
#用来正常显示中文标签
plt.rcParams['font.sans-serif']=['SimHei']
#显示图形
titles = ['原始图像', '双边滤波']
images = [source, result]
for i in range(2):
plt.subplot(1,2,i 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
其运行结果如图4所示: