双边滤波器(bilateral filter)

本文通过实例对比了高斯滤波与双边滤波在信号处理中的效果。高斯滤波平滑信号同时可能模糊阶跃变化,而双边滤波在去噪同时能较好保留边缘信息。

在这里插入图片描述
直接看看滤波结果吧,蓝线为原始信号,黄线为高斯滤波结果,绿线为双边滤波结果。

高斯滤波大家应该都很熟悉:
yi′=∑j=i−Hi+Hwijyj y_i' = \sum_{j=i-H}^{i+H} w_{ij} y_j yi=j=iHi+Hwijyjwij=1Zexp⁡(−∣i−j∣2/2σ2) w_{ij} = \frac{1}{Z}\exp(-|i-j|^2/2\sigma^2) wij=Z1exp(ij2/2σ2)

滤波后每个点的信号值是其周边值得加权平均,权值仅仅由时空距离决定。

这样的弊端是什么呢?在处理阶跃信号的时候,很容易将信号的突变平滑掉。表现在图像处理上就是在去噪的同时,减损边缘信息。

双边滤波为什么可以保留边缘信息呢?

原因在于双边滤波的权值不仅仅取决于下标的时空距离,还取决与信号值之间的距离:
wij=1Zexp⁡(−∣i−j∣2/2σ12)exp⁡(−∣yi−yj∣2/2σ22) w_{ij} = \frac{1}{Z}\exp(-|i-j|^2/2\sigma_1^2) \exp(-|y_i-y_j|^2/2\sigma_2^2) wij=Z1exp(ij2/2σ12)exp(yiyj2/2σ22)

如果信号发生阶跃,比如某点右端的信号值普遍大于当前值,而左端的值则普遍接近,那么滤波时该点左端的权重会大于右端的权重,因而不会使得阶跃信号被平滑。

code

import math
import numpy as np
import matplotlib.pyplot as plt

def denoise_step(sample, H=3, dn1=1., dn2=1.):
    def get_denoise_value(idx):
        start_idx, end_idx = get_neighbor_idx(len(sample), idx, H)
        idxs = np.arange(start_idx, end_idx)
        weight_sample = sample[idxs]

        weights = np.array(list(map(lambda j: bilateral_filter(j, idx, sample[j], sample[idx], dn1, dn2), idxs)))
        return np.sum(weight_sample * weights)/np.sum(weights)

    idx_list = np.arange(len(sample))
    denoise_sample = np.array(list(map(get_denoise_value, idx_list)))
    return denoise_sample

def get_neighbor_idx(total_len, target_idx, H=3):
    '''
    Let i = target_idx.
    Then, return i-H, ..., i, ..., i+H, (i+H+1)
    '''
    return [np.max([0, target_idx-H]), np.min([total_len, target_idx+H+1])]

def gen_wave():
    N = 100
    t = np.linspace(0,10,N)
    y = np.sign(np.sin(t))
    y += np.random.random((N))*0.5
    return y

ts = gen_wave()

plt.figure(figsize=(10,5))
plt.plot(ts, label='original')

def bilateral_filter(j, t, y_j, y_t, delta1=1.0, delta2=1.0):
    idx1 = -1.0 * (math.fabs(j-t) **2.0)/(2.0*delta1**2)
    idx2 = 0  												# gaussian filter
    weight = (math.exp(idx1)*math.exp(idx2))
    return weight

ts1 = denoise_step(ts, H=5, dn1=10, dn2=1)
plt.plot(ts1, label='gaussian')

def bilateral_filter(j, t, y_j, y_t, delta1=1.0, delta2=1.0):
    idx1 = -1.0 * (math.fabs(j-t) **2.0)/(2.0*delta1**2)
    idx2 = -1.0 * (math.fabs(y_j-y_t) **2.0)/(2.0*delta2**2)
    weight = (math.exp(idx1)*math.exp(idx2))
    return weight

ts1 = denoise_step(ts, H=5, dn1=10, dn2=1)
plt.plot(ts1, label='bilateral')
plt.legend()
plt.show()
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

颹蕭蕭

白嫖?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值