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


文章目录

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


背景

傅里叶级数得名于法国数学家约瑟夫·傅里叶(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 mathprint(math.acos(1/math.sqrt(5)))

输出

1.1071487177940904

傅里叶级数

频域与时域


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


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





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

一维离散傅立叶变换

# 单变量的离散傅立叶变换 P138import numpy as npdef 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_xx = 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 numpyimport cv2 as cvimport timedef 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 picelse: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 picdef 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 innumpy.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 picif __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 timeimport numpyimport matplotlib.pyplot as pyplotdef 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 Xdft_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.0t0 = time.time()for pp in range(0,2):Y = numpy.fft.fft(x)t2 = (time.time()-t0)/2.0n_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 cvimport numpy as npimport matplotlib.pyplot as pltimport timeimg = 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时,高->∞


卷积




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

卷积与傅里叶变换有着密切的关系。例如两函数的傅里叶变换的乘积等于它们卷积后的傅里叶变换,利用此一性质,能简化傅里叶分析中的许多问题。

Nyquist采样定理

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

图像的内插和重采样

# 最近邻内插算法import cv2 as cvimport numpy as npimg = cv.imread("Fig0417(a)(barbara).tif", 0)height, width = img.shapefx = 0.5fy = 0.5new_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 cvimport numpy as npimport timedef 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.5src_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 dstif __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


©著作权归作者所有:来自51CTO博客作者谁唱江南断肠句的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 【直观详解】什么是PCA、SVD
  2. 矩阵的乘法运算与css的3d变换(transform)
  3. Android(安卓)ApiDemos示例解析(78):Graphics->ScaleToFit
  4. Android图像处理(三)通过矩阵变换实现图像变形特效
  5. 移动架构39_RxAndroid二(变换调用:map、flatMap、lift、compose)
  6. Android(安卓)EditText 下换线颜色变换
  7. Android图片处理(Matrix,ColorMatrix) -
  8. Android变形矩阵——Matrix
  9. Android(安卓)OpenCV(十一):图像仿射变换

随机推荐

  1. 查询下拉框只显示年份(jquery年份插件)
  2. jQuery serialize()在IE中不使用ajax加载
  3. 解析jquery实现回车键提交表单
  4. jquery中的Datepicker控件如何默认显示日
  5. 在某个点停止固定位置滚动?
  6. 使用jquery tablesorter插件,有一个选中项
  7. js是否为空判断大全
  8. 如何使用jQuery选择列表中的最后X项?
  9. jquery为属性过滤器动态添加值?
  10. jQuery Datatable(V1.10.7) server side pr