傅里叶变换源代码-《医学图像处理》小作业四-Python代码/Matlab代码

天津中医药大学-20级医学信息工程   教师:王翌   学生:邓集亲

声明:本文章中所涉及的代码并非我个人独立完成的成果。

        在撰写的过程中,我广泛地吸取了前一辈人,尤其是学长学姐们的宝贵学习经验。通过深入研究他们的学习轨迹,以及查阅和分析了众多相关的理论文献与资料,并在王老师的悉心指导下,经过反复的实验、调试与优化,最终得以总结完成本文所展现的代码。

        建议各位学弟学妹们,先根据王老师的授课内容,独立思考一下应该如何完成。如果实在是有理解上的困难,不知道从何下手,再来学习和参考本文。

        学长我是用Python写的,如果你使用MATLAB,同样可以参考此代码进行翻译。我在代码中加入了许多注释和测试环节,以便于理解。由于学长能力有限,代码中或许存在一些疏漏或错误,请批判性地参考。

实验四:FFT变换

作业要求:

  1. 参考“傅里叶变换”课的内容,对输入图像进行快速傅里叶变换。
  2. 通过傅里叶逆变换,还原出原图片。

实验图片:

fft.tif,再自选其它至少20张图片(包括灰度图片和彩色图片)。

  傅里叶变换用于分析图像的频率特性,对采样的离散信号进行傅里叶变换,得到周期性的NDFT。可以将图像视为在两个方向上采样的信号。因此,在XY方向都进行傅立叶变换,可以得到图像的频率表示。

  更直观地说,对于正弦信号,如果幅度在短时间内变化很快,则可以说它是高频信号。如果变化缓慢,则为低频信号。

  将相同的想法扩展到图像。图像中的振幅在哪里急剧变化?在边缘点或噪声。因此,可以说边缘和噪声是图像中的高频内容。如果幅度没有太大变化,则它是低频分量。

  在图像处理中,频域反应了图像在空域灰度变化剧烈程度,也就是图像灰度的变化速度,也就是图像的梯度大小。也就是说,傅立叶变换提供另外一个角度来观察图像, 可以将图像从灰度分布转化到频率分布上来观察图像的特征。书面一点说就是,傅里叶变换提供了一条从空域到频率自由转换的途径。

  经过傅里叶变换后的图像,我们可以得到一张频幅图,图像信息只有频率、幅度、方向。

  同理,逆变换则可以根据频幅图的信息还原原图像。

Windows图片文件目录:

ImageSet文件目录下储存其他待处理图片

Python代码:

#导入库
import cv2 as cv
import numpy as np
from matplotlib import pyplot
from numpy.core import integer, asarray, roll,zeros, swapaxes, take
from numpy.core.multiarray import normalize_axis_index
from numpy.fft import _pocketfft_internal as pfi

#定义函数进行fft变换计算
def raw_fft(a, n, axis, is_real, is_forward, inv_norm):   #为了变换结果,这里需要定义浮点数inv_norm
    axis = normalize_axis_index(axis, a.ndim)
    if n is None:
        n = a.shape[axis]

    fct = 1/inv_norm

    if a.shape[axis] != n:
        s = list(a.shape)
        index = [slice(None)]*len(s)
        if s[axis] > n:
            index[axis] = slice(0, n)
            a = a[tuple(index)]
        else:
            index[axis] = slice(0, s[axis])
            s[axis] = n
            z = zeros(s, a.dtype.char)
            z[tuple(index)] = a
            a = z

    if axis == a.ndim-1:
        r = pfi.execute(a, is_real, is_forward, fct)
    else:
        a = swapaxes(a, axis, -1)
        r = pfi.execute(a, is_real, is_forward, fct)
        r = swapaxes(r, axis, -1)
    return r

def fft_shift(x, axes=None):   #将图像低频部分转移到图像的中心
    x = asarray(x)
    if axes is None:
        axes = tuple(range(x.ndim))
        shift = [dim // 2 for dim in x.shape]
    elif isinstance(axes, integer):
        shift = x.shape[axes] // 2
    else:
        shift = [x.shape[ax] // 2 for ax in axes]
    return roll(x, shift, axes)


def ifft_shift(x, axes=None):   #将图像低频部分移到原来位置
    x = asarray(x)
    if axes is None:
        axes = tuple(range(x.ndim))
        shift = [-(dim // 2) for dim in x.shape]
    elif isinstance(axes, integer):
        shift = -(x.shape[axes] // 2)
    else:
        shift = [-(x.shape[ax] // 2) for ax in axes]
    return roll(x, shift, axes)

def fft(a, n=None, axis=-1):   #定义一维傅里叶变换函数
    a = asarray(a)
    if n is None:
        n = a.shape[axis]
    inv_norm = 1
    output = raw_fft(a, n, axis, False, True, inv_norm)
    return output


def ifft(a, n=None, axis=-1):
    a = asarray(a)
    if n is None:
        n = a.shape[axis]
    inv_norm = n
    output = raw_fft(a, n, axis, False, False, inv_norm)
    return output

def cook_nd_args(a, shape=None, axes=None, invreal=0):
    if shape is None:
        shapeless = 1
        if axes is None:
            shape = list(a.shape)
        else:
            shape = take(a.shape, axes)
    else:
        shapeless = 0
    shape = list(shape)
    if axes is None:
        axes = list(range(-len(shape), 0))
    if invreal and shapeless:
        shape[-1] = (a.shape[axes[-1]] - 1) * 2
    return shape, axes


def raw_fftnd(a, shape=None, axes=None, function=fft):
    a = asarray(a)
    shape, axes = cook_nd_args(a, shape, axes)
    itl = list(range(len(axes)))
    itl.reverse()
    for ii in itl:
        a = function(a, n=shape[ii], axis=axes[ii])
    return a
def imagefft2(a, shape=None, axes=(-2, -1)):   #图片二维傅里叶变换
    return raw_fftnd(a, shape, axes, fft)


def imageifft2(a, shape=None, axes=(-2, -1)):
    return raw_fftnd(a, shape, axes, ifft)


#读取图像

original = cv.imread(r'D:\deng\smalljob\ImageSet\fft.tif')
original_gray = cv.cvtColor(original, cv.COLOR_BGR2GRAY)   #将图像从RGB颜色空间转换到灰度颜色空间

#傅里叶变换

f = imagefft2(original_gray)

fshift = fft_shift(f)   #将变换后图像的低频部分转移到图像的中心

result = np.log(np.abs(fshift)+1e-5)   #改变浮点数的精度为1e-5

#傅里叶逆变换

ishift = ifft_shift(fshift)

iImg = imageifft2(ishift)

iImg = np.abs(iImg)

#展示结果

pyplot.subplot(131),pyplot.imshow(original_gray,cmap='gray')
pyplot.title('original')
pyplot.axis('off')


pyplot.subplot(132),pyplot.imshow(result,cmap='gray')
pyplot.title('fft')
pyplot.axis('off')


pyplot.subplot(133),pyplot.imshow(iImg,cmap='gray')
pyplot.title('ifft')
pyplot.axis('off')
pyplot.show()

运行结果:

以下是对彩色图像进行傅里叶变换,即拆分图像颜色通道,分别进行傅里叶变换

#导入库
import cv2 as cv
import numpy as np
from matplotlib import pyplot
from numpy.core import integer, asarray, roll,zeros, swapaxes, take
from numpy.core.multiarray import normalize_axis_index
from numpy.fft import _pocketfft_internal as pfi

#定义函数进行fft变换计算
def raw_fft(a, n, axis, is_real, is_forward, inv_norm):   #为了变换结果,这里需要定义浮点数inv_norm
    axis = normalize_axis_index(axis, a.ndim)
    if n is None:
        n = a.shape[axis]

    fct = 1/inv_norm

    if a.shape[axis] != n:
        s = list(a.shape)
        index = [slice(None)]*len(s)
        if s[axis] > n:
            index[axis] = slice(0, n)
            a = a[tuple(index)]
        else:
            index[axis] = slice(0, s[axis])
            s[axis] = n
            z = zeros(s, a.dtype.char)
            z[tuple(index)] = a
            a = z

    if axis == a.ndim-1:
        r = pfi.execute(a, is_real, is_forward, fct)
    else:
        a = swapaxes(a, axis, -1)
        r = pfi.execute(a, is_real, is_forward, fct)
        r = swapaxes(r, axis, -1)
    return r

def fft_shift(x, axes=None):   #将图像低频部分转移到图像的中心
    x = asarray(x)
    if axes is None:
        axes = tuple(range(x.ndim))
        shift = [dim // 2 for dim in x.shape]
    elif isinstance(axes, integer):
        shift = x.shape[axes] // 2
    else:
        shift = [x.shape[ax] // 2 for ax in axes]
    return roll(x, shift, axes)


def ifft_shift(x, axes=None):   #将图像低频部分移到原来位置
    x = asarray(x)
    if axes is None:
        axes = tuple(range(x.ndim))
        shift = [-(dim // 2) for dim in x.shape]
    elif isinstance(axes, integer):
        shift = -(x.shape[axes] // 2)
    else:
        shift = [-(x.shape[ax] // 2) for ax in axes]
    return roll(x, shift, axes)

def fft(a, n=None, axis=-1):   #定义一维傅里叶变换函数
    a = asarray(a)
    if n is None:
        n = a.shape[axis]
    inv_norm = 1
    output = raw_fft(a, n, axis, False, True, inv_norm)
    return output


def ifft(a, n=None, axis=-1):
    a = asarray(a)
    if n is None:
        n = a.shape[axis]
    inv_norm = n
    output = raw_fft(a, n, axis, False, False, inv_norm)
    return output

def cook_nd_args(a, shape=None, axes=None, invreal=0):
    if shape is None:
        shapeless = 1
        if axes is None:
            shape = list(a.shape)
        else:
            shape = take(a.shape, axes)
    else:
        shapeless = 0
    shape = list(shape)
    if axes is None:
        axes = list(range(-len(shape), 0))
    if invreal and shapeless:
        shape[-1] = (a.shape[axes[-1]] - 1) * 2
    return shape, axes


def raw_fftnd(a, shape=None, axes=None, function=fft):
    a = asarray(a)
    shape, axes = cook_nd_args(a, shape, axes)
    itl = list(range(len(axes)))
    itl.reverse()
    for ii in itl:
        a = function(a, n=shape[ii], axis=axes[ii])
    return a
def imagefft2(a, shape=None, axes=(-2, -1)):   #图片二维傅里叶变换
    return raw_fftnd(a, shape, axes, fft)


def imageifft2(a, shape=None, axes=(-2, -1)):
    return raw_fftnd(a, shape, axes, ifft)


#读取图像

original = cv.imread(r'D:\deng\smalljob\ImageSet\yz.jpg')
original = cv.cvtColor(original, cv.COLOR_BGR2RGB)

b,g,r=cv.split(original)

b_1=imagefft2(b)
g_1=imagefft2(g)
r_1=imagefft2(r)

b_fshift=fft_shift(b_1)
g_fshift=fft_shift(g_1)
r_fshift=fft_shift(r_1)

result_1 = np.log(np.abs(b_fshift)+1e-5)
result_2 = np.log(np.abs(g_fshift)+1e-5)
result_3 = np.log(np.abs(r_fshift)+1e-5)

b_ishift = ifft_shift(b_fshift)
g_ishift = ifft_shift(g_fshift)
r_ishift = ifft_shift(r_fshift)

b_2 = imageifft2(b_ishift)
g_2 = imageifft2(g_ishift)
r_2 = imageifft2(r_ishift)

img=np.dstack((b_2,g_2,r_2))
img=np.abs(img).astype(np.float32)/255.0

#展示结果

pyplot.subplot(231),pyplot.imshow(original,cmap='gray')
pyplot.title('original')
pyplot.axis('off')


pyplot.subplot(232),pyplot.imshow(result_1,cmap='gray')
pyplot.title('b_fft')
pyplot.axis('off')


pyplot.subplot(233),pyplot.imshow(result_2,cmap='gray')
pyplot.title('g_fft')
pyplot.axis('off')


pyplot.subplot(234),pyplot.imshow(result_3,cmap='gray')
pyplot.title('r_fft')
pyplot.axis('off')


pyplot.subplot(235),pyplot.imshow(img,cmap='gray')
pyplot.title('ifft')
pyplot.axis('off')
pyplot.show()

运行结果:

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值