【OpenCV 完整例程】88. 频率域拉普拉斯高通滤波
4.3 频率域拉普拉斯高通滤波
拉普拉斯算子(Laplace)是导数算子,会突出图像中的急剧灰度变化,抑制灰度缓慢变化区域,往往会产生暗色背景下的灰色边缘和不连续图像。将拉普拉斯图像与原图叠加,可以得到保留锐化效果的图像。
拉普拉斯算子(Laplace)是最简单的各向同性导数算子(卷积核):
∇
2
f
=
∂
2
f
∂
x
2
+
∂
2
f
∂
y
2
∂
2
f
∂
x
2
=
f
(
x
+
1
,
y
)
−
2
f
(
x
,
y
)
+
f
(
x
−
1
,
y
)
∂
2
f
∂
y
2
=
f
(
x
,
y
+
1
)
−
2
f
(
x
,
y
)
+
f
(
x
,
y
−
1
)
∇
2
f
(
x
,
y
)
=
f
(
x
+
1
,
y
)
+
f
(
x
−
1
,
y
)
+
f
(
x
,
y
+
1
)
+
f
(
x
,
y
−
1
)
−
4
f
(
x
,
y
)
\begin{aligned} \nabla ^2 f &= \dfrac{\partial ^2 f}{\partial x ^2} + \dfrac{\partial ^2 f}{\partial y ^2} \\ \dfrac{\partial ^2 f}{\partial x ^2} &= f(x+1,y) - 2f(x,y) + f(x-1,y) \\ \dfrac{\partial ^2 f}{\partial y ^2} &= f(x,y+1) - 2f(x,y) + f(x,y-1) \\ \nabla ^2 f(x,y) &= f(x+1,y) + f(x-1,y) + f(x,y+1) + f(x,y-1) - 4f(x,y) \end{aligned}
∇2f∂x2∂2f∂y2∂2f∇2f(x,y)=∂x2∂2f+∂y2∂2f=f(x+1,y)−2f(x,y)+f(x−1,y)=f(x,y+1)−2f(x,y)+f(x,y−1)=f(x+1,y)+f(x−1,y)+f(x,y+1)+f(x,y−1)−4f(x,y)
于是可以得到空间域拉普拉斯核 K1,考虑对角项后可以得到拉普拉斯核 K2。
K 1 = [ 0 1 0 1 − 4 1 0 1 0 ] , K 2 = [ 1 1 1 1 − 8 1 1 1 1 ] , K 3 = [ 0 − 1 0 − 1 4 − 1 0 − 1 0 ] , K 4 = [ − 1 − 1 − 1 − 1 8 − 1 − 1 − 1 − 1 ] K1= \begin{bmatrix} 0 & 1 &0\\ 1 & -4 &1\\ 0 & 1 &0\\ \end{bmatrix}, \ K2= \begin{bmatrix} 1 & 1 &1\\ 1 & -8 &1\\ 1 & 1 &1\\ \end{bmatrix}, \ K3= \begin{bmatrix} 0 & -1 &0\\ -1 & 4 &-1\\ 0 & -1 &0\\ \end{bmatrix}, \ K4= \begin{bmatrix} -1 & -1 &-1\\ -1 & 8 &-1\\ -1 & -1 &-1\\ \end{bmatrix} K1=⎣⎡0101−41010⎦⎤, K2=⎣⎡1111−81111⎦⎤, K3=⎣⎡0−10−14−10−10⎦⎤, K4=⎣⎡−1−1−1−18−1−1−1−1⎦⎤
在频率域中拉普拉斯算子可以用传递函数描述:
H
(
u
,
v
)
=
−
4
π
2
(
u
2
+
v
2
)
H(u,v) = - 4 \pi ^2 (u^2 + v^2)
H(u,v)=−4π2(u2+v2)
采用 D(u,v) 表示到频率中心的距离函数,可以进一步表示为:
H
(
u
,
v
)
=
−
4
π
2
[
(
u
−
P
/
2
)
2
+
(
v
−
Q
/
2
)
2
]
=
−
4
π
2
D
2
(
u
,
v
)
H(u,v) = - 4 \pi ^2 [(u-P/2)^2 + (v-Q/2)^2] = - 4 \pi ^2 D^2(u,v)
H(u,v)=−4π2[(u−P/2)2+(v−Q/2)2]=−4π2D2(u,v)
于是,
∇ 2 f ( x , y ) = J − 1 { H ( u , v ) F ( u , v ) } g ( x , y ) = f ( x , y ) + c ∇ 2 f ( x , y ) = J − 1 { [ 1 + 4 π 2 D 2 ( u , v ) ] F ( u , v ) } \nabla ^2 f(x,y) = J^{-1} \{H(u,v) F(u,v)\}\\ g(x,y)= f(x,y) + c \nabla ^2 f(x,y) \\ = J^{-1} \{[1+4 \pi ^2 D^2(u,v)] F(u,v)\} ∇2f(x,y)=J−1{H(u,v)F(u,v)}g(x,y)=f(x,y)+c∇2f(x,y)=J−1{[1+4π2D2(u,v)]F(u,v)}
例程 8.27:频率域图像锐化(拉普拉斯算子)
# OpenCVdemo08.py
# Demo08 of OpenCV
# 8. 图像的频率域滤波
# Copyright 2021 Youcans, XUPT
# Crated:2021-12-30
# 8.27:频率域图像锐化(拉普拉斯算子)
def LaplacianFilter(shape): # 频域 Laplacian 滤波器
u, v = np.mgrid[-1:1:2.0/shape[0], -1:1:2.0/shape[1]]
D = np.sqrt(u**2 + v**2)
kernel = -4 * np.pi**2 * D**2
return kernel
def imgHPfilter(image, lpTyper="Laplacian"): # 频域高通滤波
# (1) 中心化, centralized 2d array f(x,y) * (-1)^(x+y)
mask = np.ones(image.shape)
mask[1::2, ::2] = -1
mask[::2, 1::2] = -1
fImage = image * mask # f(x,y) * (-1)^(x+y)
# (2) 最优 DFT 扩充尺寸, 快速傅里叶变换的尺寸扩充
rows, cols = image.shape[:2] # 原始图片的高度和宽度
rPadded = cv2.getOptimalDFTSize(rows) # 最优 DFT 扩充尺寸
cPadded = cv2.getOptimalDFTSize(cols) # 用于快速傅里叶变换
# (3) 边缘扩充(补0), 快速傅里叶变换
dftImage = np.zeros((rPadded, cPadded, 2), np.float32) # 对原始图像进行边缘扩充
dftImage[:rows, :cols, 0] = fImage # 边缘扩充,下侧和右侧补0
cv2.dft(dftImage, dftImage, cv2.DFT_COMPLEX_OUTPUT) # 快速傅里叶变换 (rPad, cPad, 2)
# (4) 构建 频域滤波器传递函数: 以 Laplacian 为例
LapFilter = LaplacianFilter((rPadded, cPadded)) # 拉普拉斯滤波器
# (5) 在频率域修改傅里叶变换: 傅里叶变换 点乘 滤波器传递函数
dftFilter = np.zeros(dftImage.shape, dftImage.dtype) # 快速傅里叶变换的尺寸(优化尺寸)
for j in range(2):
dftFilter[:rPadded, :cPadded, j] = dftImage[:rPadded, :cPadded, j] * LapFilter
# (6) 对高通傅里叶变换 执行傅里叶逆变换,并只取实部
idft = np.zeros(dftImage.shape[:2], np.float32) # 快速傅里叶变换的尺寸(优化尺寸)
cv2.dft(dftFilter, idft, cv2.DFT_REAL_OUTPUT + cv2.DFT_INVERSE + cv2.DFT_SCALE)
# (7) 中心化, centralized 2d array g(x,y) * (-1)^(x+y)
mask2 = np.ones(dftImage.shape[:2])
mask2[1::2, ::2] = -1
mask2[::2, 1::2] = -1
idftCen = idft * mask2 # g(x,y) * (-1)^(x+y)
# (8) 截取左上角,大小和输入图像相等
result = np.clip(idftCen, 0, 255) # 截断函数,将数值限制在 [0,255]
imgFilter = result.astype(np.uint8)
imgFilter = imgFilter[:rows, :cols]
return imgFilter
# (1) 读取原始图像
img = cv2.imread("../images/Fig0338a.tif", flags=0) # NASA 月球影像图
rows, cols = img.shape[:2] # 图片的高度和宽度
print(rows, cols)
# (2) 空间域 拉普拉斯算子 (Laplacian)
# 使用函数 filter2D 实现 Laplace 卷积算子
kernLaplace = np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]]) # Laplacian kernel
imgLaplace1 = cv2.filter2D(img, -1, kernLaplace, borderType=cv2.BORDER_REFLECT)
# 使用 cv2.Laplacian 实现 Laplace 卷积算子
imgLaplace2 = cv2.Laplacian(img, -1, ksize=3)
imgLapReSpace = cv2.add(img, imgLaplace2) # 恢复原图像
# (3) 频率域 拉普拉斯算子 (Laplacian)
imgLaplace = imgHPfilter(img, "Laplacian") # 调用自定义函数 imgHPfilter()
imgLapRe = cv2.add(img, imgLaplace) # 恢复原图像
plt.figure(figsize=(10, 6))
plt.subplot(131), plt.imshow(img, 'gray'), plt.title("Origin from NASA"), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(imgLapReSpace, 'gray'), plt.title("Spatial Lapalacian"), plt.xticks([]), plt.yticks([])
plt.subplot(133), plt.imshow(imgLapRe, 'gray'), plt.title("Freauency Lapalacian"), plt.xticks([]), plt.yticks([])
plt.tight_layout()
plt.show()
(本节完)
版权声明:
youcans@xupt 原创作品,转载必须标注原文链接
Copyright 2021 youcans, XUPT
Crated:2022-2-1