文章目录
- 前言
- 一、双边滤波
- 二、图像增噪
- 三、Python双边滤波
- 总结
前言
不知不觉来到了最后一个滤波算法,也是最难懂的滤波算法。要相信,坚持不一定明白原理,但不坚持肯定一脸懵。
一、双边滤波
双边滤波是一种非线性滤波器,它既可以达到降噪平滑,同时又保持边缘的效果。和其他滤波原理一样,双边滤波采用的是加权平均的方法,用周边的像素亮度值的加全平均来代表某个像素的强度,所用的加权平均也是基于高斯分布。为什么我解释怎么多,因为下面两个公式会劝退很多人。
B
F
[
I
]
p
=
1
W
p
∑
q
∈
S
G
σ
s
(
∣
∣
p
−
q
∣
∣
)
G
σ
r
(
∣
I
p
−
I
q
∣
)
BF[I]_p = \frac{1}{W_p}\sum_{q \in S}G_{\sigma_s}(||p - q||)G_{\sigma_r}(|I_p - I_q|)
BF[I]p=Wp1q∈S∑Gσs(∣∣p−q∣∣)Gσr(∣Ip−Iq∣)
I
p
n
e
w
=
1
W
p
∑
p
∈
S
[
G
σ
s
(
∣
∣
p
−
q
∣
∣
G
σ
r
)
(
∣
I
p
−
I
q
∣
I
p
)
]
=
1
W
p
∑
p
∈
S
[
e
x
2
+
y
2
2
σ
s
2
e
−
(
I
p
−
I
q
)
2
2
σ
r
2
I
p
]
=
1
W
p
∑
p
∈
S
[
G
(
x
,
y
)
e
−
(
I
p
−
I
q
)
2
2
σ
r
2
I
p
]
I_p^{new} = \frac{1}{W_p}\sum_{p \in S}[G_{\sigma_s}(||p - q||G_{\sigma_r})(|I_p - I_q|I_p)] = \frac{1}{W_p}\sum_{p\in S}[e^{\frac{x^2 + y ^2}{2\sigma_s^2}} e^{-\frac{(I_p - I_q)^2}{2\sigma_r^2}}I_p] = \frac{1}{W_p}\sum_{p\in S}[G(x, y)e^{-\frac{(I_p - I_q)^2}{2\sigma_r^2}}I_p]
Ipnew=Wp1p∈S∑[Gσs(∣∣p−q∣∣Gσr)(∣Ip−Iq∣Ip)]=Wp1p∈S∑[e2σs2x2+y2e−2σr2(Ip−Iq)2Ip]=Wp1p∈S∑[G(x,y)e−2σr2(Ip−Iq)2Ip]
公式中,
G
σ
s
G_{\sigma_s}
Gσs是当前像素空间距离的权重;
G
σ
r
G_{\sigma_r}
Gσr考虑的是当前相似度的权重。
G
σ
s
×
G
σ
r
G_{\sigma_s} \times G_{\sigma_r}
Gσs×Gσr两者乘起来就是两者都考虑。
其实你只需知道以下公式,就不影响你编程了。公式如下。
G
σ
s
=
e
x
2
+
y
2
2
σ
s
2
G_{\sigma_s}=e^{\frac{x^2 + y^2}{2\sigma_s^2}}
Gσs=e2σs2x2+y2
G
σ
r
=
e
−
(
I
p
−
I
q
)
2
2
σ
r
2
G_{\sigma_r}=e^{-\frac{(I_p - I_q)^2}{2\sigma_r^2}}
Gσr=e−2σr2(Ip−Iq)2
二、图像增噪
import numpy as np
import matplotlib.pyplot as plt
img = plt.imread("lenna.png")
gray = 0.299 * img[:, :, 0] + 0.587 * img[:, :, 1] + 0.114 * img[:, :, 2]
gray = gray * 255#图像是[0-1]--->[0-255]
prob = 0.92#生成盐噪生的概率为1-0.92=0.08
noise = np.random.choice((0, 255), size=gray.shape, p=[prob, 1 - prob])#产生和图像维度一样的噪音矩阵
noise_img = np.where(noise == 0, gray, 255).astype(np.uint8)#生成噪音图像,椒(0黑色)盐噪声的盐(255白色)
fig = plt.figure(figsize=(10, 6))
ax = plt.subplot(1, 2, 1)
ax.set_title("raw image")
ax.set_xlabel("width")
ax.set_ylabel("height")
plt.imshow(gray, cmap="gray")
ax = plt.subplot(1, 2, 2)
ax.set_title("salt image")
ax.set_xlabel("width")
ax.set_ylabel("height")
plt.imshow(noise_img, cmap="gray")
三、Python双边滤波
ef gauss_template(kernel_size=3, sigma_d=3):
k = kernel_size // 2
if sigma_d == 0:
sigma_d = ((kernel_size - 1) * 0.5 - 1) * 0.3 + 0.8
x = np.linspace(-k, k, kernel_size)
y = np.linspace(-k, k, kernel_size)
x, y = np.meshgrid(x, y)
z = np.exp(-(x ** 2 + y ** 2) / (2 * sigma_d ** 2))#根据Gsimga_s
return z
def bilateral_filter(image, n, sigma_r):
h, w = image.shape
filtered_image = np.zeros((h, w))
m = int((n - 1) / 2)
for i in range(m, h - m):
for j in range(m, w - m):
A = image[i - m: i + m + 1, j - m: j + m + 1]
H = np.exp(-((A - image[i, j]) / 255) ** 2 / (2 * sigma_r ** 2))#根据Gsigma_r
F = g3 * H#两者相乘
F2 = F / np.sum(F)#归一化
filtered_image[i, j] = np.sum(F2 * A)#乘以周围像素
return filtered_image.astype(np.uint8)
g1 = gauss_template(kernel_size=3)#高斯模板
#归一化高斯
temp = np.sum(g1)
g2 = g1 / temp
#高斯模板 * 1024定点化
g3 = np.floor(g2 * 1024)
bilateral_image = bilateral_filter(noise_img, 3, 0.1)
fig = plt.figure(figsize=(10, 6))
ax = plt.subplot(1, 2, 1)
ax.set_title("salt image")
ax.set_xlabel("width")
ax.set_ylabel("height")
plt.imshow(noise_img, cmap="gray")
ax = plt.subplot(1, 2, 2)
ax.set_title("bilateral image")
ax.set_xlabel("width")
ax.set_ylabel("height")
plt.imshow(bilateral_image, cmap="gray")
总结
滤波算法到此处就只有see you啦,虽然双边滤波是一个很难的结束,但是意味着下一个简单的开始。人生不就是一样吗?结束一段黑暗,开始一段光明,循环往复,坚强自己。