原理
双边滤波的作用主要是为了保护图像的边缘信息不被滤掉;利用高斯滤波和空间滤波相乘,计算(i,j)点位置的权重。
其中,高斯滤波函数是:
G
a
s
[
i
,
j
]
=
e
−
(
i
2
+
j
2
)
2
∗
σ
2
,
−
r
<
i
,
j
<
r
,
r
表
示
核
的
半
径
Gas[i,j]=e^{\frac{-(i^2+j^2)}{2*\sigma^2}},-r <i,j<r,r表示核的半径
Gas[i,j]=e2∗σ2−(i2+j2),−r<i,j<r,r表示核的半径
对用的空间滤波器的
S
p
a
[
i
,
j
]
=
e
−
(
I
[
i
,
j
]
−
I
[
0
,
0
]
)
2
2
∗
σ
2
,
−
r
<
i
,
j
<
r
,
r
表
示
核
的
半
径
,
I
[
i
,
j
]
表
示
(
i
,
j
)
对
应
的
像
素
值
Spa[i,j]=e^{\frac{-(I[i,j]-I[0,0])^2}{2*\sigma^2}},-r <i,j<r,r表示核的半径,I[i,j]表示(i,j)对应的像素值
Spa[i,j]=e2∗σ2−(I[i,j]−I[0,0])2,−r<i,j<r,r表示核的半径,I[i,j]表示(i,j)对应的像素值
由高斯核和空间滤波核相乘后进行归一化处理,然后逐一求各个像素点对应的输出值。
k
e
r
n
e
l
=
G
a
s
∗
S
p
a
kernel = Gas * Spa
kernel=Gas∗Spa
k
e
r
n
e
l
o
u
t
=
k
e
r
n
e
l
/
s
u
m
(
k
e
r
n
e
l
)
kernelout = kernel/sum(kernel)
kernelout=kernel/sum(kernel)
代码
# -*- coding: utf-8 -*-
"""
Created on Sat Jun 27 18:21:39 2020
@author: PRCZ
"""
import numpy as np
import random
from skimage import io
import cv2
from matplotlib import pyplot as plt
#path = "D:/2_project/0_test/1.jpg"
path1 = 'D:/2_project/0_test/median_filter/anr/input/inputdc4.jpg'
I = io.imread(path1) #R*0.299+G*0.587+B*0.114
I1 = cv2.imread(path1, cv2.IMREAD_GRAYSCALE)
image = I1
def sp_noise(image,prob):
output = np.zeros(image.shape,np.uint8)
thres = (1 - prob)*255
for i in range(image.shape[0]):
for j in range(image.shape[1]):
rdn = random.randint(0,255)
if rdn < prob*255:
output[i][j] = 0
elif rdn > 230:
output[i][j] = 200
else:
output[i][j] = image[i][j]
return output
def gaus_kernel(winsize, gsigma):
r = int(winsize/2)
c = r
kernel = np.zeros((winsize, winsize))
sigma1 = 2*gsigma*gsigma
for i in range(-r, r+1):
for j in range(-c, c+1):
kernel[i+r][j+c] = np.exp(-float(float((i*i+j*j))/sigma1))
return kernel
def bilateral_filter(image, gsigma, ssigma, winsize):
r = int(winsize/2)
c = r
image1 = np.pad(image, ((r, c),(r, c)), constant_values=0)
#image1 = sp_noise(image1, prob=0.01)
image = image1
row, col = image.shape
sigma2 = 2*ssigma*ssigma
gkernel = gaus_kernel(winsize, gsigma)
kernel = np.zeros((winsize, winsize))
bilater_image = np.zeros((row, col))
for i in range(1,row-r):
for j in range(1,col-c):
skernel = np.zeros((winsize, winsize))
#print(i, j)
for m in range(-r, r+1):
for n in range(-c, c+1):
#print(m, n)
#if (i != 0 and j !=0 and i != r and j !=c):
skernel[m+r][n+c] = np.exp(-pow((image[i][j]-image[i+m][j+n]),2)/sigma2)
# else:
#skernel[m+r][n+c] = np.exp(-pow((image[i][j]),2)/sigma2)
#print(skernel[m+r][n+c])
kernel[m+r][n+c] = skernel[m+r][n+r] * gkernel[m+r][n+r]
sum_kernel = sum(sum(kernel))
kernel = kernel/sum_kernel
for m in range(-r, r+1):
for n in range(-c, c+1):
bilater_image[i][j] = image[i+m][j+n] * kernel[m+r][n+c] + bilater_image[i][j]
return bilater_image
bilater_image = bilateral_filter(image, 10, 3, 15)
err = bilater_image - np.pad(image, ((7, 7),(7, 7)), constant_values=0)
#image1 = sp_noise(image, prob=0.01)
bilater_image1 = cv2.bilateralFilter(image, d=0, sigmaColor=10, sigmaSpace=3)
err1 = bilater_image1 - image
plt.figure()
plt.subplot(231)
plt.imshow(image)
#plt.figure()
plt.subplot(232)
plt.imshow(bilater_image)
plt.subplot(233)
plt.imshow(bilater_image1)
plt.subplot(235)
plt.imshow(bilater_image - np.pad(image, ((7, 7),(7, 7)), constant_values=0))
plt.subplot(236)
plt.imshow(err1)
path2 = 'D:/2_project/0_test/median_filter/bilater/'
io.imsave('D:/2_project/0_test/median_filter/bilater/bilater_img.jpg', bilater_image)
io.imsave('D:/2_project/0_test/median_filter/bilater/bilater_img1.jpg', bilater_image1)