第4章 Python 数字图像处理(DIP) - 频率域滤波9 - 频率域滤波基础、频率域的滤波过程、低通、高通

目录

    • 频率域滤波基础
      • 频率域的其他特性
      • 频率域滤波基础知识
      • 频率域滤波步骤小结
      • 空间域和频率域滤波之间的对应关系

频率域滤波基础

频率域的其他特性

  • 频率域中的滤波过程如下:
    • 首先修改傅里叶变换以在到特定目的
    • 然后计算IDFT,返回到空间域
# 频率域中的其他特性
img = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH04/Fig0429(a)(blown_ic).tif', -1)# FFT
img_fft = np.fft.fft2(img.astype(np.float32))# 非中心化的频谱
spectrum = spectrum_fft(img_fft)
spectrum = np.uint8(normalize(spectrum) * 255)# 中心化
fshift = np.fft.fftshift(img_fft)            # 将变换的频率图像四角移动到中心# 中心化后的频谱
spectrum_fshift = spectrum_fft(fshift)
spectrum_fshift_n = np.uint8(normalize(spectrum_fshift) * 255)# 对频谱做对数变换
spectrum_log = np.log(1 + spectrum_fshift)plt.figure(figsize=(15, 8))
plt.subplot(1, 2, 1), plt.imshow(img, cmap='gray'), plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(1, 2, 2), plt.imshow(spectrum_log, cmap='gray'), plt.title('FFT Shift log'), plt.xticks([]), plt.yticks([])
plt.tight_layout()
plt.show()

在这里插入图片描述

频率域滤波基础知识

已知大小为P×QP \times QP×Q像素的一幅数字图像f(x,y)f(x, y)f(x,y),则我们感兴趣取的基本滤波公式是:
g(x,y)=Real{J−1[H(u,v)F(u,v)]}(4.104)g(x, y) = Real\{ \mathfrak{J}^{-1}[H(u, v) F(u, v)] \} \tag{4.104}g(x,y)=Real{J1[H(u,v)F(u,v)]}(4.104)

J−1\mathfrak{J}^{-1}J1是IDFT,H(u,v)H(u, v)H(u,v)是滤波器传递函数(经常称为滤波器或滤波器函数),F(u,v)F(u, v)F(u,v)是输入图像f(x,y)f(x, y)f(x,y)的DFT,g(x,y)g(x, y)g(x,y)是滤波后的图像。

中以化:用(−1)x+y(-1)^{x + y}(1)x+y乘以输入图像来完成的

  • 低通滤波器

    • 会衰减高频而通过低频的函数,会模糊图像
  • 高通滤波器

    • 将使图像的细节更清晰,但会降低图像的对比度
def centralized_2d_loop(arr):"""centralized 2d array $f(x, y) (-1)^{x + y}$"""    #==================中心化=============================height, width = arr.shape[:2]dst = np.zeros([height, width])for h in range(height):for w in range(width):dst[h, w] = arr[h, w] * ((-1) ** (h + w))return dst
def centralized_2d_index(arr):"""centralized 2d array $f(x, y) (-1)^{x + y}$, about 35 times faster than loop"""def get_1_minus1(img):"""get 1 when image index is even, -1 while index is odd, same shape as input image, need this array to multiply with input imageto get centralized image for DFTParameter: img: input, here we only need img shape to create the arrayreturn such a [[1, -1, 1], [-1, 1, -1]] array, example is 3x3"""M, N = img.shapem, n = img.shape# 这里判断一个m, n是否是偶数,如果是偶数的话,结果不正确,需要变换为奇数if m % 2 == 0 :m += 1if n % 2 ==0 :n += 1temp = np.arange(m * n).reshape(m, n)dst = np.piecewise(temp, [temp % 2 == 0, temp % 2 == 1], [1, -1])dst = dst[:M, :N]return dst#==================中心化=============================mask = get_1_minus1(arr)dst = arr * maskreturn dst
def centralized_2d(arr):"""centralized 2d array $f(x, y) (-1)^{x + y}$, about 4.5 times faster than index, 160 times faster than loop,"""def get_1_minus1(img):"""get 1 when image index is even, -1 while index is odd, same shape as input image, need this array to multiply with input imageto get centralized image for DFTParameter: img: input, here we only need img shape to create the arrayreturn such a [[1, -1, 1], [-1, 1, -1]] array, example is 3x3"""dst = np.ones(img.shape)dst[1::2, ::2] = -1dst[::2, 1::2] = -1return dst#==================中心化=============================mask = get_1_minus1(arr)dst = arr * maskreturn dst
a = np.arange(25).reshape(5, 5)
a
array([[ 0,  1,  2,  3,  4],[ 5,  6,  7,  8,  9],[10, 11, 12, 13, 14],[15, 16, 17, 18, 19],[20, 21, 22, 23, 24]])
centralized_2d(a)
array([[  0.,  -1.,   2.,  -3.,   4.],[ -5.,   6.,  -7.,   8.,  -9.],[ 10., -11.,  12., -13.,  14.],[-15.,  16., -17.,  18., -19.],[ 20., -21.,  22., -23.,  24.]])
def idea_high_pass_filter(source, radius=5):M, N = source.shape[1], source.shape[0]u = np.arange(M)v = np.arange(N)u, v = np.meshgrid(u, v)D = np.sqrt((u - M//2)**2 + (v - N//2)**2)D0 = radiuskernel = D.copy()kernel[D > D0] = 1kernel[D <= D0] = 0kernel_normal = (kernel - kernel.min()) / (kernel.max() - kernel.min())return kernel_normal
# 频率域滤波基础知识
img = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH04/Fig0429(a)(blown_ic).tif', -1)# FFT
img_fft = np.fft.fft2(img.astype(np.float32))# 中心化
fshift = np.fft.fftshift(img_fft)            # 将变换的频率图像四角移动到中心# 滤波器
h = idea_high_pass_filter(img, radius=1)# 滤波
res = fshift * h# 先反中以化,再反变换
f1shift = np.fft.ifftshift(res)
ifft = np.fft.ifft2(f1shift)# 取实数部分
recon = np.real(ifft)
# 小于0都被置为0
# recon = np.where(recon > 0, recon, 0)
recon = np.clip(recon, 0, recon.max())
recon = np.uint8(normalize(recon) * 255)plt.figure(figsize=(15, 8))
plt.subplot(1, 2, 1), plt.imshow(img, cmap='gray'), plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(1, 2, 2), plt.imshow(recon, cmap='gray'), plt.title('FFT Shift log'), plt.xticks([]), plt.yticks([])
plt.tight_layout()
plt.show()

在这里插入图片描述

def gauss_high_pass_filter(source, center, radius=5):"""create gaussian high pass filter param: source: input, source imageparam: center: input, the center of the filter, where is the lowest value, (0, 0) is top left corner, source.shape[:2] is center of the source imageparam: radius: input, the radius of the lowest value, greater value, bigger blocker out range, if the radius is 0, then allvalue is 1return a [0, 1] value filter"""M, N = source.shape[1], source.shape[0]u = np.arange(M)v = np.arange(N)u, v = np.meshgrid(u, v)D = np.sqrt((u - center[1]//2)**2 + (v - center[0]//2)**2)D0 = radiusif D0 == 0:kernel = np.ones(source.shape[:2], dtype=np.float)else:kernel = 1 - np.exp(- (D**2)/(D0**2))   kernel = (kernel - kernel.min()) / (kernel.max() - kernel.min())return kernel
def plot_3d(ax, x, y, z):ax.plot_surface(x, y, z, antialiased=True, shade=True)ax.view_init(30, 60), ax.grid(b=False), ax.set_xticks([]), ax.set_yticks([]), ax.set_zticks([])def imshow_img(img, ax, cmap='gray'):ax.imshow(img, cmap=cmap), ax.set_xticks([]), ax.set_yticks([])
def frequency_filter(fshift, h):"""Frequency domain filtering using FFTparam: fshift: input, FFT shift to centerparam: h: input, filter, value range [0, 1]return a uint8 [0, 255] reconstruct image"""# 滤波res = fshift * h# 先反中以化,再反变换f1shift = np.fft.ifftshift(res)ifft = np.fft.ifft2(f1shift)# 取实数部分recon = np.real(ifft)# 小于0都被置为0# recon = np.where(recon > 0, recon, 0)recon = np.clip(recon, 0, recon.max())recon = np.uint8(normalize(recon) * 255)return recon
# 高斯核滤波器与对应的结果
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from matplotlib import pyplot as plt
from matplotlib import cm# 显示多个3D高斯核函数
k = 3
sigma = 0.8
X = np.linspace(-k, k, 200)
Y = np.linspace(-k, k, 200)
x, y = np.meshgrid(X, Y)
z = np.exp(- ((x)**2 + (y)**2)/ (2 * sigma**2))fig = plt.figure(figsize=(15, 10))
ax_1 = fig.add_subplot(2, 3, 1, projection='3d')
plot_3d(ax_1, x, y, z)ax_2 = fig.add_subplot(2, 3, 2, projection='3d')
plot_3d(ax_2, x, y, 1 - z)# 这里只显示不明显,
a = 1
x = a + x
y = a + y
ax_3 = fig.add_subplot(2, 3, 3, projection='3d')
plot_3d(ax_3, x, y, 1 - z)img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH04/Fig0431(d)(blown_ic_crop).tif', -1)# FFT
img_fft = np.fft.fft2(img_ori.astype(np.float32))# 中心化
fshift = np.fft.fftshift(img_fft)            # 将变换的频率图像四角移动到中心# 滤波器
radius = 20
center = img_ori.shape[:2]
h_high_1 = gauss_high_pass_filter(img_ori, center, radius=radius)
h_low = 1 - h_high_1
center = (1026, 872)
h_high_2 = gauss_high_pass_filter(img_ori, center, radius=radius)img_low = frequency_filter(fshift, h_low)
img_high_1 = frequency_filter(fshift, h_high_1)
img_high_2 = frequency_filter(fshift, h_high_2)ax_4 = fig.add_subplot(2, 3, 4)
imshow_img(img_low, ax_4)ax_5 = fig.add_subplot(2, 3, 5)
imshow_img(img_high_1, ax_5)ax_6 = fig.add_subplot(2, 3, 6)
imshow_img(img_high_2, ax_6)plt.tight_layout()
plt.show()

在这里插入图片描述

下面展示的是函数未填充时,会产生交叠错误;而函数填充0后,产生我们期望的结果,但是此时的滤波器应该是原来的2倍大小,如果是还是原来的大小的话,那么图像会比之前更模糊的。

这里采用的方法是对图像进行零填充,再直接在频率域中创建期望的滤波器传递函数,该函数的到底会给你个填充零后的图像的大小相同。这个明显降低交叠错误,只是会出现振铃效应

# 未填充与填充0的结果
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH04/Fig0432(a)(square_original).tif', -1)#================未填充===================
# FFT
img_fft = np.fft.fft2(img_ori.astype(np.float32))# 中心化
fshift = np.fft.fftshift(img_fft)            # 将变换的频率图像四角移动到中心# 滤波器
radius = 50
center = img_ori.shape[:2]
h_high_1 = gauss_high_pass_filter(img_ori, center, radius=radius)
h_low = 1 - h_high_1img_low = frequency_filter(fshift, h_low)fig = plt.figure(figsize=(15, 5))
ax_1 = fig.add_subplot(1, 3, 1)
imshow_img(img_ori, ax_1)ax_2 = fig.add_subplot(1, 3, 2)
imshow_img(img_low, ax_2)#================填充0====================
fp = np.zeros([img_ori.shape[0]*2, img_ori.shape[1]*2])
fp[:img_ori.shape[0], :img_ori.shape[1]] = img_oriimg_fft = np.fft.fft2(fp.astype(np.float32))
fshift = np.fft.fftshift(img_fft)   hp = 1 - gauss_high_pass_filter(fp, fp.shape, radius=100)img_low = frequency_filter(fshift, hp)
img_dst = img_low[:img_ori.shape[0], :img_ori.shape[1]]ax_3 = fig.add_subplot(1, 3, 3)
imshow_img(img_dst, ax_3)plt.tight_layout()
plt.show()

在这里插入图片描述

另一个合理的做法是:构建一个与未填充图像大小相同的函数,计算该函数的IDFT得到相应的空间表示,在空间域中对这一表示填充,然后计算其DFT返回到频率域。这也会出现振铃效应

def centralized(arr):"""centralized 1d array $f(x) (-1)^{n}$"""u = arr.shape[0]dst = np.zeros(arr.shape)# 中心化for n in range(u):dst[n] = arr[n] * ((-1) ** n)return dst
# 频率域反变换到空间域,再填充,再DFT,会出现振铃效应
h = np.zeros([256])
h[:9] = 1
h_c = np.fft.fftshift(h)fig = plt.figure(figsize=(15, 10))
grid = plt.GridSpec(2, 3, wspace=0.2, hspace=0.1)
ax_1 = fig.add_subplot(grid[0, 0])
ax_1.plot(h_c), ax_1.set_xticks([0, 128, 255]), ax_1.set_yticks(np.arange(-0.2, 1.4, 0.2)), ax_1.set_xlim([0, 255])# 用公式法的中以化才能得到理想的结果
h_pad = np.pad(h, (0, 256), mode='constant', constant_values=0)
ifshift = centralized_2d(h_pad.reshape(1, -1)).flatten() # 也可以用centralized_2d这个函数
ifft = np.fft.ifft(ifshift)
ifft = ifft.real * 2
ifft[:128] = 0
ifft[384:] = 0
ax_2 = fig.add_subplot(grid[0, 1:3])
ax_2.plot(ifft), ax_2.set_xticks([0, 128, 256, 384, 511]), ax_2.set_yticks(np.arange(-0.01, 0.05, 0.01)), ax_2.set_xlim([0, 511])f = ifft[128:384]
ax_3 = fig.add_subplot(grid[1, 0])
ax_3.plot(f), ax_3.set_xticks([0, 128, 255]), ax_3.set_yticks(np.arange(-0.01, 0.05, 0.01)), ax_3.set_xlim([0, 255])# 已经中心化,截取部分构成原函数,但出现的效果不是太好,但可以看出振铃效应
d = 120
f_ = np.zeros([h.shape[0]])
f_[:256-d] = f[d:]
f_pad = np.pad(f_, (0, 256), mode='constant', constant_values=0)
f_centralized = centralized(f_pad)
fft = np.fft.fft(f_centralized)
ax_4 = fig.add_subplot(grid[1, 1:3])
ax_4.plot(fft.real), ax_4.set_xticks([0, 128, 256, 384, 511]), ax_4.set_yticks(np.arange(-0.2, 1.4, 0.2)), ax_4.set_xlim([0, 511])plt.show()

在这里插入图片描述

零相移滤波器

  • 相角计算为复数的实部与虚部之比的反正切。因为H(u,v)H(u, v)H(u,v)同是乘以R,IR,IR,I,所以当这个比率形成后,它会被抵消。对实部和虚部的影响相同且对相角无影响的滤波器。
# 相角对反变换的影响
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH04/Fig0431(d)(blown_ic_crop).tif', -1)#================未填充===================
# FFT
img_fft = np.fft.fft2(img_ori.astype(np.float32))# 中心化
fshift = np.fft.fftshift(img_fft)            # 频谱与相角
spectrum = spectrum_fft(fshift)
phase = phase_fft(fshift)# 相角乘以-1
phase_1 = phase * -1
new_fshift = spectrum * np.exp(phase_1 * -1j)
new_fshift = np.fft.ifftshift(new_fshift)
recon_1 = np.fft.fft2(new_fshift)# 相角乘以0.5,需要乘以一个倍数,以便可视化
phase_2 = phase * 0.25
new_fshift = spectrum * np.exp(phase_2 * -1j)
new_fshift = np.fft.ifftshift(new_fshift)
recon_2 = np.fft.fft2(new_fshift)
recon_2 = np.uint8(normalize(recon_2.real) * 4000)fig = plt.figure(figsize=(15, 5))
ax_1 = fig.add_subplot(1, 3, 1)
imshow_img(img_ori, ax_1)ax_2 = fig.add_subplot(1, 3, 2)
imshow_img(recon_1.real, ax_2)ax_3 = fig.add_subplot(1, 3, 3)
ax_3.imshow(recon_2, cmap='gray')plt.tight_layout()
plt.show()

在这里插入图片描述

频率域滤波步骤小结

  1. 已知一幅大小为M×NM\times NM×N的输入图像f(x,y)f(x, y)f(x,y),分别得到填充零后的尺寸PPPQQQ,即P=2MP=2MP=2MQ=2NQ=2NQ=2N
  2. 使用零填充、镜像填充或复制填充,形成大小为P×QP\times QP×Q的填充后的图像fP(x,y)f_P(x, y)fP(x,y)
  3. fP(x,y)f_P(x, y)fP(x,y)乘以(−1)x+y(-1)^{x+y}(1)x+y,使用傅里叶变换位于P×QP\times QP×Q大小的频率矩形的中心。
  4. 计算步骤3得到的图像的DFT,即F(u,v)F(u, v)F(u,v)
  5. 构建一个实对称滤波器传递函数H(u,v)H(u, v)H(u,v),其大小为P×QP\times QP×Q,中心中(P/2,Q/2)(P/2, Q/2)(P/2,Q/2)处。
  6. 采用对应像素相乘得到G(u,v)=H(u,v)F(u,v)G(u, v) = H(u, v)F(u, v)G(u,v)=H(u,v)F(u,v)
  7. 计算G(u,v)G(u, v)G(u,v)的IDFT得到滤波后的图像(大小为P×QP\times QP×Q),gP(x,y)={Real[J−1[G(u,v)]]}(−1)x+yg_P(x, y) = \Big\{\text{Real} \big[\mathfrak{J}^{-1}[G(u, v)] \big]\Big\}(-1)^{x+y}gP(x,y)={Real[J1[G(u,v)]]}(1)x+y
  8. 最后,从gP(x,y)g_P(x, y)gP(x,y)的左上象限提取一个大小为M×NM\times NM×N的区域,得到与输入图像大小相同的滤波后的结果g(x,y)g(x, y)g(x,y)
def pad_image(img, mode='constant'):"""pad image into PxQ shape, orginal is in the top left corner.param: img: input imageparam: mode: input, str, is numpy pad parameter, default is 'constant'. for more detail please refere to Numpy padreturn PxQ shape image padded with zeros or other values"""dst = np.pad(img, ((0, img.shape[0]), (0, img.shape[1])), mode=mode)return dst    
# 频率域滤波过程
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH04/Fig0431(d)(blown_ic_crop).tif', -1)
M, N = img_ori.shape[:2]
fig = plt.figure(figsize=(15, 15))# 这里对原图像进行pad,以得到更好的显示
img_ori_show = np.ones([img_ori.shape[0]*2, img_ori.shape[1]*2]) * 255
img_ori_show[:img_ori.shape[0], img_ori.shape[1]:] = img_ori
ax_1 = fig.add_subplot(3, 3, 1)
imshow_img(img_ori_show, ax_1)fp = pad_image(img_ori, mode='constant')
ax_2 = fig.add_subplot(3, 3, 2)
imshow_img(fp, ax_2)fp_cen = centralized_2d(fp)
fp_cen_show = np.clip(fp_cen, 0, 255) # 负数的都截断为0
ax_3 = fig.add_subplot(3, 3, 3)
ax_3.imshow(fp_cen_show, cmap='gray'), ax_3.set_xticks([]), ax_3.set_yticks([])fft = np.fft.fft2(fp_cen)
spectrum = spectrum_fft(fft)
spectrum = np.log(1 + spectrum)
ax_4 = fig.add_subplot(3, 3, 4)
imshow_img(spectrum, ax_4)H = 1 - gauss_high_pass_filter(fp, center=fp.shape, radius=70)
ax_5 = fig.add_subplot(3, 3, 5)
imshow_img(H, ax_5)HF = fft * H
HF_spectrum = np.log(1 + spectrum_fft(HF))
ax_6 = fig.add_subplot(3, 3, 6)
imshow_img(HF_spectrum, ax_6)ifft = np.fft.ifft2(HF)
gp = centralized_2d(ifft.real)
ax_7 = fig.add_subplot(3, 3, 7)
imshow_img(gp, ax_7)# 最终结果有黑边
g = gp[:M, :N]
ax_8 = fig.add_subplot(3, 3, 8)
imshow_img(g, ax_8)plt.tight_layout()
plt.show()

在这里插入图片描述

def frequency_filter(fft, h):"""Frequency domain filtering using FFTparam: fshift: input, FFT shift to centerparam: h: input, filter, value range [0, 1]return a uint8 [0, 255] reconstruct image"""# 滤波res = fft * h# 先反中以化,再反变换ifft = np.fft.ifft2(res)# 取实数部分recon = centralized_2d(ifft.real)# 小于0都被置为0recon = np.clip(recon, 0, recon.max())recon = np.uint8(normalize(recon) * 255)return recon
# 频率域滤波
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH04/Fig0431(d)(blown_ic_crop).tif', -1)
M, N = img_ori.shape[:2]# 填充
fp = pad_image(img_ori, mode='reflect')
# 中心化
fp_cen = centralized_2d(fp)
# 正变换
fft = np.fft.fft2(fp_cen)
# 滤波器
H = 1 - gauss_high_pass_filter(fp, center=fp.shape, radius=100)
# 滤波
HF = fft * H
# 反变换
ifft = np.fft.ifft2(HF)
# 去中心化
gp = centralized_2d(ifft.real)
# 还回来与原图像的大小
g = gp[:M, :N]
fig = plt.figure(figsize=(15, 15))
ax_8 = fig.add_subplot(3, 3, 8)
imshow_img(g, ax_8)
plt.tight_layout()
plt.show()

在这里插入图片描述

空间域和频率域滤波之间的对应关系

空间域中的滤波器核与频率域傅里叶变换对:
h(x,y)⇔H(u,v)(4.106)h(x, y) \Leftrightarrow H(u, v) \tag{4.106}h(x,y)H(u,v)(4.106)

h(x,y)h(x, y)h(x,y)是空间核。这个核 可以由一个频率域滤波器对一个冲激的响应得到,因此有时我们称h(x,y)h(x, y)h(x,y)H(u,v)H(u, v)H(u,v)的冲激响应。

一维频率域高斯传递函数
H(u)=Ae−u2/2σ2(4.107)H(u) = A e^{-u^2/2\sigma^2} \tag{4.107}H(u)=Aeu2/2σ2(4.107)
空间域的核 由H(u)H(u)H(u)的傅里叶反变换得到
h(x)=2πσAe−2π2σ2x2(4.108)h(x) = \sqrt{2\pi}\sigma A e^{-2\pi^2\sigma^2 x^2} \tag{4.108}h(x)=2πσAe2π2σ2x2(4.108)

这是两个很重要的公式

  1. 它们是一个傅里叶变换对,两者都是高斯函数和实函数
  2. 两个函数的表现相反
  • 高斯差

    • 用一个常量减去低通函数,可以构建一个高通滤波器。
    • 因为使用所谓的高斯差(涉及两个低通函数)就可更好地控制滤波函数的形状
  • 频率域 A≥B,σ1>σ2A \ge B, \sigma_1 > \sigma_2AB,σ1>σ2
    H(u)=Ae−u2/2σ12−Be−u2/2σ22(4.109)H(u) = A e^{-u^2/2\sigma_1^2} - B e^{-u^2/2\sigma_2^2}\tag{4.109}H(u)=Aeu2/2σ12Beu2/2σ22(4.109)

  • 空间域
    h(x)=2πσ1Ae−2π2σ12x2−2πσ2Be−2π2σ22x2(4.110)h(x) = \sqrt{2\pi}\sigma_1 A e^{-2\pi^2\sigma_1^2 x^2} - \sqrt{2\pi}\sigma_2 B e^{-2\pi^2\sigma_2^2 x^2} \tag{4.110}h(x)=2πσ1Ae2π2σ12x22πσ2Be2π2σ22x2(4.110)

# 空间域与频率域的滤波器对应关系
u = np.linspace(-3, 3, 200)A = 1
sigma = 0.2
Hu = A * np.exp(-np.power(u, 2) / (2 * np.power(sigma, 2)))x = u
hx = np.sqrt(2 * np.pi) * sigma * A * np.exp(-2 * np.pi**2 * sigma**2 * x**2)fig = plt.figure(figsize=(10, 10))
ax_1 = setup_axes(fig, 221)
ax_1.plot(u, Hu), ax_1.set_title('H(u)', loc='center', y=1.05), ax_1.set_ylim([0, 1]), ax_1.set_yticks([])B = 1
sigma_2 = 4
Hu_2 = B * np.exp(-np.power(u, 2) / (2 * np.power(sigma_2, 2)))
Hu_diff = Hu_2 - Huax_2 = setup_axes(fig, 222)
ax_2.plot(x, Hu_diff), ax_2.set_title('H(u)', loc='center', y=1.05), ax_2.set_ylim([0, 1.1]), ax_2.set_yticks([])ax_3 = setup_axes(fig, 223)
ax_3.plot(x, hx), ax_3.set_title('h(x)', loc='center', y=1.05), ax_3.set_ylim([0, 0.8]), ax_3.set_yticks([])hx_2 = np.sqrt(2 * np.pi) * sigma_2 * B * np.exp(-2 * np.pi**2 * sigma_2**2 * x**2)
hx_diff = hx_2 - hxax_4 = setup_axes(fig, 224)
ax_4.plot(x, hx_diff), ax_4.set_title('h(x)', loc='center', y=1.05), ax_4.set_ylim([-1, 10]), ax_4.set_yticks([])plt.tight_layout()
plt.show()

在这里插入图片描述

# 空间核得到频率域
img_ori = cv2.imread('DIP_Figures/DIP3E_Original_Images_CH04/Fig0438(a)(bld_600by600).tif', -1)fp = pad_zero(img_ori)
fp_cen = centralized_2d(fp)
fft = np.fft.fft2(fp_cen)
spectrum = spectrum_fft(fft)
spectrum = np.log(1 + spectrum)plt.figure(figsize=(18, 15))
plt.subplot(1, 2, 1), plt.imshow(img, cmap='gray'), plt.title('No Log')
plt.subplot(1, 2, 2), plt.imshow(spectrum, cmap='gray'), plt.title('FFT')
plt.tight_layout()
plt.show()

在这里插入图片描述
注:频率域的Sobel滤波器还没有解决

# 频域
center = (fp.shape[0], fp.shape[1] + 300)
GHPF = gauss_high_pass_filter(fp, center, radius=200)
GHPF = (1 - np.where(GHPF > 1e-6, GHPF, 1)) * -2center = (fp.shape[0], fp.shape[1] - 300)
GHPF_1 = gauss_high_pass_filter(fp, center, radius=200)
GHPF_1 = (1 - np.where(GHPF_1 > 1e-6, GHPF_1, 1)) * 2sobel_f = GHPF + GHPF_1plt.figure(figsize=(15, 5))plt.subplot(1, 3, 1), plt.imshow(GHPF, 'gray')
plt.subplot(1, 3, 2), plt.imshow(GHPF_1, 'gray')
plt.subplot(1, 3, 3), plt.imshow(sobel_f, 'gray')plt.tight_layout()
plt.show()

在这里插入图片描述

# 频域
fig = plt.figure(figsize=(15, 5))
HF = fft * sobel_f
HF_spectrum = np.log(1 + spectrum_fft(HF))
ax_6 = fig.add_subplot(1, 3, 1)
imshow_img(HF_spectrum, ax_6)ifft = np.fft.ifft2(HF)
gp = centralized_2d(ifft.real)
ax_7 = fig.add_subplot(1, 3, 2)
imshow_img(gp, ax_7)# 最终结果有黑边
g = gp[:M, :N]
ax_8 = fig.add_subplot(1, 3, 3)
imshow_img(g, ax_8)# plt.figure(figsize=(15, 5))# plt.subplot(1, 3, 1), plt.imshow(GHPF, 'gray')
# plt.subplot(1, 3, 2), plt.imshow(GHPF_1, 'gray')
# plt.subplot(1, 3, 3), plt.imshow(sobel_f, 'gray')plt.tight_layout()
plt.show()

在这里插入图片描述

空间域的Sobel滤波器

def kernel_seperate(kernel):"""这里的分离核跟之前不太一样get kernel seperate vector if separableparam: kernel: input kerel of the filterreturn two separable vector c, r"""rank = np.linalg.matrix_rank(kernel)if rank == 1:#-----------------Numpy------------------# here for sobel kernel seperatec = kernel[:, -1]r = kernel[-1, :]else:print('Not separable')#     c = np.array(c).reshape(-1, 1)
#     r = np.array(r).reshape(-1, 1)return c, r
def separate_kernel_conv2D(img, kernel):"""separable kernel convolution 2D, if 2D kernel not separable, then canot use this fuction. in the fuction. first need toseperate the 2D kernel into two 1D vectors.param: img: input image you want to implement 2d convolution with 2d kernelparam: kernel: 2D separable kernel, such as Gaussian kernel, Box Kernelreturn image after 2D convolution"""m, n = kernel.shape[:2]pad_h = int((m - 1) / 2)pad_w = int((n - 1) / 2)w_1, w_2 = kernel_seperate(kernel)
#     w_1 = np.array([-1, 0, 1])
#     w_2 = np.array([1, 2, 1])convovle = np.vectorize(np.convolve, signature='(x),(y)->(k)')r_2 = convovle(img, w_2)r_r = np.rot90(r_2)r_1 = convovle(r_r, w_1)r_1 = r_1.Tr_1 = r_1[:, ::-1]img_dst = img.copy().astype(np.float)img_dst = r_1[pad_h:-pad_h, pad_w:-pad_w]return img_dst
# Sobel梯度增强边缘
img_ori = cv2.imread("DIP_Figures/DIP3E_Original_Images_CH04/Fig0438(a)(bld_600by600).tif", 0)sobel_x = np.zeros([3, 3], np.int)
sobel_x[0, :] = np.array([-1, -2, -1])
sobel_x[2, :] = np.array([1, 2, 1])sobel_y = np.zeros([3, 3], np.int)
sobel_y[:, 0] = np.array([-1, -2, -1])
sobel_y[:, 2] = np.array([1, 2, 1])gx = separate_kernel_conv2D(img_ori, kernel=sobel_x)
gy = separate_kernel_conv2D(img_ori, kernel=sobel_y)# gx = cv2.filter2D(img_ori, ddepth=-1, kernel=sobel_x)
# gy = cv2.filter2D(img_ori, ddepth=-1, kernel=sobel_y)# 先对gx gy做二值化处理再应用下面的公式
img_sobel = np.sqrt(gx**2 + gy**2)   # 二值化后,平方根的效果与绝对值很接近
img_sobel = abs(gx) + abs(gy)
img_sobel = np.uint8(normalize(img_sobel) * 255)plt.figure(figsize=(15, 12))
plt.subplot(1, 2, 1), plt.imshow(img_ori,   'gray', vmax=255), plt.title("Original"), plt.xticks([]), plt.yticks([])
plt.subplot(1, 2, 2), plt.imshow(img_sobel, 'gray', vmax=255), plt.title("Sobel"), plt.xticks([]), plt.yticks([])
plt.tight_layout()
plt.show()

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/260705.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# :试玩EventLog

1. 专门创建Source的Log   创建了Source&#xff0c;log显示在 Event viewer/Applications and Services logs/ 自定义Source 中&#xff0c;待遇比较高&#xff0c;专门显示的。 创建Source需要管理员身份&#xff0c;否则Crash。 如果已经打开了 Computer Management,请关闭…

css 宋体_Java前端基础(一)之html/css

1.1 htmlHTML:超文本标记语言(Hyper Text Markup Language)&#xff0c;标准通用标记语言下的一个应用。HTML 不是一种编程语言&#xff0c;而是一种标记语言 (markup language)&#xff0c;是网页制作所必备的WEB开发工具&#xff1a;hbuilder/webstorm/vs code/eclpise最简单…

gpio的8种工作模式_Stm32之GPIO工作模式简介

GPIO的8种工作模式GPIO初始化结构体的时候&#xff0c;必须要配置合适的工作模式&#xff0c;这样才能使得IO口发挥应有的作用。工作模式大体上共分为输入输出两类&#xff0c;共8种&#xff0c;下面将介绍这8种工作模式。GPIO工作模式输入模式GPIO_Mode_AIN 模拟输入 GPIO_Mod…

vagrant,流浪汉,我又来啦。

最近学个DEVOPS2.0&#xff0c;讲微服务&#xff0c;容器华&#xff0c;持续部署&#xff0c;很到位&#xff0c;就一个一个工具撸一撸。。。 vagrant&#xff0c;以前接触过&#xff0c;所以上手快&#xff0c;&#xff0c;哈哈&#xff0c;&#xff0c;用时再具体配置。 virt…

dedecms最新版本修改任意管理员漏洞

此漏洞无视gpc转义&#xff0c;过80sec注入防御。 补充下&#xff0c;不用担心后台找不到。这只是一个demo&#xff0c;都能修改任意数据库了&#xff0c;还怕拿不到SHELL&#xff1f; 起因是全局变量$GLOBALS可以被任意修改&#xff0c;随便看了下&#xff0c;漏洞一堆&#x…

第4章 Python 数字图像处理(DIP) - 频率域滤波10 - 使用低通频率域滤波器平滑图像 - 理想、高斯、巴特沃斯低通滤波器

目录使用低通频率域滤波器平滑图像理想低通滤波器(ILPF)高斯低通滤波器(GLPF)巴特沃斯低通滤波器低通滤波的例子使用低通频率域滤波器平滑图像 理想低通滤波器(ILPF) 在以原点为中心的一个圆内无衰减地通过所有频率&#xff0c;而在这个圆外“截止”所有的频率的二维低通滤波…

bluecam连接步骤说明_厂家详解旋片式真空泵使用说明

旋片式真空泵是有区分单双极高速直联结构的真空泵&#xff0c;是用来对密封容器抽除气体的基本设备之一。旋片式真空泵的泵与电机连轴&#xff0c;有着高转速、外型小、结构紧凑、流动性工作方便的优点。本文所使用旋片式真空泵使用说明资料&#xff0c;是台冠真空泵技术团队工…

第4章 Python 数字图像处理(DIP) - 频率域滤波11 - 使用高通滤波器锐化图像

目录使用高通滤波器锐化图像由低通滤波器得到理想、高斯和巴特沃斯高通滤波器指纹增强频域中的拉普拉斯钝化掩蔽、高提升滤波和高频强调滤波同态滤波使用高通滤波器锐化图像 由低通滤波器得到理想、高斯和巴特沃斯高通滤波器 HHP(u,v)1−HLP(u,v)(4.118)H_{HP}(u, v) 1 - H_{…

漫步者lollipods如何调节音量_漫步者MF5扩音器体验:老师值得入手

对于教师职业来说&#xff0c;保护好嗓子是很重要的。每天为学生操劳&#xff0c;频繁的讲课&#xff0c;很多老师都遇上了喉咙沙哑的问题。怎么样才能保护好老师的嗓子呢&#xff1f;“小蜜蜂”是很多老师们的选择&#xff0c;这种扩音器可以挂在腰间&#xff0c;通过麦克风&a…

pandas删除某列有空值的行_Python-零基础学习Pandas知识点整理(2)

DataFrame数据的清洗--预处理操作import pandas as pdimport numpy as np#DataFrame数据框行或列的删除#df.drop(labelsNone,axis0,indexNone,columnsNone,levelNone,inplaceFalse,error"raise")#labels 表示需要删除的行或列的标签&#xff0c;多行或多列用列表传入…

第4章 Python 数字图像处理(DIP) - 频率域滤波12 - 选择性滤波 - 带阻

目录选择性滤波带阻滤波器和带通滤波器陷波滤波器选择性滤波 处理特定的频带的滤波器称为频带滤波器 带阻滤波器&#xff1a; 若某个频带中的频率被滤除 带通滤波器&#xff1a; 若某个频带中的频率被通过 处理小频率矩形区域的滤波器称为陷波滤波器 陷波带阻滤波器&#x…

python打包工具报错_python打包生成exe报错

如图所示 如果出现的是这个问题可以可以考虑以下方法 首先卸载原先下载的 Pyinstaller pip uninstall pyinstaller 再执行以下代码&#xff0c;去github上下载 pip install https://github.com/pyinstaller/pyinstaller/archive/develop.zip 注释&#xff1a;再次打包&#xff…

去除lcd图片的摩尔纹_宝妈时尚产后有妊娠纹怎么办?教你这三招,轻松修复肚皮!...

产后肚子上长妊娠纹&#xff0c;相信是很多妈妈的痛点。首先我们来介绍一下什么是妊娠纹。由于妊娠期荷尔蒙的影响&#xff0c;加之腹部膨隆使皮肤的弹力纤维与胶原纤维损伤或断裂&#xff0c;腹部皮肤变薄变细&#xff0c;出现一些宽窄不同、长短不一的粉红色或紫红色的波浪状…

anaconda 换清华镜像源 windows

方法1 Windows 下安装好Anaconda 应该会有如下这些应用&#xff0c;我们打开如下图anaconda Prompt(下面简称prompt)&#xff0c;(当然CMD也可以&#xff0c;只是我比较喜欢用prompt) 打开如下图 使用下面命令&#xff0c;即可以添加清华镜像 conda config --add channels …

提高表格可读性的一些技巧

表格的应用由于工作原因&#xff0c;经常接触到表格。我们发现&#xff0c;表格不但广泛的运用在各类数据收集和分析&#xff0c;同时通过表格这样一种二维矩阵来整理和陈列信息时&#xff08;即便最后的展示方式并非一个典型的表格样式&#xff09;&#xff0c;能够很好的表达…

分页第一页用0还是1_如何设计api分页

常规的分页方式API处理分页看似简单&#xff0c;实际上暗藏危机。最常见的分页方式&#xff0c;大概是下面这样的/users/?page1&limit5//服务端返回最理想的情况下&#xff0c;客户端请求第一页的5条数据&#xff0c;服务端如常返回&#xff0c;比如下图:拿Twitter的图用一…

数据挖掘肿瘤预测_科研套路不嫌多,数据挖掘发3分

解螺旋公众号陪伴你科研的第2003天如何复现一篇3分生信研究做科研需要先学习套路&#xff0c;才能超越套路。今天给大家介绍的套路文献是今年发表在《Oncology reports》(IF 3.041)上的一篇文章。文章的标题虽然看上去比较泛&#xff0c;但也让读者一眼就能知道主题了&#xff…

Jupyter notebook 导出PDF的3种方法

很多用Jupyter notebook的都想导出PDF&#xff0c;但是我们点击Download as PDF via LaTex. 然后呢&#xff1f; Ohzzzzzzzzz 出现下图的错误&#xff0c;看到这里感觉糟糕透啦。虽然可以根据提供的方法解决这个问题。下面我说说我的方法吧。 方法1 打开jupyter notebook&a…

mybatis中的#{value}和${value}的区别

2019独角兽企业重金招聘Python工程师标准>>> 1. #{value}将传入的数据都当成一个字符串&#xff0c;会对自动传入的数据加一个双引号。 2. ${value}将传入的数据直接显示生成在sql中。 3. #{value}方式能够很大程度防止sql注入。  4.${value}方式无法防止Sql注入。…

数据库备份失败问题

备份对于服务器“服务器名”失败。&#xff08;Microsoft.SqlServer.Smo&#xff09; 其他信息&#xff1a;System.Data.SqlClient.SqlError:无法打开备份设备c:\abc.bak。出现操作系统错误5(拒绝访问。)。(Microsoft.SqlServer.Smo&#xff09; 解决办法&#xff1a; Sql Serv…