如何使用 FFT 去除图像中的重复图案
How to remove repititve pattern from an image using FFT
我有一张带有重复图案(水平白线)的肤色图像,由使用一行传感器感知照片的扫描仪生成。
我的问题是如何在不影响图像质量的情况下有效地使用 FFT 对图像进行降噪,有人告诉我必须抑制线条手动出现在幅度谱中,但我不知道该怎么做,你能告诉我怎么做吗?
我的方法是使用快速傅里叶变换(FFT)逐通道去噪图像。
我已经在傅里叶域中尝试了 HPF 和 LPF,但结果并不如您所见:
我的代码:
from skimage.io import imread, imsave
from matplotlib import pyplot as plt
import numpy as np
img = imread('skin.jpg')
R = img[...,2]
G = img[...,1]
B = img[...,0]
f1 = np.fft.fft2(R)
fshift1 = np.fft.fftshift(f1)
phase_spectrumR = np.angle(fshift1)
magnitude_spectrumR = 20*np.log(np.abs(fshift1))
f2 = np.fft.fft2(G)
fshift2 = np.fft.fftshift(f2)
phase_spectrumG = np.angle(fshift2)
magnitude_spectrumG = 20*np.log(np.abs(fshift2))
f3 = np.fft.fft2(B)
fshift3 = np.fft.fftshift(f3)
phase_spectrumB = np.angle(fshift3)
magnitude_spectrumB = 20*np.log(np.abs(fshift2))
#===============================
# LPF # HPF
magR = np.zeros_like(R) # = fshift1 #
magR[magR.shape[0]//4:3*magR.shape[0]//4,
magR.shape[1]//4:3*magR.shape[1]//4] = np.abs(fshift1[magR.shape[0]//4:3*magR.shape[0]//4,
magR.shape[1]//4:3*magR.shape[1]//4]) # =0 #
resR = np.abs(np.fft.ifft2(np.fft.ifftshift(magR)))
resR = R - resR
#===============================
magnitude_spectrumR
plt.subplot(221)
plt.imshow(R, cmap='gray')
plt.title('Original')
plt.subplot(222)
plt.imshow(magnitude_spectrumR, cmap='gray')
plt.title('Magnitude Spectrum')
plt.subplot(223)
plt.imshow(phase_spectrumR, cmap='gray')
plt.title('Phase Spectrum')
plt.subplot(224)
plt.imshow(resR, cmap='gray')
plt.title('Processed')
plt.show()
这里有一个简单有效的线性过滤策略来去除水平线伪影:
大纲:
通过在垂直维度上寻找图像功率谱中的峰值来估计失真的频率。函数 scipy.signal.welch 对此很有用。
设计两个滤波器:截止频率刚好低于失真频率的高通滤波器和截止频率接近直流的低通滤波器。我们将垂直应用高通滤波器,水平应用低通滤波器,以尝试隔离失真。我们将使用 scipy.signal.firwin 来设计这些过滤器,尽管有很多方法可以做到这一点。
将恢复后的图像计算为“image − (hpf ⊗ lpf) ∗ image”。
代码:
# Copyright 2021 Google LLC.
# SPDX-License-Identifier: Apache-2.0
import numpy as np
from scipy.ndimage import convolve1d
from scipy.signal import firwin, welch
def remove_lines(image, distortion_freq=None, num_taps=65, eps=0.025):
"""Removes horizontal line artifacts from scanned image.
Args:
image: 2D or 3D array.
distortion_freq: Float, distortion frequency in cycles/pixel, or
`None` to estimate from spectrum.
num_taps: Integer, number of filter taps to use in each dimension.
eps: Small positive param to adjust filters cutoffs (cycles/pixel).
Returns:
Denoised image.
"""
image = np.asarray(image, float)
if distortion_freq is None:
distortion_freq = estimate_distortion_freq(image)
hpf = firwin(num_taps, distortion_freq - eps,
pass_zero='highpass', fs=1)
lpf = firwin(num_taps, eps, pass_zero='lowpass', fs=1)
return image - convolve1d(convolve1d(image, hpf, axis=0), lpf, axis=1)
def estimate_distortion_freq(image, min_frequency=1/25):
"""Estimates distortion frequency as spectral peak in vertical dim."""
f, pxx = welch(np.reshape(image, (len(image), -1), 'C').sum(axis=1))
pxx[f < min_frequency] = 0.0
return f[pxx.argmax()]
示例:
在人像图像上,estimate_distortion_freq
估计失真频率为 0.1094 cycles/pixel(周期为 9.14 像素)。过滤“image − (hpf ⊗ lpf) ∗ image”的传递函数如下所示:
这是 remove_lines
的过滤输出:
在皮肤图像上,estimate_distortion_freq
估计失真频率为 0.08333 cycles/pixel(周期为 12.0 像素)。 remove_lines
:
的过滤输出
两个示例中的失真大部分都已消除。它并不完美:在肖像图像上,在顶部和底部边界附近仍然可以看到一些波纹,这是使用大型滤波器或傅立叶方法时的典型缺陷。尽管如此,它还是比原始图像有了很好的改进。
我有一张带有重复图案(水平白线)的肤色图像,由使用一行传感器感知照片的扫描仪生成。
我的问题是如何在不影响图像质量的情况下有效地使用 FFT 对图像进行降噪,有人告诉我必须抑制线条手动出现在幅度谱中,但我不知道该怎么做,你能告诉我怎么做吗?
我的方法是使用快速傅里叶变换(FFT)逐通道去噪图像。
我已经在傅里叶域中尝试了 HPF 和 LPF,但结果并不如您所见:
我的代码:
from skimage.io import imread, imsave
from matplotlib import pyplot as plt
import numpy as np
img = imread('skin.jpg')
R = img[...,2]
G = img[...,1]
B = img[...,0]
f1 = np.fft.fft2(R)
fshift1 = np.fft.fftshift(f1)
phase_spectrumR = np.angle(fshift1)
magnitude_spectrumR = 20*np.log(np.abs(fshift1))
f2 = np.fft.fft2(G)
fshift2 = np.fft.fftshift(f2)
phase_spectrumG = np.angle(fshift2)
magnitude_spectrumG = 20*np.log(np.abs(fshift2))
f3 = np.fft.fft2(B)
fshift3 = np.fft.fftshift(f3)
phase_spectrumB = np.angle(fshift3)
magnitude_spectrumB = 20*np.log(np.abs(fshift2))
#===============================
# LPF # HPF
magR = np.zeros_like(R) # = fshift1 #
magR[magR.shape[0]//4:3*magR.shape[0]//4,
magR.shape[1]//4:3*magR.shape[1]//4] = np.abs(fshift1[magR.shape[0]//4:3*magR.shape[0]//4,
magR.shape[1]//4:3*magR.shape[1]//4]) # =0 #
resR = np.abs(np.fft.ifft2(np.fft.ifftshift(magR)))
resR = R - resR
#===============================
magnitude_spectrumR
plt.subplot(221)
plt.imshow(R, cmap='gray')
plt.title('Original')
plt.subplot(222)
plt.imshow(magnitude_spectrumR, cmap='gray')
plt.title('Magnitude Spectrum')
plt.subplot(223)
plt.imshow(phase_spectrumR, cmap='gray')
plt.title('Phase Spectrum')
plt.subplot(224)
plt.imshow(resR, cmap='gray')
plt.title('Processed')
plt.show()
这里有一个简单有效的线性过滤策略来去除水平线伪影:
大纲:
通过在垂直维度上寻找图像功率谱中的峰值来估计失真的频率。函数 scipy.signal.welch 对此很有用。
设计两个滤波器:截止频率刚好低于失真频率的高通滤波器和截止频率接近直流的低通滤波器。我们将垂直应用高通滤波器,水平应用低通滤波器,以尝试隔离失真。我们将使用 scipy.signal.firwin 来设计这些过滤器,尽管有很多方法可以做到这一点。
将恢复后的图像计算为“image − (hpf ⊗ lpf) ∗ image”。
代码:
# Copyright 2021 Google LLC.
# SPDX-License-Identifier: Apache-2.0
import numpy as np
from scipy.ndimage import convolve1d
from scipy.signal import firwin, welch
def remove_lines(image, distortion_freq=None, num_taps=65, eps=0.025):
"""Removes horizontal line artifacts from scanned image.
Args:
image: 2D or 3D array.
distortion_freq: Float, distortion frequency in cycles/pixel, or
`None` to estimate from spectrum.
num_taps: Integer, number of filter taps to use in each dimension.
eps: Small positive param to adjust filters cutoffs (cycles/pixel).
Returns:
Denoised image.
"""
image = np.asarray(image, float)
if distortion_freq is None:
distortion_freq = estimate_distortion_freq(image)
hpf = firwin(num_taps, distortion_freq - eps,
pass_zero='highpass', fs=1)
lpf = firwin(num_taps, eps, pass_zero='lowpass', fs=1)
return image - convolve1d(convolve1d(image, hpf, axis=0), lpf, axis=1)
def estimate_distortion_freq(image, min_frequency=1/25):
"""Estimates distortion frequency as spectral peak in vertical dim."""
f, pxx = welch(np.reshape(image, (len(image), -1), 'C').sum(axis=1))
pxx[f < min_frequency] = 0.0
return f[pxx.argmax()]
示例:
在人像图像上,estimate_distortion_freq
估计失真频率为 0.1094 cycles/pixel(周期为 9.14 像素)。过滤“image − (hpf ⊗ lpf) ∗ image”的传递函数如下所示:
这是 remove_lines
的过滤输出:
在皮肤图像上,estimate_distortion_freq
估计失真频率为 0.08333 cycles/pixel(周期为 12.0 像素)。 remove_lines
:
两个示例中的失真大部分都已消除。它并不完美:在肖像图像上,在顶部和底部边界附近仍然可以看到一些波纹,这是使用大型滤波器或傅立叶方法时的典型缺陷。尽管如此,它还是比原始图像有了很好的改进。