点击上方“小白学视觉”,选择加"星标"或“置顶”
重磅干货,第一时间送达
来源:DeepHub IMBA
本文约4300字,建议阅读8分钟 本文将讨论图像从FFT到逆FFT的频率变换所涉及的各个阶段,并结合FFT位移和逆FFT位移的使用。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('sample.png',0) # Using 0 to read image in grayscale mode
plt.imshow(img, cmap='gray') #cmap is used to specify imshow that the image is in greyscale
plt.xticks([]), plt.yticks([]) # remove tick marks
plt.show()
1、快速傅里叶变换(FFT)
f = np.fft.fft2(img) #the image 'img' is passed to np.fft.fft2() to compute its 2D Discrete Fourier transform f
mag = 20*np.log(np.abs(f))
plt.imshow(mag, cmap = 'gray') #cmap='gray' parameter to indicate that the image should be displayed in grayscale.
plt.title('Magnitude Spectrum')
plt.xticks([]), plt.yticks([])
plt.show()
2、FFT位移
fshift = np.fft.fftshift(f) mag = 20*np.log(np.abs(fshift)) plt.imshow(mag, cmap = 'gray') plt.title('Centered Spectrum'), plt.xticks([]), plt.yticks([]) plt.show()
3、过滤
在通带内,幅频响应为 1 在阻带内,幅频响应为 0
在通带内,冲激响应为一个无限长的单位冲激函数序列 在阻带内,冲激响应为零
import math
def distance(point1,point2):
return math.sqrt((point1[0]-point2[0])**2 + (point1[1]-point2[1])**2)
def idealFilterLP(D0,imgShape):
base = np.zeros(imgShape[:2])
rows, cols = imgShape[:2]
center = (rows/2,cols/2)
for x in range(cols):
for y in range(rows):
if distance((y,x),center) < D0:
base[y,x] = 1
return base
def idealFilterHP(D0,imgShape):
base = np.ones(imgShape[:2])
rows, cols = imgShape[:2]
center = (rows/2,cols/2)
for x in range(cols):
for y in range(rows):
if distance((y,x),center) < D0:
base[y,x] = 0
return base
import math
def distance(point1,point2):
return math.sqrt((point1[0]-point2[0])**2 + (point1[1]-point2[1])**2)
def gaussianLP(D0,imgShape):
base = np.zeros(imgShape[:2])
rows, cols = imgShape[:2]
center = (rows/2,cols/2)
for x in range(cols):
for y in range(rows):
base[y,x] = math.exp(((-distance((y,x),center)**2)/(2*(D0**2))))
return base
def gaussianHP(D0,imgShape):
base = np.zeros(imgShape[:2])
rows, cols = imgShape[:2]
center = (rows/2,cols/2)
for x in range(cols):
for y in range(rows):
base[y,x] = 1 - math.exp(((-distance((y,x),center)**2)/(2*(D0**2))))
return base
fig, ax = plt.subplots(2, 2) # create a 2x2 grid of subplots
fig.suptitle('Filters') # set the title for the entire figure
# plot the first image in the top-left subplot
im1 = ax[0, 0].imshow(np.abs(idealFilterLP(50, img.shape)), cmap='gray')
ax[0, 0].set_title('Low Pass Filter of Diameter 50 px')
ax[0, 0].set_xticks([])
ax[0, 0].set_yticks([])
# plot the second image in the top-right subplot
im2 = ax[0, 1].imshow(np.abs(idealFilterHP(50, img.shape)), cmap='gray')
ax[0, 1].set_title('High Pass Filter of Diameter 50 px')
ax[0, 1].set_xticks([])
ax[0, 1].set_yticks([])
# plot the third image in the bottom-left subplot
im3 = ax[1, 0].imshow(np.abs(gaussianLP(50 ,img.shape)), cmap='gray')
ax[1, 0].set_title('Gaussian Filter of Diameter 50 px')
ax[1, 0].set_xticks([])
ax[1, 0].set_yticks([])
# plot the fourth image in the bottom-right subplot
im4 = ax[1, 1].imshow(np.abs(gaussianHP(50 ,img.shape)), cmap='gray')
ax[1, 1].set_title('Gaussian Filter of Diameter 50 px')
ax[1, 1].set_xticks([])
ax[1, 1].set_yticks([])
# adjust the spacing between subplots
fig.subplots_adjust(wspace=0.5, hspace=0.5)
# save the figure to a file
fig.savefig('filters.png', bbox_inches='tight')
4、乘法滤波器(Multiplying Filter)和平移后的图像(Shifted Image)
fig, ax = plt.subplots()
im = ax.imshow(np.log(1+np.abs(fftshifted_image * idealFilterLP(50,img.shape))), cmap='gray')
ax.set_title('Filtered Image in Frequency Domain')
ax.set_xticks([])
ax.set_yticks([])
fig.savefig('filtered image in freq domain.png', bbox_inches='tight')
5、逆FFT位移
fig, ax = plt.subplots()
im = ax.imshow(np.log(1+np.abs(np.fft.ifftshift(fftshifted_image * idealFilterLP(50,img.shape)))), cmap='gray')
ax.set_title('Filtered Image inverse fft shifted')
ax.set_xticks([])
ax.set_yticks([])
fig.savefig('filtered image inverse fft shifted.png', bbox_inches='tight')
6、快速傅里叶逆变换(IFFT)
fig, ax = plt.subplots()
im = ax.imshow(np.log(1+np.abs(np.fft.ifft2(np.fft.ifftshift(fftshifted_image * idealFilterLP(50,img.shape))))), cmap='gray')
ax.set_title('Final Filtered Image In Spatial Domain')
ax.set_xticks([])
ax.set_yticks([])
fig.savefig('final filtered image.png', bbox_inches='tight')
总结
def Freq_Trans(image, filter_used):
img_in_freq_domain = np.fft.fft2(image)
# Shift the zero-frequency component to the center of the frequency spectrum
centered = np.fft.fftshift(img_in_freq_domain)
# Multiply the filter with the centered spectrum
filtered_image_in_freq_domain = centered * filter_used
# Shift the zero-frequency component back to the top-left corner of the frequency spectrum
inverse_fftshift_on_filtered_image = np.fft.ifftshift(filtered_image_in_freq_domain)
# Apply the inverse Fourier transform to obtain the final filtered image
final_filtered_image = np.fft.ifft2(inverse_fftshift_on_filtered_image)
return img_in_freq_domain,centered,filter_used,filtered_image_in_freq_domain,inverse_fftshift_on_filtered_image,final_filtered_image
fig, axs = plt.subplots(12, 7, figsize=(30, 60))
filters = [(f, d) for f in [idealFilterLP, idealFilterHP, gaussianLP, gaussianHP] for d in [50, 100, 150]]
for row, (filter_name, filter_diameter) in enumerate(filters):
# Plot each filter output on a separate subplot
result = Freq_Trans(img, filter_name(filter_diameter, img.shape))
for col, title, img_array in zip(range(7),
["Original Image", "Spectrum", "Centered Spectrum", f"{filter_name.__name__} of Diameter {filter_diameter} px",
f"Centered Spectrum multiplied by {filter_name.__name__}", "Decentralize", "Processed Image"],
[img, np.log(1+np.abs(result[0])), np.log(1+np.abs(result[1])), np.abs(result[2]), np.log(1+np.abs(result[3])),
np.log(1+np.abs(result[4])), np.abs(result[5])]):
axs[row, col].imshow(img_array, cmap='gray')
axs[row, col].set_title(title)
plt.tight_layout()
plt.savefig('all_processess.png', bbox_inches='tight')
plt.show()
下载1:OpenCV-Contrib扩展模块中文版教程 在「小白学视觉」公众号后台回复:扩展模块中文教程,即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。 下载2:Python视觉实战项目52讲 在「小白学视觉」公众号后台回复:Python视觉实战项目,即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。 下载3:OpenCV实战项目20讲 在「小白学视觉」公众号后台回复:OpenCV实战项目20讲,即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。 交流群
欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~