Closed. This question needs to be more focused. It is not currently accepting answers. Learn more。
想改进这个问题吗?更新问题,使其只关注一个问题editing this post
在numpy
中,我们有以下功能:
import numpy
from numpy.fft import fft2, ifft2, fftshift, ifftshift
我想在r中重写这些函数。r中的
fft
与python中的fft
或fft2
一样工作。同样对于ifft2
,我们必须执行fft(,inverse=T)
现在我想知道如何在r中高效地重写
fftshift
和ifftshift
函数(对于矩阵)。 最佳答案
fftshift
和ifftshift
背后的概念非常直接。下面是我从MathWorks(Matlab的创建者)那里得到的一个数字:
Source: MathWorks doc page on fftshift
假设输入的2D矩阵被分割成象限象限1在左上角,象限2在右上角,象限3在右下角,象限4在左下角对于二维矩阵,fftshift
默认交换第一和第三象限以及第二和第四象限。您可以重写此行为,只需在一个维度上单独执行fftshift
如果你这样做,你就是在交换所谓的半空间。如果指定沿行交换(即维度1),则矩阵的上半部分将与下半部分交换。如果指定沿列交换(即维度2),则右半部分将与左半部分交换:
Source: MathWorks doc page on fftshift
默认情况下,使用fftshift
按顺序链接维度1和维度2的交换。如果有一个大小均匀的矩阵,其中的行和列是均匀的,那么将矩阵分成四部分并进行交换是非常明确的。但是,如果矩阵的大小是奇数,则取决于您所使用的语言。例如,在MATLAB和Python中,执行切换的位置定义为numpy
,其中(r,c) = ceil(rows/2), ceil(cols/2)
和rows
是矩阵的行和列cols
和r
是交换发生的行和列。
对于c
您只需反转对ifftshift
执行的操作。因此,默认操作是先交换维度2,然后交换维度1但是,必须重新定义奇数维矩阵的切换中心。您必须使用fftshift
,而不是ceil
,因为这精确地确定了执行floor
之后的半个空格的位置,现在您正在撤消对原始矩阵所做的操作。因此,新的开关中心是fftshift
。除此之外,在单一维度之间交换的逻辑是相同的——只是交换的中心现在已经改变了。
因此,这是我想出的办法。这些函数采用r中定义的矩阵和第二个可选参数来确定要交换的维度。忽略此选项将执行我刚才谈到的默认象限交换:
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")
}
}
在每个函数中,我定义了交换左半部分和右半部分以及上半部分和下半部分的函数。为了交换左右两半,简单地确定你使用什么列来执行交换,并使用索引来创建一个新的矩阵,通过将这两个半部连接起来,其中上半部是右半部,而下半部是左半部。在交换上半部分和下半部分时也会这样做,但要找到执行交换的正确行。
第二个参数
(r,c) = floor(rows/2), floor(cols/2)
可以选择性地设置为1或2以交换相应的维度请注意,dim
和fftshift
之间的唯一区别是定义的交换中心以及默认交换两个维度时的操作顺序剩下的代码是一样的。作为演示的一种方式,假设我声明了一个5 x 5的数字矩阵,如下所示:
> 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
注意,矩阵的大小在两个维度上都是奇数执行a
ifftshift
可以:> 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
您可以看到相应的维度已被交换。如果用
fftshift
来逆转,应该会返回原始矩阵,并且它确实:> 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
当然,您可以覆盖它并指定要交换的维度,因此假设您只想交换行:
> 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
时,必须使用与使用ifftshift
时用于交换的相同维度,以确保将原始矩阵取回。对于第二维度,我们也可以这样做:
> 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
有趣的是,我们可以验证
fftshift
所做的事情与我们上面讨论的相同下面是一个ipython会话: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
包的fftshift
和ifftshift
被导入,并创建一个2D矩阵,该矩阵与您在R中定义的示例中看到的相同。然后依次调用numpy.fft
、fftshift
和fftshift
,我们可以看到得到与R代码中看到的相同的结果。关于python - 如何在R中编写fftshift和ifftshift? ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38230794/