【千律】OpenCV基础:离散傅里叶变换

环境:Python3.8 和 OpenCV

内容:一维离散傅里叶变换和二维离散傅里叶变换

傅里叶变换和傅里叶反变换:

【千律】OpenCV基础:离散傅里叶变换_第1张图片

一维傅里叶变换后,除去初始点,其余各点满足:

(1)实部的点对称

(2)虚部的点反对称

(3)幅值(模长)的点对称

因此,可以得到F(u) 和 F(M - u) 两点共轭。

一维离散傅里叶变换:

实现方式1:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt


if __name__ == '__main__':

    # 绘制方波信号
    M = 100            # 信号长度
    fx = np.zeros(M)   #
    fx[30: 70] = 1     # 方波信号

    # 傅里叶变换
    x = np.arange(0, M)
    Fu = np.zeros(M, np.complex128)
    for u in range(M):
        Re = np.sum(fx * np.cos(-2 * np.pi * u * x / M))
        Im = np.sum(fx * np.sin(-2 * np.pi * u * x / M))
        Fu[u] = Re + 1j * Im

    # 傅里叶反变换
    u = np.arange(0, M)
    Fx = np.zeros(M, np.complex128)
    for x in range(M):
        Re = np.sum(Fu * np.cos(2 * np.pi * u * x / M))
        Im = np.sum(Fu * np.sin(2 * np.pi * u * x / M))
        Fx[x] = Re + 1j * Im

    # 解决中文乱码
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False

    # 绘制结果
    plt.plot(fx, 'r-', label='原始信号')
    plt.plot(np.real(Fu), 'b-', label='傅里叶变换实部')
    plt.plot(np.real(Fx), 'k-', label='反傅里叶变换实部')
    plt.legend()
    plt.xlim([0, 100])
    plt.show()

实现方式2:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt


if __name__ == '__main__':

    # 绘制方波信号
    M = 100            # 信号长度
    fx = np.zeros(M)   #
    fx[30: 70] = 1     # 方波信号

    # 傅里叶变换
    x = np.arange(0, M)
    Fu = np.zeros(M, np.complex128)
    for u in range(M):
        Fu[u] = np.sum(fx * np.exp(-2j * np.pi * u * x / M))

    # 傅里叶反变换
    u = np.arange(0, M)
    Fx = np.zeros(M, np.complex128)
    for x in range(M):
        Fx[x] = np.sum(Fu * np.exp(2j * np.pi * u * x / M))

    # 解决中文乱码
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False

    # 绘制结果
    plt.plot(fx, 'r-', label='原始信号')
    plt.plot(np.real(Fu), 'b-', label='傅里叶变换实部')
    plt.plot(np.real(Fx), 'k-', label='反傅里叶变换实部')
    plt.legend()
    plt.xlim([0, 100])
    plt.show()

二维离散傅里叶变换:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt


if __name__ == '__main__':

    # 读取灰度图片
    img_lenna = cv.imread('lenna.png', 0)

    # 二维离散傅里叶变换
    img_fft = np.fft.fft2(img_lenna)

    # 傅里叶变换的平移
    img_ffts = np.fft.fftshift(img_fft)

    # 获取变换后的振幅谱和相位谱
    Amp = np.abs(img_ffts)
    Ang = np.angle(img_ffts)

    # 显示振幅谱和相位谱
    plt.figure()
    plt.subplot(121)
    plt.imshow(np.log(Amp + 1), cmap='jet')
    plt.subplot(122)
    plt.imshow(Ang, cmap='jet')
    plt.show()

    # 恢复成原图像
    img_lenna_re1 = np.abs(np.fft.ifft2(img_fft))
    img_lenna_re2 = np.abs(np.fft.ifft2(img_ffts))

    # 显示恢复结果
    plt.figure()
    plt.subplot(121)
    plt.imshow(img_lenna_re1, cmap='gray')
    plt.subplot(122)
    plt.imshow(img_lenna_re2, cmap='gray')
    plt.show()

基于傅里叶变换的图像融合 :

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt


# 封装图片显示函数
def image_show(image):
    if image.ndim == 2:
        plt.imshow(image, cmap='gray')
    else:
        image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
        plt.imshow(image)
    plt.show()


if __name__ == '__main__':

    # 读取图像
    img_desk = cv.imread('desk.png', 0)
    img_lenna = cv.imread('lenna.png', 0)

    # 图像裁剪
    img_desk_crap = img_desk[:500, :500]

    # 二维离散傅里叶变换
    desk_fft = np.fft.fft2(img_desk_crap)
    lenna_fft = np.fft.fft2(img_lenna)

    # 获取幅值谱和相位谱
    Desk_Amp, Desk_Ang = np.abs(desk_fft), np.angle(desk_fft)
    Lenna_Amp, Lenna_Ang = np.abs(lenna_fft), np.angle(lenna_fft)

    # 图像融合
    Fu_A = Desk_Amp * np.cos(Lenna_Ang) + Desk_Amp * np.sin(Lenna_Ang)
    Fu_B = Lenna_Amp * np.cos(Desk_Ang) + Lenna_Amp * np.sin(Desk_Ang)

    # 傅里叶反变换
    img_desk_rec = np.fft.ifft2(Fu_A)
    img_Lenna_rec = np.fft.ifft2(Fu_B)

    # 显示结果
    image_show(np.abs(img_desk_rec))
    image_show(np.abs(img_Lenna_rec))

你可能感兴趣的:(OpenCV基础,opencv,人工智能,python)