FFTW@wiki
http://w.atwiki.jp/amaeda/
FFTW@wiki
ja
2012-10-10T20:01:05+09:00
1349866865
-
comments
https://w.atwiki.jp/amaeda/pages/37.html
-Re:powerspectol.hとは? > すみません.見逃してました.ありました.とても参考になりました - 名無しさん 2012-10-10 20:01:06
-powerspectol.hとは? - 名無しさん 2012-10-10 19:57:28
-わかりやすく、ありがとうございます。 - yukichi 2012-06-10 17:24:44
-がびょーん - 通りすがり 2012-05-14 23:51:29
-文字ばっかりでわかりづらいぞっ - 名無し 2009-07-05 11:41:03
->名無しさん ほっ、ほんとうだ・・・。ご指摘ありがとうございます。 - 管理人 2009-06-28 23:50:57
-とても参考になりますた。 - 16:55:36の人 2009-06-24 17:39:31
-サンプルプログラムの「位相を得る」のソース中のatan2の引数がおかしいかと。 - 名無しさん 2009-06-24 16:55:36
-時間があったら、バージョン情報も載せます。 - 管理人 2008-11-22 15:50:42
-新しいバージョンとの違いも載せてください - 名無しさん 2008-11-09 12:19:17
-コメントありがとうございます。データ入力の配列。サンプルプログラムの基本の使い方はご覧になりましたでしょうか。合わせて、マニュアルの多次元配列のフォーマットもご参照ください。分かりにくかったら遠慮なくご一報を。 - 管理人 2008-10-31 10:03:13
-データ入力の配列について教えていただきたいです。 - 名無しさん 2008-10-30 14:53:48
-GURUインターフェースについて知りたいです - 名無しさん 2008-10-05 15:52:19
--Advanced、Guruインターフェースについても翻訳予定です~ - 管理人 2008-10-05 16:01:57
-ぽーにょぽにょぽにょさかなのこ~ - ぽにょ 2008-09-24 23:43:42
-意見・感想など、どんどんお寄せください - 管理人 2008-09-15 22:01:55
2012-10-10T20:01:05+09:00
1349866865
-
FFTWマニュアル
https://w.atwiki.jp/amaeda/pages/11.html
&counter()番目のお客様 (^-^)/~~
* FFTWのページ
このページは、フリーのFFTライブラリFFTWが有効に活用されるように作られたページです。
マニュアルの日本語訳や、使用上の注意、サンプルプログラムがあります。
未完成のところも多いですが、常時更新していきます。
FFTWはバージョン2と3では大幅に仕様が異なるので、ご利用のバージョンにご注意ください。
ご意見や、感想を掲示板のほうへお寄せください。
動かない、分からないなどのお問い合わせは takaidohigasi あっと gmail.com へ!(回答あるかどうかは、保証しかねますが。。。)
#image(lena.bmp,inline) #image(powerspectol_gray.bmp,inline)
* FFTW3.1.2 マニュアル
+[[FFTWとは??>FFTW Introduction]]
+[[FFTWの使い方>FFTW Tutorial]] (簡単な使い方)
++[[複素1次元離散フーリエ変換>Complex One-Dimensional DFTs]]
++[[複素多次元離散フーリエ変換>Complex Multi-Dimensional DFTs]]
++[[実データ1次元離散フーリエ変換>One-Dimensional DFTs of Real Data]]
++[[実データ多次元離散フーリエ変換>Multi-Dimensional DFTs of Real Data]]
+[[その他重要なこと>Other Important Topics]]
++[[データの並び>Data Alignment]]
++[[多次元配列のフォーマット>Multi-dimensional Array Format]]
++[[知の利用-プランの保存>Words of Wisdom-Saving Plans]]
++[[知の利用上の注意>>Caveats in Using Wisdom]]
+[[FFTWリファレンス>>FFTW Reference]] (詳細なマニュアル)
++ [[データタイプとファイル>>Data Types and Files]]
++ [[プランの利用>>Using Plans]]
++ [[ベーシックインターフェース>>Basic Interface]]
** サンプルプログラム
-[[programs>サンプルプログラム]]
** 掲示板
-[[BBS]]
** リンク
- [[本家FFTW>http://www.fftw.org/]]
- [[本家マニュアル(英語)>http://www.fftw.org/fftw3_doc/]]
** 修正/更新
- [[実データ1次元離散フーリエ変換>One-Dimensional DFTs of Real Data]]の対称性を利用した、計算機資源節約の節で、hermitian redundancyをハミルトニアン冗長性と誤訳していました。正しくはエルミート~。
- 4.2節プランの利用を追加しました。
- 4.3節ベーシックインターフェース4.3.2プランのフラグのところまで追加しました。
- 位相を求めるサンプルプログラムの間違えを修正しました。ご指摘ありがとうございます!
2012-05-15T00:19:42+09:00
1337008782
-
Basic Interface
https://w.atwiki.jp/amaeda/pages/55.html
[[FFTWマニュアル]] - [[FFTWリファレンス>FFTW Reference]] - [[ベーシックインターフェース>>Basic Interface]]
* ベーシックインターフェース Basic Interface
ベーシックインターフェースは、おそらく大多数のユーザーの要望を満たすもので、FFTWのサポートする全てのタイプの、単一の連続した配列の変換に関するプランナールーチンを提供します。
- [[複素離散フーリエ変換>Complex DFTs]]
- [[プランナーフラグ>>Planner Flags]]
- [[実データ離散フーリエ変換>>Real-Data DFTs]]
- [[実データ離散フーリエ変換の配列の形式>>Real-Data DFT Array Format]]
- [[実数から実数への変換>>Real-to-Real Transforms]]
- 実数から実数への変換種
2009-07-04T23:17:40+09:00
1246717060
-
Real-to-Real Transforms
https://w.atwiki.jp/amaeda/pages/60.html
[[FFTWマニュアル]] - [[FFTWリファレンス>FFTW Reference]] - [[ベーシックインターフェース>>Basic Interface]] - [[実数から実数への変換>>Real-to-Real Transforms]]
* 実数から実数への変換 Real-to-Real Transforms
2009-07-04T23:17:14+09:00
1246717034
-
Real-data DFT Array Format
https://w.atwiki.jp/amaeda/pages/59.html
[[FFTWマニュアル]] - [[FFTWリファレンス>FFTW Reference]] - [[ベーシックインターフェース>>Basic Interface]] - [[実データ離散フーリエ変換配列様式>>Real-data DFT Array Format]]
* 実データ離散フーリエ変換配列様式
実データの離散フーリエ変換出力(r2c変換)は、対称性を持つ。つまり、原則的には、2倍の冗長性を持つ(4.7節[[What FFTW Really Computes>>What FFTW Really Computes]]参照)。(逆c2r変換の入力も、同様)。実際のところ、これらの冗長性の排除を、効果的かつ理解しやすい形式(多次元変換の一般化するもの)で行うことを、完全に実現することは不可能である。その代わりに、r2c変換の出力は、対応する複素変換の出力の半分を&italic(){わづかに}超える。データはいかなる方法でも”圧縮”せず、通常のfftw_complex値の配列として、格納している。実際のところ、このデータは対応する複素変換の配列の一部分である。
具体的にいえば、d(=ランク)次元の n1 x n2 x n3 x ... x nd の実変換では、複素データは、fftw_complex値で、n1 x n2 x n3 x ... x (nd/2 + 1)の行メジャー形式の配列である(割り算の余りは切り捨て)。つまり、我々は通常の複素変換で得られるデータの最後の次元の、小さいほうの半分(非負周波数)、に加えて1要素しか保存していません。(他の次元を半分にすることも可能でしたが、実装が最も簡単だったため、最後の次元を半分にしました)。
入出力が異なる、アウトオブレイス変換では、実データは単なる配列で、物理次元 n1 x n2 x n3 x ... x nd(列メジャー形式)となっています。
入出力が同じである、インプレイス変換では、いくつか複雑な問題が生じます。というのも、複素データは、実データより僅かに大きいためです。このケースでは、実データの最後の次元は、必ず&italic(){余白}がとられている必要があり、そこには追加の余分な値が格納されます。--最後の次元が偶数であれば、2つの追加、奇数であれば1つの追加データです。
つまり、実データの最後の次元は、物理的に 2(nd + 1)個のdouble値である必要があります(複素データを格納するのに過不足ないサイズ)。しかしながら、この物理的配列サイズは、論理的な配列サイズは変更しません。ndの値だけが、実際に最後の次元に格納され、ndがプランナーに渡される最後の次元となります。
2009-07-04T23:13:43+09:00
1246716823
-
phase
https://w.atwiki.jp/amaeda/pages/27.html
//cpp
/**
* @brief phase calculation
* @auther maeda
* @date 2008/09/23
*/
#include "phase.h"
#define _USE_MATH_DEFINES
#include "math.h"
/**
* get the phase of the signal and normalize it to 0-1 range
* if we can't get the phase i.e. power=0, set -1
* @param in input data ( frequency domain )
* @param out 0-1 normalized phase ( frequency domain )
* @param rows ( height )
* @param cols ( width )
* @return true if succeed
*/
int maGetPhase2D( fftw_complex *data, double *out, int rows, int cols )
{
int i,j;
int idx;
if( data==NULL || out==NULL ) return false;
if( rows<0 || cols<0 ) return false;
for( j=0; j<rows; j++ ){
for( i=0; i<cols; i++ ){
idx = j*cols + i;
if( data[idx][0]!=0 || data[idx][1]!=0 ){
// function atan2 returns [-M_PI, M_PI], so normalize it to 0-1
out[idx] = 0.5 + 0.5*atan2( data[idx][1], data[idx][0] )/M_PI;
}else{
// if we can't decide phase, return -1
out[idx] = -1;
}
}
}
return true;
}
2009-06-28T23:53:59+09:00
1246200839
-
Real-Data DFTs
https://w.atwiki.jp/amaeda/pages/58.html
[[FFTWマニュアル]] - [[FFTWリファレンス>FFTW Reference]] - [[ベーシックインターフェース>>Basic Interface]] - [[実データ離散フーリエ変換>>Real-Data DFTs]]
* 実データ離散フーリエ変換 Real-Data DFTs
fftw_plan fftw_plan_dft_r2c_1d( int n,
double *in, fftw_complex *out,
unsigned flags );
fftw_plan fftw_plan_dft_r2c_2d( int nx, int ny,
double *in, fftw_complex *out,
unsigned flags );
fftw_plan fftw_plan_dft_r2c_3d( int nx, int ny, int nz,
double *in, fftw_complex *out,
unsigned flags );
fftw_plan fftw_plan_dft_r2c( int rank, const int *n,
double *in, fftw_complex *out,
unsigned flags );
実数入力/複素数出力の0次以上の離散フーリエ変換(DFT)のプランをたてて、fftw_planを返します(4.2節の[[プランの利用>>Using Plans]]参照)。
いったんある変換タイプおよびパラメータのプランを生成すれば、異なる配列に対して、同じタイプおよびパラメータのプランを生成する際に、高速にプランが生成され、定数は共有されます(もし存在すれば)。
プランナーはプランが生成できなかったとき、返り値としてNULLを返します。そして、ベーシックインターフェースでは、FFTWをある制限された変換群をサポートする設定にカスタマイズするか、入出力が異なるout-of-placeのc2r多次元変換でFFTW_PRESERVE_INPUTフラグを使わない限り、返り値としてNULLでない値を返します。
** 引数 Arguments
*** rank
ランク(rank)は、変換の次元で(これは配列*nのサイズであるはずです)任意の非負整数を取りえます。'_1d'、'_2d'、'_3d'のプランナーはそれぞれランク(rank)が1,2,3に対応します。ランク(rank)0は、サイズ1の変換、つまり入力から出力への数のコピーに相当します(ただし、0の虚部を伴います)。
*** nまたは、nx/ny/nzまたは、n[rank]
nまたは、nx,ny,nzもしくは、n[rank]はそれぞれ変換の次元の&i(){論理的}サイズを与え、任意の非負整数をとりえます。これは一般的に、&i(){物理的}配列次元とはことなります。これについては4.3.4章の[[実データ離散フーリエ変換配列形式>>Real-data DFT Array Format]]に記されています。
- FFTWは配列サイズが$$2^a3^b5^c7^d11^e13^f$$の時に、一番性能が発揮され
ます。ただし、e+fは、0か1で他の係数(a,b,c,d)は任意です。他のサイズの時は、一般的なアルゴリズムを用いた遅いアルゴリズムで計算されます(それでも遅くてもO(nlogn)の次元です)。FFTWを違うサイズ用にカスタマイズすることもできるので、必要なら8章のInstallation and Customizationを参照してください。2の階乗のサイズの変換はとりわけ高速に計算でき、それは一般的にr2c/c2r変換の&i(){最後の}次元が偶数であるときに効果があるということになります。
*** in,out
inとoutは変換の入力および出力の配列を表し、同じものを取りえます(in-place変換)。これらの配列は、FFTW_ESTIMATEフラグが使われない限り、プラン生成の際に値が上書きされます。(配列は初期化する必要はないが、確保する必要があります)。入出力が同じであるin-place変換の時は、実配列はパディングが必要です。これについては4.3.4章の[[実データ離散フーリエ変換配列様式>>Rea-data DFT Array Format]]に記されています。
*** flags
flagはビットごとのORで構成されるゼロ以上のフラグです。24ページの4.3.2章の[[プランナーフラグ>>Planner Flags]]で定義されます。
逆変換については、複素数の入力(エルミート配列の論理的に半分のサイズに非冗長に格納されているもの)をとり、実数を出力とする以下のようなものです。
fftw_plan fftw_plan_dft_c2r_1d( int n,
fftw_complex *in, double *out,
unsigned flags );
fftw_plan fftw_plan_dft_c2r_2d( int nx, int ny,
fftw_complex *in, double *out,
unsigned flags );
fftw_plan fftw_plan_dft_c2r_3d( int nx, int ny, int nz,
fftw_complex *in, double *out,
unsigned flags );
fftw_plan fftw_plan_dft_c2r( int rank, const int *n
fftw_complex *in, double *out,
unsigned flags );
引数は、入出力のデータ形式が逆になっているところ以外はr2c変換と、まったく同じです。
&color(red){FFTWの演算では規格化がされません}。すなわち、c2r変換を行った後、r2c変換(またははその逆)を行うと、計算結果は元のデータを変換のサイズ倍(配列の論理的次元の積)されます。r2c変換は、同じ入力を用いて、複素離散フーリエ変換のでFFTW_FORWARDとした時と、同じ結果になり、c2r変換はFFTW_BACKWARDに対応します。より詳しい情報は、4.7章の[[What FFTW Really Computes>>What FFTW Really Computes]]を参照してください。
2009-03-24T13:10:05+09:00
1237867805
-
Complex DFTs
https://w.atwiki.jp/amaeda/pages/56.html
[[FFTWマニュアル]] - [[FFTWリファレンス>FFTW Reference]] - [[ベーシックインターフェース>>Basic Interface]] - [[複素離散フーリエ変換>>Complex DFTs]]
* 複素離散フーリエ変換
fftw_plan fftw_plan_dft_1d( int n,
fftw_complex *in, fftw_complex *out,
int sign, unsigned flags );
fftw_plan fftw_plan_dft_2d( int nx, int ny,
fftw_complex *in, fftw_complex *out,
int sign, unsigned flags );
fftw_plan fftw_plan_dft_3d( int nx, int ny, int nz,
fftw_complex *in, fftw_complex *out,
int sign, unsigned flags );
fftw_plan fftw_plan_dft( int rank, const int *n,
fftw_complex *in, fftw_complex *out,
int sign, unsigned flags );
複素数を入出力とする、0次元または多次元の離散フーリエ変換(DFT)をおこない、fftw_planを返り値として返します(4.2章[[プランの利用>>Using Plans]]参照)。
一たび、特定の型及びパラメータに対しプランを作り、その後同じ型、パラメータに対する異なるプラン(ただし対象とする配列が異なるもの)を生成すれば、プラン生成は高速におこなわれ、最初のプランと同じデータは共有されます(仮に最初のプランがまだ存在すれば)。
プランナーは、プランの生成に失敗すればNULLを返します。
FFTWの設定をカスタマイズして、特定の変換を行うようにしない限りベーシックインターフェースは常にNULLでない値を返します。
** 引数
*** rank
ランク(rank)は変換の次元(配列*nのサイズであるはずです)であり、任意の非負整数をとりえます。"_1d","_2d","_3d"のプランナーはそれぞれrankが1,2,3に対応します。rankが0は、サイズ1の変換に対応し、これはすなわち1つの数を入力から出力へコピーとなります。
*** n, nx, ny, nz, n[rank]
nまたは、nx,ny,nzもしくは、n[rank]はそれぞれ変換の次元のサイズを与え、任意の非負整数をとりえます。
- 多次元の配列は列メジャー順で次元が格納されます。すなわちnx x ny、あるいはnx x ny x nz、あるいはn[0] x n[1] x ... n[rank-1]という順です。詳細は3.2章の[[多次元配列のフォーマット>>Multi-dimensional Array Format]]参照。
- FFTWは配列サイズが$$2^a3^b5^c7^d11^e13^f$$の時に、一番性能が発揮され
ます。ただし、e+fは、0か1で他の係数(a,b,c,d)は任意です。他のサイズの時は、一般的なアルゴリズムを用いた遅いアルゴリズムで計算されます(それでも遅くてもO(nlogn)の次元です)。FFTWを違うサイズ用にカスタマイズすることもできるので、必要なら8章のInstallation and Customizationを参照してください。2の階乗のサイズの変換はとりわけ高速に計算できます。
*** in, out
inとoutは変換の入力および出力の配列を表し、同じものを取りえます(in-place変換)。これらの配列は、FFTW_ESTIMATEフラグが使われない限り、プラン生成の際に値が上書きされます。(配列は初期化する必要はないが、確保する必要があります)。
in == outの時には、変換はin-placeとなり、入力配列は上書きされます。in != outであれば、2つの配列はメモリ領域が重なってはいけません(FFTWはこの条件はチェックしません)。
*** sign
signはフーリエ変換を定義するエクスポーネントです。-1(=FFTW_FOWRARD)もしくは+1(FFTW_BACKWARD)の値をとります。
※変換の方向と考えてよい
*** flags
flagはビットごとのORで構成されるゼロ以上のフラグです。24ページの4.3.2章の[[プランナーフラグ>>Planner Flags]]で定義されます。
&color(red){FFTWの演算では規格化がされません}。すなわち、逆変換を行った後、正変換(またはその逆)を行うと、計算結果は元のデータを変換のサイズ倍(配列の次元の積)されます。より詳しい情報は、4.7章の[[What FFTW Really Computes>>What FFTW Really Computes]]を参照してください。
2009-03-24T12:57:27+09:00
1237867047
-
FFTW使用上の注意
https://w.atwiki.jp/amaeda/pages/17.html
* 全般
# スケーリング
変換の結果は配列のスケール倍される。
* プラン生成
プラン生成は、原則的にデータの”メモリ空間”に対して行われ、
(これはFFTWのバージョン3になってから大きく変更されたポイントである。)
プラン生成時には、計算時間の最適化などを行うので、多少時間がかかる。
したがって、繰り返し計算を行う時には、一度生成したプランを繰り返し使うことが推奨されている。
すると、例えば、同じサイズの入力データが複数あるとき、一度プランを生成してから、プラン生成時に指定したメモリ空間にデータをコピーして演算を行うことが考えられる。
この際、プラン用のメモリ空間が、”バッファ”として余分に消費されることになるので、多くのメモリを必要とする場合には検討が必要だ。
また、ここまででプランは特定の”メモリ空間”に対して生成されると述べたが、データサイズが同じ、などの制約下であれば、他のメモリ空間に対してプランを再利用する関数も存在する。
また、プラン生成時に入出力配列は上書きされることがある。フラグの設定をよく確認しよう。面倒だったら、入力配列はプラン生成後の初期化するよう心がけよう。
** データのメモリ空間上の並び(行メジャー)
FFTWのデータはrow-major(行メジャー)で考えられて作られている。
行メジャーとは、最後の配列が、もっともはやく変化する順序である。
int a[SIZEX][SIZEY];
というものがあったとすると、メモリ空間では、
a[0][0],a[0][1],・・・,a[1][0],・・・,a[SIZEX-1][SIZEY-1]
のように並ぶ。
利用上は、column-major(列メジャー)でも構わないが注意が必要である。
すると、利用者は、int a[SIZEY][SIZEX]のつもりなのに、FFTWは、int a[SIZEX][SIZEY]だと思っているので、
#image(caution.bmp)
のようにパラメータのヒントなどで誤解を招く表現が生じる。
要注意である。
このページでは、画像データなどを扱うことを考え、FFTWの推奨ではないのを承知で、列メジャーのデータを扱うコードに統一することとする。
#image(row-major.bmp,center,width=250)
行メジャー(row-major)ーと列メジャー(column-major)
* 実数->複素数/複素数->実数変換&u(){}
2009-03-23T01:51:20+09:00
1237740680
-
powerspectol
https://w.atwiki.jp/amaeda/pages/24.html
//cpp
/**
* Powerspectol calculation
* @author maeda
* @date 2008/09/01
*/
#include "powerspectol.h"
#define _USE_MATH_DEFINES
#include "math.h"
/**
* get the log scaled powerspectol of the signal and normalize it to 0-1 range
* @param in input data ( frequency domain )
* @param out output data ( frequency domain )
* @param cols ( width )
* @param rows ( height )
* @return true if succeed
* -------------------------------------------------------------------------
* (1) get the log scaled powerspectol : log(1 + sqrt(re*re + im*im))
* (2) normalize
*/
int maGetPowerSpectol2D( fftw_complex *in, double *out, int cols, int rows )
{
int i,j;
int idx; // index of data
double max, min, scale; // max/min of powerspectol
if( in==NULL || out==NULL ) return false;
if( rows<0 || cols<0 ) return false;
// (1) get the log scaled powerspectol : log(1 + sqrt(re*re + im*im))
// ( powerspectol is defined as re*re + im*im )
// this is equal or greater than 0
for( j=0; j<rows; j++ ){
for( i=0; i<cols; i++ ){
idx = j*cols + i;
out[idx] = log10( 1 + sqrt(pow(in[idx][0],2) + pow(in[idx][1],2)) );
}
}
// (2) normalization
// (2-1) get the maximum and minimum
max = min = out[0];
for( j=0; j<rows; j++ ){
for( i=0; i<cols; i++ ){
idx = j*cols + i;
if( out[idx]>max ) max = out[idx];
if( out[idx]<min ) min = out[idx];
}
}
// (2-2) normalize
scale = 1./(max-min);
for( j=0; j<rows; j++ ){
for( i=0; i<cols; i++ ){
idx = j*cols + i;
out[idx] = ( out[idx] - min ) * scale;
}
}
return true;
}
2009-03-23T01:43:18+09:00
1237740198