数字图像处理关于傅立叶变换的小记

数字图像处理关于傅里叶变换的小记

文章目录

  • 数字图像处理关于傅里叶变换的小记
    • 背景
    • 复数
    • 傅里叶级数
      • 频域与时域
      • 复数形式的傅里叶级数的证明
    • 傅立叶变换与傅立叶逆变换
      • 一维离散傅立叶变换
      • 二维离散傅立叶变换
        • 时间消耗
    • 冲激
    • 卷积
      • 卷积的求法(利用傅立叶变换)
    • Nyquist采样定理
    • 图像的内插和重采样

背景

傅里叶级数得名于法国数学家约瑟夫·傅里叶(1768年–1830年),他提出任何周期函数都可以展开为三角级数。此前数学家如拉格朗日等已经找到了一些非周期函数的三角级数展开,而认定一个函数有三角级数展开之后,通过积分方法计算其系数的公式,欧拉、达朗贝尔和克莱罗早已发现,傅里叶的工作得到了丹尼尔·伯努利的赞助。傅里叶介入三角级数用来解热传导方程,其最初论文在1807年经拉格朗日、拉普拉斯和勒让德评审后被拒绝出版,他的现在被称为傅里叶逆转定理的理论后来发表于1820年的《热的解析理论》中。将周期函数分解为简单振荡函数的总和的最早想法,可以追溯至公元前3世纪古代天文学家的均轮和本轮学说。

傅里叶级数在数论、组合数学、信号处理、概率论、统计学、密码学、声学、光学等领域都有着广泛的应用。

傅里叶在这个领域的贡献是,他指出任何周期函数都可以表示为不同频率的正弦和/或余弦函数之后的形式,每一个正弦项和/或余弦都乘以不同的系数,无论函数多么复杂,只要它是周期性的,并且满足一些适度的数学条件,都可以用这样的和来表示。即任何周期函数,都可以看作是不同振幅,不同相位正弦波的叠加。甚至非周期函数(但该曲线的面积是有限的情况下)也可用正弦和/或余弦乘以加权函数的积分来表示。

傅里叶变换原来就是一种变换而已,只是这种变换是从时间转换为频率的变化

数字图像处理关于傅立叶变换的小记_第1张图片

参考链接 https://zh.wikipedia.org/wiki/%E5%82%85%E9%87%8C%E5%8F%B6%E7%BA%A7%E6%95%B0

https://www.cnblogs.com/h2zZhou/articles/8405717.html

复数

数字图像处理关于傅立叶变换的小记_第2张图片

∣ Z ∣ = x 2 + y 2 |Z|=\sqrt{x^2+y^2} Z=x2+y2
Z =|Z|(cosθ+jsinθ)

e=cosθ+jsinθ

则可得:θ

import math
print(math.acos(1/math.sqrt(5)))

输出

1.1071487177940904

傅里叶级数

频域与时域

数字图像处理关于傅立叶变换的小记_第3张图片

数字图像处理关于傅立叶变换的小记_第4张图片

数字图像处理关于傅立叶变换的小记_第5张图片

数字图像处理关于傅立叶变换的小记_第6张图片

傅立叶变换,傅里叶级数和频谱

复数形式的傅里叶级数的证明




数字图像处理关于傅立叶变换的小记_第7张图片

傅立叶变换与傅立叶逆变换

一维离散傅立叶变换

数字图像处理关于傅立叶变换的小记_第8张图片

# 单变量的离散傅立叶变换 P138
import numpy as np


def DFT(x):
    M = np.size(x)
    new_x = np.zeros((M, ), dtype=np.complex)
    for n in range(0, M):
        for m in range(0, M):
            new_x[n] += x[m]*np.exp(-2j*np.pi*m*n/M)

    return new_x

x = np.random.rand(1024, )
x1 = DFT(x)
x2 = np.fft.fft(x)
print("x1", x1)
print("x2", x2)
print('Is DFT close to fft?', np.allclose(x1, x2, 1e-12))

二维离散傅立叶变换

# 二维离散傅立叶变换
import numpy
import cv2 as cv
import time


def FFT_v1(Img, Wr):
    if Img.shape[0] == 2:
        pic = numpy.zeros([2], dtype=complex)
        pic = pic * (1 + 0j)
        pic[0] = Img[0] + Img[1] * Wr[0]
        pic[1] = Img[0] - Img[1] * Wr[0]
        return pic
    else:
        pic = numpy.empty([Img.shape[0]], dtype=complex)
        pic[0:Img.shape[0] // 2] = FFT_v1(Img[::2], Wr[::2]) + Wr * FFT_v1(Img[1::2], Wr[::2])
        pic[Img.shape[0] // 2:Img.shape[0]] = FFT_v1(Img[::2], Wr[::2]) - Wr * FFT_v1(Img[1::2], Wr[::2])
        return pic


def FFT_1d(Img):
    Wr = numpy.ones([Img.shape[0] // 2]) * [
        numpy.cos(2 * numpy.pi * i / Img.shape[0]) - 1j * numpy.sin(2 * numpy.pi * i / Img.shape[0]) for i in
        numpy.arange(Img.shape[0] / 2)]
    return FFT_v1(Img, Wr)


def FFT_2d(Img):
    pic = numpy.zeros([Img.shape[0], Img.shape[1]], dtype=complex)
    for i in numpy.arange(Img.shape[0]):
        pic[:, i] = FFT_1d(Img[:, i])
    for i in numpy.arange(Img.shape[1]):
        pic[i, :] = FFT_1d(pic[i, :])
    return pic


if __name__ == "__main__":
    array = numpy.zeros([512], dtype=complex)

    img = cv.imread('p1.jpg', 0)

    print("numpy.fft.fft2()函数计算结果:")
    t_s1 = time.time()
    a=numpy.fft.fft2(img)
    print(a)
    t_e1 = time.time()
    print("计算时间:" + str(t_e1 - t_s1))

    print("FFT_2d()函数的计算结果:")
    t_s2 = time.time()
    b=FFT_2d(img)
    print(b)
    t_e2 = time.time()
    print("计算时间:" + str(t_e2 - t_s2))
    print(a == b)
    print(numpy.allclose(a, b), 1e-12)

时间消耗
import time
import numpy
import matplotlib.pyplot as pyplot


def DFT(x):
    N = numpy.size(x)
    X = numpy.zeros((N,),dtype=numpy.complex128)
    for m in range(0,N):
        for n in range(0,N):
            X[m] += x[n]*numpy.exp(-numpy.pi*2j*m*n/N)
    return X

dft_time = []
fft_time = []
n_series = []
for N in numpy.power(2,range(1,11)):
    print(N)
    x = numpy.ones((N,))

    t0 = time.time()
    for pp in range(0,2):
        X = DFT(x)
    print(X)
    t1 = (time.time()-t0)/2.0

    t0 = time.time()
    for pp in range(0,2):
        Y = numpy.fft.fft(x)
    t2 = (time.time()-t0)/2.0

    n_series.append(N)
    dft_time.append(t1)
    fft_time.append(t2)

line_dft, = pyplot.plot(n_series, dft_time, label='DFT')
line_fft, = pyplot.plot(n_series, fft_time,'r',label='FFT')
pyplot.legend(handles=[line_dft, line_fft])
pyplot.ylabel('times(second)')
pyplot.xlabel('N')

pyplot.show()
print(dft_time)
print(fft_time)
print(numpy.allclose(X, Y), 1e-12)
print(X == Y)

数字图像处理关于傅立叶变换的小记_第9张图片
数字图像处理关于傅立叶变换的小记_第10张图片

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


img = cv.imread('t1.png', 0)

plt.subplot(131)
plt.title("original")
plt.axis('off')
plt.imshow(img, cmap='gray')

f = np.fft.fft2(img)  # 快速傅里叶变换算法得到频率分布
fshift = np.fft.fftshift(f)  # 默认结果中心点位置是在左上角,调用fftshift()函数转移到中间位置
fimg = np.log(np.abs(fshift))  # fft结果是复数, 其绝对值结果是振幅,频谱对数变换,取对数放大波动

#展示结果
plt.subplot(132)
plt.title('Fourier Fourier')
plt.axis('off')
plt.imshow(fimg, 'gray')


# 傅立叶逆变换
plt.subplot(133)
ifshift = np.fft.ifftshift(fshift)
iimg = np.fft.ifft2(ifshift)
iimg = np.abs(iimg)
plt.axis('off')
plt.title('Inverse Fourier Image')
plt.imshow(iimg, 'gray')

plt.savefig('test0.png')
plt.show()

数字图像处理关于傅立叶变换的小记_第11张图片

左边为原始图像,中间为频率分布图谱,其中越靠近中心位置频率越低,越亮(灰度值越高)的位置代表该频率的信号振幅越大,右边为傅立叶逆变换得到的图像。

#计算一维傅里叶变换
numpy.fft.fft(a, n=None, axis=-1, norm=None)
#计算二维的傅里叶变换
numpy.fft.fft2(a, n=None, axis=-1, norm=None)
#计算n维的傅里叶变换
numpy.fft.fftn()
#计算n维实数的傅里叶变换
numpy.fft.rfftn()
#返回傅里叶变换的采样频率
numpy.fft.fftfreq()
#将FFT输出中的直流分量移动到频谱中央
numpy.fft.shift()
#实现图像逆傅里叶变换,返回一个复数数组
numpy.fft.ifft2(a, n=None, axis=-1, norm=None)
#fftshit()函数的逆函数,它将频谱图像的中心低频部分移动至左上角
numpy.fft.fftshift()
#将复数转换为0至255范围
iimg = numpy.abs(逆傅里叶变换结果)

冲激

数字图像处理关于傅立叶变换的小记_第12张图片
数字图像处理关于傅立叶变换的小记_第13张图片

以一个面积为1的三角形为例,底边不断收缩,当底边a->0时,高->∞

数字图像处理关于傅立叶变换的小记_第14张图片
数字图像处理关于傅立叶变换的小记_第15张图片

卷积

数字图像处理关于傅立叶变换的小记_第16张图片
数字图像处理关于傅立叶变换的小记_第17张图片
数字图像处理关于傅立叶变换的小记_第18张图片
数字图像处理关于傅立叶变换的小记_第19张图片数字图像处理关于傅立叶变换的小记_第20张图片数字图像处理关于傅立叶变换的小记_第21张图片数字图像处理关于傅立叶变换的小记_第22张图片

卷积的求法(利用傅立叶变换)

卷积与傅里叶变换有着密切的关系。例如两函数的傅里叶变换的乘积等于它们卷积后的傅里叶变换,利用此一性质,能简化傅里叶分析中的许多问题。
数字图像处理关于傅立叶变换的小记_第23张图片

Nyquist采样定理

象一个白色的圆盘,有一条沿着半径的黑线,圆盘以角速度[公式]旋转。
你以一定的周期拍照,就是采样。
你拍照的频率恰好为圆盘自转频率两倍的时候,你的照片里黑线的位置,永远是下一张和上一张呈180度,看不出圆盘原来到底是顺时针转的还是逆时针转的。

图像的内插和重采样

# 最近邻内插算法

import cv2 as cv
import numpy as np

img = cv.imread("Fig0417(a)(barbara).tif", 0)
height, width = img.shape
fx = 0.5
fy = 0.5

new_height = int(fx*height)
new_width = int(fy*width)
new_img = np.zeros((new_height, new_width), dtype=np.uint8)

for i in range(height):
    for j in range(width):
        new_i = int(fx*i)
        new_j = int(fy*j)
        new_img[new_i, new_j] = img[i, j]

new_img1 = cv.resize(img, (0, 0), fx=0.5, fy=0.5, interpolation=cv.INTER_NEAREST)
new_img2 = cv.resize(new_img1, (0, 0), fx=2, fy=2, interpolation=cv.INTER_NEAREST)
new_img3 = cv.resize(new_img, (0, 0), fx=2, fy=2, interpolation=cv.INTER_NEAREST)

while 1:
    cv.imshow("img", img)
    cv.imshow('new_img', new_img)
    cv.imshow('new_img1', new_img1)
    cv.imshow('new_img2', new_img2)
    cv.imshow('new_img3', new_img3)
    if cv.waitKey(1) == 27:
        break

数字图像处理关于傅立叶变换的小记_第24张图片

数字图像处理关于傅立叶变换的小记_第25张图片

数字图像处理关于傅立叶变换的小记_第26张图片
数字图像处理关于傅立叶变换的小记_第27张图片
数字图像处理关于傅立叶变换的小记_第28张图片

# 双线性内插法
import cv2 as cv
import numpy as np
import time


def resize(src, fx, fy):
    src_h, src_w = src.shape[:2]
    dst_w, dst_h = int(src_w*fx), int(src_h*fy)
    if fx == 1 and fy == 1:
        return src.copy()

    # 遍历目标图像,插值
    dst = np.zeros((dst_h, dst_w, 3), dtype=np.uint8)
    for n in range(3):  # 对channel循环
        for dst_y in range(dst_h):  # 对height循环
            for dst_x in range(dst_w):  # 对width循环
                # 目标在源上的坐标
                src_x = (dst_x + 0.5) / fx - 0.5
                src_y = (dst_y + 0.5) / fy - 0.5
                # 计算在源图上四个近邻点的位置
                src_x_0 = int(np.floor(src_x))
                src_y_0 = int(np.floor(src_y))
                src_x_1 = min(src_x_0 + 1, src_w - 1)
                src_y_1 = min(src_y_0 + 1, src_h - 1)

                # 双线性插值
                value0 = (src_x_1 - src_x) * src[src_y_0, src_x_0, n] + (src_x - src_x_0) * src[src_y_0, src_x_1, n]
                value1 = (src_x_1 - src_x) * src[src_y_1, src_x_0, n] + (src_x - src_x_0) * src[src_y_1, src_x_1, n]
                dst[dst_y, dst_x, n] = int((src_y_1 - src_y) * value0 + (src_y - src_y_0) * value1)
    return dst


if __name__ == '__main__':
    img = cv.imread('Fig0417(a)(barbara).tif')
    start = time.time()
    img_out = resize(img, fx=0.5, fy=0.5)
    img_out0 = cv.resize(img, (0, 0), fx=0.5, fy=0.5, interpolation=cv.INTER_LINEAR_EXACT)
    print('cost '+str(time.time() - start)+' seconds')

    while 1:
        cv.imshow('src_image', img)
        cv.imshow('dst_image', img_out)
        cv.imshow('dst_image0', img_out0)

        if cv.waitKey(1) == 27:
            break

数字图像处理关于傅立叶变换的小记_第29张图片

数字图像处理关于傅立叶变换的小记_第30张图片
数字图像处理关于傅立叶变换的小记_第31张图片

参考
傅立叶变换,傅立叶序列以及频谱
傅立叶级数
深入浅出的讲解傅里叶变换(真正的通俗易懂)
numpy.fft.fft

你可能感兴趣的:(数字图像处理)