中值平滑
种植平滑,类似于卷积,也是一种邻域运算,但计算的不是加权求和,而是对邻域中像素点按灰度值进行排序,然后选择该组中的中值作为输出的灰度值。
中值滤波最重要的能力是去除椒盐噪声。
椒盐噪声是指图像在传输系统中由于解码误差等原因,导致图像中出现孤立的白点或黑点。
import numpy as np
import random
def salt(image,number):
"""
模拟添加椒盐噪声
"""
# 图像的高、宽
rows,cols = image.shape
# 加入椒盐噪声后的图像
salt_image = np.copy(image)
for i in range(number):
rand_r = random.randint(0,rows-1)
rand_c = random.randint(0,cols-1)
salt_image[rand_r][rand_c] = 255
return salt_image
def median_blur(image,win_size):
rows,cols = image.shape
win_h,win_w = win_size
half_win_h = (win_h-1)/2
half_win_w = (win_w-1)/2
median_blur_image = np.zeros(image.shape,image.dtype)
for r in range(rows):
for c in range(cols):
# 判断边界
rTop = 0 if r-half_win_h<0 else r-half_win_h
rBottom = rows-1 ifr+half_win_h>rows-1 else r+half_win_h
cLeft = 0 if c-half_win_w<0 else c-half_win_w
cRight = cols-1 if c+half_win_w>cols-1 else c+half_win_w
# 取邻域
region = image[rTop:rBottom+1,cLeft:cRight+1]
# 求中值
median_blur_image[r][c] = np.median(region)
return median_blur_image
双边滤波
均值平滑和高斯平滑本质上都是计算每个位置的邻域加权和作为该位置的输出。
双边滤波是根据每个位置的邻域,对该位置构建不同的权重模板,构建过程如下:
第一步:构建winH×winW的空间距离权重模板。
c l o s e n e s s W e i g h t ( h , w ) = e x p ( − ( h − w i n H − 1 2 ) 2 + ( w − w i n W − 1 2 ) 2 2 σ 1 2 ) closenessWeight(h,w) = exp(-\frac{(h-\frac{winH-1}{2})^2+(w-\frac{winW-1}{2})^2}{2\sigma_{1}^{2}}) closenessWeight(h,w)=exp(−2σ12(h−2winH−1)2+(w−2winW−1)2)
第二步:构建winH×winW的相似性权重模板,是通过(r,c)处的值与其邻域值的差值的指数衡量的。
s
i
m
i
l
a
r
i
t
y
W
e
i
g
h
t
(
h
,
w
)
=
e
x
p
(
−
∣
∣
I
(
r
,
c
)
−
I
(
r
+
(
h
−
w
i
n
H
−
1
2
)
,
c
+
(
w
−
w
i
n
W
−
1
2
)
∣
∣
2
2
σ
2
2
)
similarityWeight(h,w) = exp(-\frac{||I(r,c)-I(r+(h-\frac{winH-1}{2}),c+(w-\frac{winW-1}{2})||^2}{2\sigma_{2}^{2}})
similarityWeight(h,w)=exp(−2σ22∣∣I(r,c)−I(r+(h−2winH−1),c+(w−2winW−1)∣∣2)
第三步:将
c
l
o
s
e
n
e
s
s
W
e
i
g
h
t
closenessWeight
closenessWeight和
s
i
m
i
l
a
r
i
t
y
W
e
i
g
h
t
similarityWeight
similarityWeight 的对应位置相乘(即点乘)
第四步:归一化,得到该位置权重模板
第五步:将得到的权重模板和该位置邻域的对应位置相乘,然后求和得到该位置的输出值。
import numpy as np
import cv2 as cv
import math
def get_closenessWeight(sigma_g,H,W):
"""
构建空间距离权重模板
"""
r,c = np.mgrid[0:H:1,0:W:1]
r-=(h-1)/2
c-=(w-1)/2
closenessWeight = np.exp(-0.5*(np.power(r,2)+np.power(c,2)/math.pow(sigma_g,2)))
return closenessWeight
def bfltGray(I,H,W,sigma_g,sigma_d):
"""
sigma_g: 代表空间距离权重模板的标准差
sigma_d:代表相似性权重模板的标准差
令sigma_g>1,sigma_d<1效果会比较好
"""
# 构建空间距离模板
closenessWeight = get_closenessWeight(sigma_g,H,W)
# 模板的中心位置
cH = (H-1)/2
cW = (W-1)/2
# 图像矩阵的行数和列数
rows,cols = I.shape
# 双边滤波后的结果
bfltGrayImage = np.zeros(I.shape,np.float32)
for r in range(rows):
for c in range(cols):
piexl = T[r][c]
# 判断边界
rTop = 0 if r-cH<0 else r-cH
rBottom = rows-1 if r+cH >rows-1 else r+cH
cLeft = 0 if c-cW<0 else c-cW
cRight = cols-1 if c+cW>cols-1 else c+cW
# 权重模板作用的区域
region = I[rTop:rBottom+1,cLeft:cRight+1]
# 构建灰度值相似性的权重因子
similarityWeightTemp = np.exp(-0.5*np.power(region-piexl,2.0)/math.pow(sigma_d,2))
closenessWeightTemp = closenessWeight[rTop-r+cH:rBottom-r+cH+1,cLeft-c+cW:cRight-c+cW+1]
# 权重模板相乘
weightTemp = similarityWeightTemp*closenessWeightTemp
# 归一化权重模板
weightTemp = weightTemp/np.sum(weightTemp)
# 权重模板和对应的邻域值相乘求和
bfltGrayImage[r][c] = np.sum(region*weightTemp)
return bfltGrayImage
联合双边滤波
联合双边滤波与双边滤波类似,在双边滤波的基础上做了些改动,两者的区别在于双边滤波是在原灰度图的基础上构建的相似性权重模板,而联合双边滤波是在原灰度图经过高斯平滑后的图像的基础上构建的相似性权重模板,其他都是相同的。
注意:最终的权重模板是与原图(不是高斯平滑后的结果)在该位置的邻域对应位置积的和作为输出值。
import numpy as np
import cv2 as cv
import math
def get_closenessWeight(sigma_g,H,W):
"""
构建空间距离权重模板
"""
r,c = np.mgrid[0:H:1,0:W:1]
r-=(h-1)/2
c-=(w-1)/2
closenessWeight = np.exp(-0.5*(np.power(r,2)+np.power(c,2)/math.pow(sigma_g,2)))
return closenessWeight
def jointBLF(I,H,W,sigma_g,sigma_d,borderType=cv.BORDER_DEFAULT):
"""
sigma_g: 代表空间距离权重模板的标准差
sigma_d:代表相似性权重模板的标准差
令sigma_g>1,sigma_d<1效果会比较好
"""
# 构建空间距离模板
closenessWeight = get_closenessWeight(sigma_g,H,W)
# 对I进行高斯平滑
Ig = cv.GaussianBlur(I,(W,H),sigma_g)
# 模板的中心位置
cH = (H-1)/2
cW = (W-1)/2
# 对原图和高斯平滑后的结果扩充边界
Ip = cv.copyMakeBorder(I,cH,cH,cW,cW,borderType)
Igp = cv.copyMakeBorder(Ig,cH,cH,cW,cW,borderType)
# 图像矩阵的行数和列数
rows,cols = I.shape
i,j =0,0
# 联合双边滤波后的结果
jblf = np.zeros(I.shape,np.float64)
for r in range(cH,cH+rows,1):
for c in range(cW,cW+cols,1):
piexl = T[r][c]
# 当前位置的邻域
rTop,rBottom = r-cH,r+cH
cLeft,cRight = c-cW,c+cW
# 权重模板作用的区域
region = Igp[rTop:rBottom+1,cLeft:cRight+1]
# 构建灰度值相似性的权重因子
similarityWeightTemp = np.exp(-0.5*np.power(region-piexl,2.0)/math.pow(sigma_d,2))
# 权重模板相乘
weightTemp = similarityWeightTemp*closenessWeight
# 归一化权重模板
weightTemp = weightTemp/np.sum(weightTemp)
# 权重模板和对应的邻域值相乘求和
jblf[r][c] = np.sum(Ip[rTop:rBottom+1,cLeft:cRight+1]*weightTemp)
j+=1
j=0
i+=1
return jblf
注:文中所书内容来自张平的《opencv算法精解》,作为自己所学的输出,如若撰写过程中出现错误欢迎指出。