2016-07-06 2 views
3

numpy В, мы имеем следующие функции:Как написать fftshift и ifftshift в R?

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

Я хотел бы переписать эти функции в R. fft в R работает точно так же, как fft или fft2 в питона. Кроме того, для ifft2, мы должны сделать fft(,inverse=T)

Теперь я хотел бы знать, как переписать fftshift и ifftshift функции (для матриц), эффективно в R.

+0

Спасибо за ваш комментарий. Функция в SynchWave предназначена только для векторов. И я постараюсь переписать с документом matlab. –

+0

Хорошо, вы хотите это для 2D-матриц? Я могу что-то написать для вас. – rayryeng

+0

Да! Спасибо, это очень мило с вашей стороны! –

ответ

5

Концепция fftshift и ifftshift довольно прямо вперед , Вот фигура, я вытащил из MathWorks (создатели MATLAB):

Source: MathWorks doc page on fftshift

Представьте, что ваш вход 2D матрица разбивается на квадранты. Квадрант № 1 находится в верхнем левом углу, квадрант № 2 находится в верхнем правом углу, четверть 3 - внизу справа, а четверть 4 - внизу слева. Для 2D-матриц fftshift по умолчанию меняет первый и третий квадранты, второй и четвертый квадранты. Вы можете переопределить это поведение, когда вы можете просто выполнить fftshift по одному измерению отдельно. Если вы это сделаете, вы обмениваете то, что называется полупространством. Если вы указали для свопинга вдоль строк (т. Е. Размер 1), то верхняя половина матрицы будет заменена нижней половиной. Если вы указали, чтобы поменять местами вдоль столбцов (т.е. размер 2), то правая половина становится местами с левой половины:

Source: MathWorks doc page on fftshift

Использование fftshift по умолчанию цепочки в обменивать размеров 1 и размеры 2 в последовательности. Если у вас есть матрица четного размера, где строки и столбцы четные, то очень однозначно разрезать матрицу на четыре части и выполнить обмен. Однако, если размер матрицы нечетный, это зависит от того, на каком языке вы смотрите. Например, в MATLAB и Python , где выполнение переключения определяется как (r,c) = ceil(rows/2), ceil(cols/2), где rows и cols являются строками и столбцами матрицы. r и c - это строка и столбец, где происходит обмен.

Для ifftshift вы просто обратный действия, совершенные на fftshift. Поэтому действие по умолчанию состоит в том, чтобы поменять размеры 2, а затем размеры 1. Однако вам нужно переопределить, где центр переключения используется для матриц нечетных размеров. Вместо ceil вы должны использовать floor, потому что это точно определяет, где полупространства были после того, как было выполненоfftshift, и теперь вы уничтожаете то, что было сделано на исходной матрице. Поэтому новый центр коммутации - (r,c) = floor(rows/2), floor(cols/2). Кроме того, логика для обмена между одним измерением - это то же самое - только что центр переключения теперь изменился.

Таким образом, вот что я придумал. Эти функции принимают матрицу, определенную в 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") 
    } 
} 

В каждой функции, я определить функции, поменять местами левую и правую половины, а также верхнюю и нижнюю половины. Чтобы поменять местами левую и правую половинки, просто определите, какой столбец вы используете для выполнения обмена и используйте индексирование, чтобы создать новую матрицу, объединив эти две половины вместе, где первая половина - правая половина, а вторая половина - левая половина , Вы бы сделали то же самое при замене верхней и нижней половин, но найти правильную строку для выполнения свопа.

Второй параметр dim может быть установлен в 1 или 2 для замены соответствующего измерения. Обратите внимание, что единственная разница между fftshift и ifftshift - это центр обмена, который определяется так же, как и порядок операций, когда вы по умолчанию меняете оба измерения. Остальная часть кода такая же.

В качестве средства демонстрации, предположим, я объявлен 5 х 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 

Обратите внимание, что размер матрицы нечетно в обоих измерениях. Выполнение fftshift дает нам:

> 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 должно дать нам первоначальную матрицу обратно, и это делает:

> 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 на матрицу, которая была выгружена в одном измерении, вы должны использовать один и тот же размер, который был использован для замены, когда вы использовали fftshift, чтобы убедиться, что вы получите оригинальную матрицу обратно.

Мы также можем сделать то же самое для второго измерения:

> 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:

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, а также fftshift и ifftshift из numpy.fft пакета импортированы в и 2D матрица создается, что это то же самое, что вы видели в примере, определенной в R. Затем мы называем fftshift, затем fftshift и ifftshift, и мы видим, что мы получаем те же результаты, что и в коде R.

+0

Я применил к своему изображению, это чудесно гауссовское размыто! Огромное спасибо. –

+0

@XRSC Добро пожаловать! – rayryeng

 Смежные вопросы

  • Нет связанных вопросов^_^