如何在R中编写fftshift和ifftshift? [英] How to write fftshift and ifftshift in R?

查看:159
本文介绍了如何在R中编写fftshift和ifftshift?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

numpy中,我们具有以下功能:

In numpy, we have the following functions :

import numpy
from numpy.fft import fft2, ifft2, fftshift, ifftshift

我想在R中重写这些函数.R中的fft与python中的fftfft2一样工作.同样对于ifft2,我们也必须执行fft(,inverse=T)

I would like to rewrite these functions in R. fft in R works just as fft or fft2 in python. Also for ifft2, we have to do fft(,inverse=T)

现在,我想知道如何在R中高效地重写fftshiftifftshift函数(用于矩阵).

Now I would like to know how to rewrite the fftshift and ifftshift functions (for matrices), efficiently in R.

推荐答案

fftshiftifftshift背后的概念非常简单.这是我从MathWorks(MATLAB的创建者)中提取的一个图:

The concept behind fftshift and ifftshift is quite straight forward. Here's a figure that I pulled from MathWorks (creators of MATLAB):

来源:fftshift上的MathWorks文档页面

Source: MathWorks doc page on fftshift

想象一下,您输入的2D矩阵被分成多个象限.第1象限在左上方,第2象限在右上方,第3象限在右下,第4象限在左下.对于2D矩阵,默认情况下fftshift交换第一和第三象限以及第二和第四象限.您可以覆盖此行为,而仅在一个维度上简单地执行fftshift即可.如果这样做,则交换了所谓的半角空格.如果您指定沿行交换(即维度1),则矩阵的上半部分将与下半部分交换.如果您指定沿列交换(即维度2),则右半部分将与左半部分交换:

Imagine that your input 2D matrix is split up into quadrants. Quadrant #1 is at the top left, quadrant #2 is at the top right, quadrant #3 is at the bottom right and quadrant #4 is at the bottom left. For 2D matrices, fftshift swaps the first and third quadrants and second and fourth quadrants by default. You can override this behaviour where you can simply perform fftshift on one dimension separately. If you do this, you are swapping what are known as half spaces. If you specified to swap along the rows (i.e. dimension 1), then the top half of the matrix gets swapped with the bottom half. If you specified to swap along the columns (i.e. dimension 2), then the right half gets swapped with the left half:

来源:fftshift上的MathWorks文档页面

Source: MathWorks doc page on fftshift

默认情况下,使用fftshift依次按顺序链接尺寸1和尺寸2的交换.如果您有一个偶数大小的矩阵,其中行和列是偶数,那么将矩阵切成四个部分并进行交换是非常明确的.但是,如果矩阵的大小奇数,则取决于您要使用的语言.例如,在MATLAB和Python numpy中,将执行切换的位置定义为(r,c) = ceil(rows/2), ceil(cols/2),其中rowscols是矩阵的行和列. rc是交换发生的行和列.

Using fftshift by default chains the swapping of dimensions 1 and dimensions 2 in sequence. If you have an even sized matrix where the rows and columns are even, then it's very unambiguous to cut the matrix into the four portions and do the swapping. However, if the matrix is odd sized, it depends on which language you're looking at. In MATLAB and Python numpy for instance, where to perform the switching is defined as (r,c) = ceil(rows/2), ceil(cols/2) where rows and cols are the rows and columns of the matrix. r and c are the row and column of where the swapping takes place.

对于ifftshift,您只需撤消fftshift执行的操作.因此,默认操作是交换2维,然后交换1维.但是,您必须重新定义交换中心是奇数维矩阵的位置.您必须使用floor而不是ceil,因为这可以精确确定执行 fftshift之后的半个空格,现在您要撤消对原始矩阵所做的操作.因此,新的切换中心是(r,c) = floor(rows/2), floor(cols/2).除此之外,在一个维度之间交换的逻辑是相同的-只是交换中心现在已更改.

For ifftshift you simply reverse the actions done on fftshift. Therefore, the default action is to swap dimensions 2 then dimensions 1. However, you have to redefine where the centre of switching is for matrices of odd dimensions. Instead of ceil, you must use floor because this precisely determines where the half spaces were after fftshift was performed and you are now undoing what was done on the original matrix. Therefore, the new centre of switching is (r,c) = floor(rows/2), floor(cols/2). Other than that, the logic to swap among a single dimension is the same - just that the centre of switching has now changed.

因此,这就是我的想法.这些函数采用R中定义的矩阵以及第二个可选参数来确定要交换的尺寸.省略此操作将执行我刚才谈到的默认象限交换:

As such, here's what I have come up with. These functions take in a matrix defined in R as well as a second optional argument to determine what dimension you want to swap. Omitting this performs the default quadrant swap I just talked about:

fftshift <- function(input_matrix, dim = -1) {

    rows <- dim(input_matrix)[1]    
    cols <- dim(input_matrix)[2]    

    swap_up_down <- function(input_matrix) {
        rows_half <- ceiling(rows/2)
        return(rbind(input_matrix[((rows_half+1):rows), (1:cols)], input_matrix[(1:rows_half), (1:cols)]))
    }

    swap_left_right <- function(input_matrix) {
        cols_half <- ceiling(cols/2)
        return(cbind(input_matrix[1:rows, ((cols_half+1):cols)], input_matrix[1:rows, 1:cols_half]))
    }

    if (dim == -1) {
        input_matrix <- swap_up_down(input_matrix)
        return(swap_left_right(input_matrix))
    }
    else if (dim == 1) {
        return(swap_up_down(input_matrix))
    }
    else if (dim == 2) {
        return(swap_left_right(input_matrix))
    }
    else {
        stop("Invalid dimension parameter")
    }
}

ifftshift <- function(input_matrix, dim = -1) {

    rows <- dim(input_matrix)[1]    
    cols <- dim(input_matrix)[2]    

    swap_up_down <- function(input_matrix) {
        rows_half <- floor(rows/2)
        return(rbind(input_matrix[((rows_half+1):rows), (1:cols)], input_matrix[(1:rows_half), (1:cols)]))
    }

    swap_left_right <- function(input_matrix) {
        cols_half <- floor(cols/2)
        return(cbind(input_matrix[1:rows, ((cols_half+1):cols)], input_matrix[1:rows, 1:cols_half]))
    }

    if (dim == -1) {
        input_matrix <- swap_left_right(input_matrix)
        return(swap_up_down(input_matrix))
    }
    else if (dim == 1) {
        return(swap_up_down(input_matrix))
    }
    else if (dim == 2) {
        return(swap_left_right(input_matrix))
    }
    else {
        stop("Invalid dimension parameter")
    }
}

在每个函数中,我都定义了交换左半部分和右半部分以及上半部分和下半部分的函数.要交换左右两半,只需确定要使用哪一列来执行交换,并通过将这两个两半连接在一起来使用索引来创建新矩阵,其中上半部分为右半部分,下半部分为左半部分.交换上半部分和下半部分时,您将执行相同的操作,但是找到右行执行交换.

In each function, I define functions that swap the left and right halves as well as the top and bottom halves. To swap the left and right halves, simply determine what column you're using to perform the swapping and use indexing to create a new matrix by concatenating these two halves together where the first half is the right half and the second half is the left half. You would do the same when swapping the top and bottom halves but find the right row to perform the swap.

第二个参数dim可以选择设置为1或2以交换相应的尺寸.请注意,fftshiftifftshift之间的唯一区别是定义的交换中心以及默认情况下交换两个尺寸时的操作顺序.其余代码相同.

The second parameter dim can optionally be set to either 1 or 2 to swap the corresponding dimension. Note that the only difference between fftshift and ifftshift is the centre of swapping that is defined as well as the order of operations when you default to swapping both dimensions. The rest of the code is the same.

作为演示的方法,假设我已经声明了一个5 x 5的数字矩阵,如下所示:

As a means of demonstration, suppose I have declared a 5 x 5 numeric matrix like so:

> O <- matrix(1:25, 5, 5)
> O
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    2    7   12   17   22
[3,]    3    8   13   18   23
[4,]    4    9   14   19   24
[5,]    5   10   15   20   25

请注意,矩阵的尺寸在两个维度上都是奇数.执行fftshift给我们:

Note that the size of the matrix is odd in both dimensions. Performing a fftshift gives us:

> P <- fftshift(O)
> P
     [,1] [,2] [,3] [,4] [,5]
[1,]   19   24    4    9   14
[2,]   20   25    5   10   15
[3,]   16   21    1    6   11
[4,]   17   22    2    7   12
[5,]   18   23    3    8   13

您可以看到已经交换了相应的尺寸.用ifftshift逆转此操作应该可以将原始矩阵返回给我们,并且可以做到:

You can see that the corresponding dimensions have been swapped. Reversing this with ifftshift should give us the original matrix back, and it does:

> Q <- ifftshift(P)
> Q
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    2    7   12   17   22
[3,]    3    8   13   18   23
[4,]    4    9   14   19   24
[5,]    5   10   15   20   25

当然,您可以覆盖此参数并指定要交换的维度,因此,假设您只希望交换行:

Of course you can override this and specify which dimension you want to swap, so let's say you wanted to swap just the rows:

> fftshift(O, 1)
     [,1] [,2] [,3] [,4] [,5]
[1,]    4    9   14   19   24
[2,]    5   10   15   20   25
[3,]    1    6   11   16   21
[4,]    2    7   12   17   22
[5,]    3    8   13   18   23

> ifftshift(fftshift(O, 1), 1)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    2    7   12   17   22
[3,]    3    8   13   18   23
[4,]    4    9   14   19   24
[5,]    5   10   15   20   25

请注意,在对一维交换矩阵执行ifftshift时,必须使用与使用fftshift交换时使用的维相同的维,以确保获得原始矩阵返回.

Take care that when you perform ifftshift on a matrix that was swapped in one dimension, you must use the same dimension that was used for swapping when you used fftshift to ensure you get the original matrix back.

对于第二维,我们也可以这样做:

We can also do the same for the second dimension:

> ifftshift(O, 2)
     [,1] [,2] [,3] [,4] [,5]
[1,]   11   16   21    1    6
[2,]   12   17   22    2    7
[3,]   13   18   23    3    8
[4,]   14   19   24    4    9
[5,]   15   20   25    5   10

> ifftshift(fftshift(O, 2), 2)
     [,1] [,2] [,3] [,4] [,5]
[1,]    1    6   11   16   21
[2,]    2    7   12   17   22
[3,]    3    8   13   18   23
[4,]    4    9   14   19   24
[5,]    5   10   15   20   25


作为一个有趣的注解,我们可以验证numpy所做的与我们上面讨论的相同.这是一个IPython会话:


As an interesting note, we can verify that numpy does the same thing as what we discussed above. Here's an IPython session:

In [16]: import numpy as np

In [17]: from numpy.fft import fftshift, ifftshift

In [18]: O = np.reshape(np.arange(1,26), (5,5)).T

In [19]: O
Out[19]:
array([[ 1,  6, 11, 16, 21],
       [ 2,  7, 12, 17, 22],
       [ 3,  8, 13, 18, 23],
       [ 4,  9, 14, 19, 24],
       [ 5, 10, 15, 20, 25]])

In [20]: fftshift(O)
Out[20]:
array([[19, 24,  4,  9, 14],
       [20, 25,  5, 10, 15],
       [16, 21,  1,  6, 11],
       [17, 22,  2,  7, 12],
       [18, 23,  3,  8, 13]])

In [21]: ifftshift(fftshift(O))
Out[21]:
array([[ 1,  6, 11, 16, 21],
       [ 2,  7, 12, 17, 22],
       [ 3,  8, 13, 18, 23],
       [ 4,  9, 14, 19, 24],
       [ 5, 10, 15, 20, 25]])

导入

numpy以及numpy.fft包中的fftshiftifftshift,并创建一个二维矩阵,该矩阵与R中定义的示例中所看到的相同.然后,​​调用fftshift,然后依次是fftshiftifftshift,我们可以看到得到的结果与R代码相同.

numpy as well as fftshift and ifftshift from the numpy.fft package are imported in and a 2D matrix is created that is the same as what you saw in the example defined in R. We then call fftshift, then fftshift and ifftshift in sequence and we can see that we get the same results as seen in the R code.

这篇关于如何在R中编写fftshift和ifftshift?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆