OpenCV-Python图像傅里叶变换Numpy实现

理论基础

图像处理一般分为空间域处理和频率域处理。

空间域处理是直接对图像内的像素进行处理。空间域处理主要划分为灰度变换和空间滤波两种形式。灰度变换是对图像内的单个像素进行处理,比如调节对比度和处理阈值等。空间滤波涉及图像质量的改变,例如图像平滑处理。空间域处理的计算简单方便,运算速度更快。

频率域处理是先将图像变换到频率域,然后在频率域对图像进行处理,最后再通过反变换将图像从频率域变换到空间域。傅里叶变换是应用最广泛的一种频域变换,它能够将图像从空间域变换到频率域,而逆傅里叶变换能够将频率域信息变换到空间域内。傅里叶变换在图像处理领域内有着非常重要的作用。

实现傅里叶变换

Numpy 提供的实现傅里叶变换的函数是 numpy.fft.fft2(),它的语法格式是:

返回值 = numpy.fft.fft2(原始图像)

这里需要注意的是,参数“原始图像”的类型是灰度图像,函数的返回值是一个复数数组(complex ndarray)。

经过该函数的处理,就能得到图像的频谱信息。此时,图像频谱中的零频率分量位于频谱图像(频域图像)的左上角,为了便于观察,通常会使用numpy.fft.fftshift()函数将零频率成分移动到频域图像的中心位置。

函数 numpy.fft.fftshift()的语法格式是:

返回值=numpy.fft.fftshift(原始频谱)
在这里插入图片描述
对图像进行傅里叶变换后,得到的是一个复数数组。为了显示为图像,需要将它们的值调整到[0, 255]的灰度空间内,使用的公式为:

像素新值=20*np.log(np.abs(频谱值))

import cv2
import  numpy as np
import  matplotlib.pyplot as plt
img = cv2.imread('images/lena.jpg',0)

f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
magnitude_spectrum = 20*np.log(np.abs(fshift))
plt.subplot(121)
plt.imshow(img, cmap = 'gray')
plt.title('original')
plt.axis('off')
plt.subplot(122)
plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('result')
plt.axis('off')
plt.show()

在这里插入图片描述

实现逆傅里叶变换

  1. 在傅里叶变换过程中使用了 numpy.fft.fftshift()函数移动零频率分量,那么在逆傅里叶变换过程中,需要先使用 numpy.fft.ifftshift() 函数将零频率分量移到原来的位置,再进行逆傅里叶变换

    调整后的频谱 = numpy.fft.ifftshift(原始频谱)
    在这里插入图片描述

  2. numpy.fft.ifft2() 函数可以实现逆傅里叶变换

    返回值=numpy.fft.ifft2(频域数据)

  3. 将该信息调整至[0, 255]灰度空间内

    iimg = np.abs(逆傅里叶变换结果)

import cv2
import  numpy as np
import  matplotlib.pyplot as plt
img = cv2.imread('images/lena.jpg',0)

f = np.fft.fft2(img)

fshift = np.fft.fftshift(f)

ishift = np.fft.ifftshift(fshift)
iimg = np.fft.ifft2(ishift)
print(img)
iimg = np.abs(iimg)
# magnitude_spectrum = 20*np.log(np.abs(fshift))

plt.subplot(121)
plt.imshow(img, cmap = 'gray')
plt.title('original')
plt.axis('off')
plt.subplot(122)
plt.imshow(iimg, cmap = 'gray')
plt.title('result')
plt.axis('off')
plt.show()

在这里插入图片描述

滤波

在一幅图像内,同时存在着高频信号和低频信号。

  • 低频信号对应图像内变化缓慢的灰度分量。例如,在一幅大草原的图像中,低频信号对应着颜色趋于一致的广袤草原。
  • 高频信号对应图像内变化越来越快的灰度分量,是由灰度的尖锐过渡造成的。如果在上面的大草原图像中还有一头狮子,那么高频信号就对应着狮子的边缘等信息。

滤波器能够允许一定频率的分量通过或者拒绝其通过,按照其作用方式可以划分为低通滤波器和高通滤波器。

  • 允许低频信号通过的滤波器称为低通滤波器。低通滤波器使高频信号衰减而对低频信号 放行,会使图像变模糊。
  • 允许高频信号通过的滤波器称为高通滤波器。高通滤波器使低频信号衰减而让高频信号 通过,将增强图像中尖锐的细节,但是会导致图像的对比度降低。
    在这里插入图片描述

低频信号位于图的中心位置

  • 实现高通滤波,将傅里叶变换结果图像中的低频分量值都替换为0(处理为黑色)。图中间的像素值都置零,需要先计算其中心位置的坐标,然后选取以该坐标为中心,上下左右各 30个像素大小的区域,将这个区域内的像素值置零。
  • 实现低通滤波,将傅里叶变换结果图像中的高频信号值都替换为0(处理为黑色),就屏蔽了高频信号,只保留低频信号。需要构造一个下图中左图所示的图像,用它与原图的傅里叶变换频谱图像进行与运算,就能将频谱图像中的高频信号过滤掉。

在这里插入图片描述

高通滤波
import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('images/lena.jpg',0)

img_float32 = np.float32(img)

f = np.fft.fft2(img)

fshift = np.fft.fftshift(f)

rows, cols = img.shape
crow, ccol = int(rows/2) , int(cols/2)     # 中心位置

# 高通滤波
mask = np.ones((rows, cols), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 0
# print(fshift.shape)
fshift = fshift*mask

f_ishift = np.fft.ifftshift(fshift)

img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back)

plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Result'), plt.xticks([]), plt.yticks([])

plt.show()

在这里插入图片描述

低通滤波
import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('images/lena.jpg',0)

img_float32 = np.float32(img)

f = np.fft.fft2(img)

fshift = np.fft.fftshift(f)

rows, cols = img.shape
crow, ccol = int(rows/2) , int(cols/2)     # 中心位置

# 低通滤波
mask = np.zeros((rows, cols), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1

# IDFT
fshift = fshift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back)

plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Result'), plt.xticks([]), plt.yticks([])

plt.show()

在这里插入图片描述

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您解答这个问题。首先,对于图像加水印,我们可以使用傅里叶变换FFT)来实现傅里叶变换可以将图像从空间域转换到频域,使得我们可以对其进行频域操作,例如在频域中添加水印。接下来,我将为您提供一个Python示例代码,演示如何使用OpenCVFFT函数来实现图像加水印。 ``` import cv2 import numpy as np # 加载图像 img = cv2.imread("lena.png", cv2.IMREAD_GRAYSCALE) # 获取图像尺寸 rows, cols = img.shape # 傅里叶变换 f = np.fft.fft2(img) # 移动零频分量到频谱中心 fshift = np.fft.fftshift(f) # 创建水印 watermark = np.zeros((rows, cols), dtype=np.uint8) cv2.putText(watermark, "Watermark", (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, 255) # 将水印转换为频域 w = np.fft.fft2(watermark) # 移动零频分量到频谱中心 wshift = np.fft.fftshift(w) # 将水印添加到图像中 fwatermark = fshift + 0.1 * wshift # 移动零频分量回到左上角 fwatermarkshift = np.fft.ifftshift(fwatermark) # 反傅里叶变换 iwatermark = np.fft.ifft2(fwatermarkshift) # 取实部 iwatermark = np.real(iwatermark) # 将结果转换为0-255的灰度图像 iwatermark = cv2.normalize(iwatermark, dst=None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U) # 显示结果 cv2.imshow("Original Image", img) cv2.imshow("Watermarked Image", iwatermark) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在这个示例中,我们首先加载了一张灰度图像,并对其进行了傅里叶变换。然后,我们创建了一个水印图像,并将其转换为频域。接下来,我们将水印添加到原始图像的频域表示中,并将结果转换回空间域。最后,我们显示了原始图像和添加水印后的图像。 请注意,这个示例只是演示了如何使用傅里叶变换来添加水印。在实际应用中,可能需要采用更复杂的算法来保证水印的鲁棒性和不可见性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值