傅里叶级数得名于法国数学家约瑟夫·傅里叶(1768年–1830年),他提出任何周期函数都可以展开为三角级数。此前数学家如拉格朗日等已经找到了一些非周期函数的三角级数展开,而认定一个函数有三角级数展开之后,通过积分方法计算其系数的公式,欧拉、达朗贝尔和克莱罗早已发现,傅里叶的工作得到了丹尼尔·伯努利的赞助。傅里叶介入三角级数用来解热传导方程,其最初论文在1807年经拉格朗日、拉普拉斯和勒让德评审后被拒绝出版,他的现在被称为傅里叶逆转定理的理论后来发表于1820年的《热的解析理论》中。将周期函数分解为简单振荡函数的总和的最早想法,可以追溯至公元前3世纪古代天文学家的均轮和本轮学说。
傅里叶级数在数论、组合数学、信号处理、概率论、统计学、密码学、声学、光学等领域都有着广泛的应用。
傅里叶在这个领域的贡献是,他指出任何周期函数都可以表示为不同频率的正弦和/或余弦函数之后的形式,每一个正弦项和/或余弦都乘以不同的系数,无论函数多么复杂,只要它是周期性的,并且满足一些适度的数学条件,都可以用这样的和来表示。即任何周期函数,都可以看作是不同振幅,不同相位正弦波的叠加。甚至非周期函数(但该曲线的面积是有限的情况下)也可用正弦和/或余弦乘以加权函数的积分来表示。
傅里叶变换原来就是一种变换而已,只是这种变换是从时间转换为频率的变化
参考链接 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
∣ Z ∣ = x 2 + y 2 |Z|=\sqrt{x^2+y^2} ∣Z∣=x2+y2
Z =|Z|(cosθ+jsinθ)
ejθ=cosθ+jsinθ
则可得:θ
import math
print(math.acos(1/math.sqrt(5)))
输出
1.1071487177940904
傅立叶变换,傅里叶级数和频谱
# 单变量的离散傅立叶变换 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)
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()
左边为原始图像,中间为频率分布图谱,其中越靠近中心位置频率越低,越亮(灰度值越高)的位置代表该频率的信号振幅越大,右边为傅立叶逆变换得到的图像。
#计算一维傅里叶变换
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(逆傅里叶变换结果)
以一个面积为1的三角形为例,底边不断收缩,当底边a->0时,高->∞
卷积与傅里叶变换有着密切的关系。例如两函数的傅里叶变换的乘积等于它们卷积后的傅里叶变换,利用此一性质,能简化傅里叶分析中的许多问题。
象一个白色的圆盘,有一条沿着半径的黑线,圆盘以角速度[公式]旋转。
你以一定的周期拍照,就是采样。
你拍照的频率恰好为圆盘自转频率两倍的时候,你的照片里黑线的位置,永远是下一张和上一张呈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
# 双线性内插法
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
参考
傅立叶变换,傅立叶序列以及频谱
傅立叶级数
深入浅出的讲解傅里叶变换(真正的通俗易懂)
numpy.fft.fft