web-dev-qa-db-ja.com

pythonのDFT行列

Pythonで2次元DFTの DFT行列 を取得する最も簡単な方法は何ですか? numpy.fft でそのような関数を見つけることができませんでした。ありがとう!

16
Uri Cohen

これが組み込まれているとは思いません。ただし、直接計算は簡単です。

import numpy as np
def DFT_matrix(N):
    i, j = np.meshgrid(np.arange(N), np.arange(N))
    omega = np.exp( - 2 * pi * 1J / N )
    W = np.power( omega, i * j ) / sqrt(N)
    return W

[〜#〜] edit [〜#〜] 2D FFT行列の場合、次を使用できます。

x = np.zeros(N, N) # x is any input data with those dimensions
W = DFT_matrix(N)
dft_of_x = W.dot(x).dot(W)
13
Alex I

最も簡単でおそらく最速の方法は、SciPyのfftを使用することです。

import scipy as sp

def dftmtx(N):
    return sp.fft(sp.eye(N))

もっと速い方法を知っているなら(もっと複雑かもしれません)、私はあなたの入力に感謝します。

主な質問との関連性を高めるために、numpyを使用して行うこともできます。

import numpy as np

dftmtx = np.fft.fft(np.eye(N))

両方のベンチマークを行ったとき、scipyの方がわずかに速かったという印象がありますが、完全には実行しておらず、しばらく前のことなので、Wordを使用しないでください。

PythonでのFFT実装に関するかなり良い情報源は次のとおりです。 http://nbviewer.ipython.org/url/jakevdp.github.io/downloads/notebooks/UnderstandingTheFFT.ipynb 速度の観点からですが、この場合、実際には、単純さも伴う場合があることが実際にわかります。

11
pank

ラムダ関数も機能します:

dftmtx = lambda N: np.fft.fft(np.eye(N))

Dftmtx(N)を使用して呼び出すことができます。例:

In [62]: dftmtx(2)
Out[62]: 
array([[ 1.+0.j,  1.+0.j],
       [ 1.+0.j, -1.+0.j]])
2
Rehman Ali

@アレックス|基本的に正しいので、ここに2次元DFTに使用したバージョンを追加します。

def DFT_matrix_2d(N):
    i, j = np.meshgrid(np.arange(N), np.arange(N))
    A=np.multiply.outer(i.flatten(), i.flatten())
    B=np.multiply.outer(j.flatten(), j.flatten())
    omega = np.exp(-2*np.pi*1J/N)
    W = np.power(omega, A+B)/N
    return W
2
Uri Cohen

Scipy _0.14_の時点で、組み込みの_scipy.linalg.dft_があります。

16ポイントのDFT行列の例:

_>>> import scipy.linalg
>>> import numpy as np
>>> m = scipy.linalg.dft(16)
_

ユニタリプロパティを検証します。行列はスケーリングされていないため、16*np.eye(16)

_>>> np.allclose(np.abs(np.dot( m.conj().T, m )), 16*np.eye(16))
True
_

2D DFT行列の場合、行列代数を扱っているため、これはテンソル積、特にこの場合はクロネッカー積の問題です。

_>>> m2 = np.kron(m, m) # 256x256 matrix, flattened from (16,16,16,16) tensor
_

これで、タイル状の視覚化を行うことができます。これは、各行を正方形のブロックに再配置することによって行われます。

_>>> import matplotlib.pyplot as plt
>>> m2tiled = m2.reshape((16,)*4).transpose(0,2,1,3).reshape((256,256))
>>> plt.subplot(121)
>>> plt.imshow(np.real(m2tiled), cmap='gray', interpolation='nearest')
>>> plt.subplot(122)
>>> plt.imshow(np.imag(m2tiled), cmap='gray', interpolation='nearest')
>>> plt.show()
_

結果(実数部と画像部を別々に):

2D DFT basis

ご覧のとおり、これらは2DDFT基底関数です。

リンク ドキュメントへ

2
Kh40tiK

2D DFTを単一の行列演算として計算する場合、DFTの各出力には入力のすべてのインデックスの合計があるため、DFTを計算する行列Xをベクトルに解く必要があります。単一の二乗行列乗算にはこの機能がありません。インデックスを正しく処理していることを確認するように注意すると、次の作業が見つかります。

M = 16
N = 16
X = np.random.random((M,N)) + 1j*np.random.random((M,N))
Y = np.fft.fft2(X)
W = np.zeros((M*N,M*N),dtype=np.complex)
​
hold = []
for m in range(M):
    for n in range(N):
        hold.append((m,n))
​
for j in range(M*N):
    for i in range(M*N):
        k,l = hold[j]
        m,n = hold[i]
        W[j,i] = np.exp(-2*np.pi*1j*(m*k/M + n*l/N))

np.allclose(np.dot(W,X.ravel()),Y.ravel())
True

正規化を直交に変更する場合は、1/sqrt(MN)で除算するか、逆変換を行う場合は、指数の符号を変更するだけです。

1
Alex Madurowicz