如何使用OpenCV Python找到图像的傅里叶变换?

如何使用OpenCV Python找到图像的傅里叶变换?

傅里叶变换(Fourier Transform)是处理频率域信息的有力工具,可以在图像处理、信号处理和音频处理中找到很多应用。在本篇文章中,我们将介绍如何使用OpenCV Python对图像执行傅里叶变换的过程。

图像的傅里叶变换

在开始之前,我们需要先了解一下什么是傅里叶变换。

傅里叶变换是将一个函数(可以是时间域函数、空间域函数等)变换到频域的过程,它可以将图像从空间域(每个像素在x、y坐标上的位置)转换为频域(每个频率上的信号的强度)。在图片的情况下,每个像素的亮度都会在傅里叶变换中用一个频率分量表示。

以下是一幅灰度图像和它的傅里叶变换:

注:图片中间是直流分量(DC),左上角到右下角是高频分量(注意黑色和白色,用黑色表示低频,用白色表示高频),右上角到左下角也是高频分量

下面是一个简单的Python代码示例,它使用OpenCV的dft方法对图像执行傅里叶变换:

import cv2
import numpy as np

# 读入一幅灰度图像
img = cv2.imread('image.png', 0)

# 执行傅里叶变换
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
magnitude_spectrum = 20*np.log(np.abs(fshift))

# 显示图像和傅里叶变换结果
cv2.imshow('input image', img)
cv2.imshow('magnitude spectrum', magnitude_spectrum)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这个例子中,我们首先读入一幅灰度图像,并对其执行傅里叶变换。使用 np.fft.fft2()函数可以完成这个过程,并将它赋值给一个名为f的二维数组。接下来,我们使用np.fft.fftshift()函数将傅里叶变换的结果转移到图像中心,并将其赋值给一个名为fshift的新数组。最后,我们计算幅度谱,并将结果保存在一个名为magnitude_spectrum的数组中。你可以看到,在代码中,我们使用 20*np.log(np.abs(fshift))来计算幅度谱。

逆傅里叶变换

在处理完图像的傅里叶变换后,你可能想要再将其转换回空间域。这可以通过使用逆傅里叶变换实现,OpenCV也提供了逆傅里叶变换的方法 np.fft.ifft2() 。下面是一个示例代码:

import cv2
import numpy as np

# 读入一幅灰度图像
img = cv2.imread('image.png', 0)

# 执行傅里叶变换
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)

# 将结果转回空间域
ishift = np.fft.ifftshift(fshift)
iimg = np.fft.ifft2(ishift)
iimg = np.abs(iimg)

# 显示原图像和逆变换结果
cv2.imshow('input image', img)
cv2.imshow('reconstructed image', iimg)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这个例子中,我们使用np.fft.ifft2()函数执行逆傅里叶变换,并将结果保存在一个名为iimg的新数组中。你可以看到,在代码中,我们使用np.abs()函数以获取结果的幅值。

傅里叶变换的应用

傅里叶变换的应用相当广泛,下面是一些示例:

图像去噪

傅里叶变换可以用于图像去噪。以下是一个简单的示例代码:

import cv2
import numpy as np

# 读入一幅灰度图像
img = cv2.imread('image.png', 0)

# 添加高斯噪声
mean = 0
sigma = 30
gauss = np.random.normal(mean, sigma, img.shape)
gauss = gauss.reshape(img.shape[0], img.shape[1])
noisy = img + gauss

# 执行傅里叶变换
f = np.fft.fft2(noisy)
fshift = np.fft.fftshift(f)

# 设置低通滤波器,过滤掉高频分量
rows, cols = noisy.shape
crow, ccol = rows // 2, cols // 2
fshift[crow - 30:crow + 30, ccol - 30:ccol + 30] = 0

# 将结果转回空间域
ishift = np.fft.ifftshift(fshift)
iimg = np.fft.ifft2(ishift)
iimg = np.abs(iimg)

# 显示原图像和去噪结果
cv2.imshow('noisy image', noisy)
cv2.imshow('denoised image', iimg)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这个示例中,我们首先读入一幅灰度图像,并添加高斯噪声。使用 np.random.normal()函数可以实现添加随机高斯噪声的过程。接下来,我们对图像执行傅里叶变换并进行频域操作。最后,我们使用逆傅里叶变换将结果转换回空间域并得到去噪后的图像。您可以在代码中看到,我们使用 fshift[crow-30:crow+30,ccol-30:ccol+30]=0将高频分量过滤掉,这可以帮助我们在去除噪声的同时保留图像的清晰度。

边缘检测

傅里叶变换可以用于图像边缘检测。以下是一个简单的示例代码:

import cv2
import numpy as np
from matplotlib import pyplot as plt

# 读入一幅灰度图像
img = cv2.imread('image.png', 0)

# 执行傅里叶变换
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)

# 构建高斯拉普拉斯滤波器
rows, cols = img.shape
crow, ccol = rows // 2, cols // 2
D = 30
n = 10
hpf = np.zeros((rows, cols))
for i in range(rows):
    for j in range(cols):
        hpf[i, j] = 1 - np.exp(-((i - crow) ** 2 + (j - ccol) ** 2) / (2 * D ** 2))
        hpf[i, j] = hpf[i, j] * hpf[i, j]
        hpf[i, j] = 1 - hpf[i, j]
        hpf[i, j] = hpf[i, j] ** n

# 将高斯拉普拉斯滤波器应用于傅里叶变换结果
fshift = fshift * hpf

# 将结果转回空间域
ishift = np.fft.ifftshift(fshift)
iimg = np.fft.ifft2(ishift)
iimg = np.abs(iimg)

# 显示边缘检测结果
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(iimg, cmap = 'gray')
plt.title('Edges'), plt.xticks([]), plt.yticks([])
plt.show()

这个示例代码与之前的代码有一些类似,但是它有一些不同之处。在这个示例中,我们构建了一个高斯拉普拉斯滤波器,该滤波器可以用于检测图像中的边缘。我们使用 hpf[i,j]=1-np.exp(-((i-crow)**2+(j-ccol)**2)/(2*D**2)) 构建了高斯函数,并在这个函数中加入了幂n,以增加滤波器的锐度。我们将这个滤波器应用于傅里叶变换的结果中,然后使用逆傅里叶变换将其转换回空间域。最后,我们使用 plt.imshow()函数将边缘检测的结果显示出来。您可能想要调整滤波器中的参数以获取更好的边缘检测结果。

前景提取

傅里叶变换可以用于图像分割和前景提取。以下是一个简单的示例代码:

import cv2
import numpy as np

# 读入一幅彩色图像
img = cv2.imread('image.png')

# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 执行傅里叶变换
f = np.fft.fft2(gray)
fshift = np.fft.fftshift(f)

# 构建带通滤波器,保留图像中心和四个角的高频分量
rows, cols = img.shape[:2]
crow, ccol = rows // 2, cols // 2
mask = np.zeros_like(gray)
mask[crow - 30:crow + 30, ccol - 30:ccol + 30] = 1
mask[:30, :30] = 1
mask[:30, cols - 30:] = 1
mask[rows - 30:, :30] = 1
mask[rows - 30:, cols - 30:] = 1

# 将带通滤波器应用于傅里叶变换结果
fshift = fshift * mask

# 将结果转回空间域
ishift = np.fft.ifftshift(fshift)
iimg = np.fft.ifft2(ishift)
iimg = np.abs(iimg)
iimg = cv2.normalize(iimg, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)

# 使用二值化将背景变为黑色,前景变为白色
ret, thresh = cv2.threshold(iimg, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

# 显示前景提取结果
cv2.imshow('input image', img)
cv2.imshow('foreground', thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这个示例代码中,我们读入了一幅彩色图像,并将其转换为灰度图像。接下来,我们对灰度图像执行傅里叶变换,并使用一个自定义带通滤波器保留了图像中心和四个角的高频分量。我们将过滤器应用于傅里叶变换的结果中,然后使用逆傅里叶变换将其转换回空间域。最后,我们使用二值化将背景变为黑色,前景变为白色,从而得到前景提取的结果。您可以看到,在代码中,我们使用 mask[crow-30:crow+30,ccol-30:ccol+30]=1创建了一个带通滤波器,并使用 ret,thresh=cv2.threhold(iimg,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)将结果二值化。

结论

在本文中,我们介绍了如何使用OpenCV Python对图像进行傅里叶变换,并演示了傅里叶变换的一些应用,例如图像去噪、边缘检测和前景提取。虽然傅里叶变换在数字图像处理中有广泛的应用,但是理解它的数学原理并不容易。希望本文能够帮助您更好地理解和应用傅里叶变换。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程

Python OpenCV