VBを使った自作の逆FFTについて

このQ&Aのポイント
  • 自作の逆FFTを用いて2次元FFT図を元の画像に戻すプログラムを作成しました。
  • しかし、得られた画像には右斜上方向に数本の線や何かが入り、その線によって画像の濃度が逆転するという問題があります。
  • また、2次元FFT図を読み込む際に、白い点の実数部のみを読み込ませていますが、虚数部も読み込む必要があるのか、それとも別の原因による問題なのかについても疑問があります。
回答を見る
  • ベストアンサー

VBを使った自作の逆FFT

2次元FFT図を逆FFTし元の画像を得るプログラムを作ったのですが、得られた画像は、右斜上方向に数本の線やら何か入っててその線によって画像の濃度を逆転したりしています(説明が悪くてすいません)。その障害はありますが、少し画像は得られてます。 2次元FFT図は、自分で作ったものです。picture.backcolor=RGB(0,0,0)でスペクトルの点は、半径1、RGB(255,255,255)です。サイズは256*256です。一点かき、逆FFTで水平方向に白、黒、白・・・・(画像)を得ることを目的としております。 画像を読み込みの時、 For j = 1 To Size For i = 1 To Size rTemp(i) = Picture.Point(i, j) And &HFFFFFF iTemp(i) = 0# Next i For i = 1 To Size rData(i, j) = rTemp(i) iData(i, j) = iTemp(i) Next i Next j (r-実部、i-虚部) このように白い点だけ実数部に読み込ませて、逆FFTをしています。 虚部もよみ込ませる必要あるのですか? 読み込ませるとしたら、値をどのように与えてやればいいのですか? それか結果(得られる画像にいろんな障害がある)の原因は別のところにあるのですか? 説明が不十分や悪いとは思いますが、宜しくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
  • nta
  • ベストアンサー率78% (1525/1942)
回答No.3

実例となると自分で作ってみるしかないのですが、フーリエ変換式というのはこういうものでしょうか。DFTの具体的なアルゴリズムをご提示ください。 http://www.geocities.jp/shotajp/fourier.htm 計算結果が複素数で出力されますが、この結果はノルムだけをとっても0から255の間の整数に収まらないので最大値を255として比例配分することになります。ただ、この操作では全体的に数値の小さいところがほとんどになり、画面上は真っ黒になってしまいます。人間の視覚で判断するには対数スケールで配分した方がわかりやすくなります。もちろん次の計算には使うことができないので見るだけですが。

na-asuka
質問者

お礼

ありがとうございました。 0から255の間の整数に収まらないので最大値を255として比例配分することになります。がポイントですね。 がんばってみます。

その他の回答 (2)

  • nta
  • ベストアンサー率78% (1525/1942)
回答No.2

グレースケール上ではRGBのそれぞれの8ビット値が一致すればよいので、演算はどれか8ビット値だけを取り出してフーリエ変換すればいいと思います。もちろんフーリエ変換の前は実数変換を行い、フーリエ変換後もスケーリングをして0~255の整数値に規格化する必要があります。これをRGB値のそれぞれに代入することになるでしょう。フーリエ変換後の複素数の取り扱いはいろいろな課題があります。ノルムだけを使用するのか、実数部をとるのかこのあたりは求める内容やそれ以降の処理の進め方によります。

na-asuka
質問者

補足

ありがとうございます。 >演算はどれか8ビット値だけを取り出して すいません。よろしければ、具体例を教えていただけませんでしょうか? 規格化っていうのは、どういうことなのでしょうか? ご指導の程よろしくおねがいします。

  • nta
  • ベストアンサー率78% (1525/1942)
回答No.1

どうしても説明が読みとれません。 使用する逆FFT図はRGB値各8ビット×4の組み合わせでモノクロかもしれませんが、その32ビット値をフーリエ変換してしまうと別の色を表現することになってしまいます。常にグレースケール上に配分できるように変換する作業はできているのでしょうか。

na-asuka
質問者

補足

遅くなって申し訳ございません。 >どうしても説明が読みとれません。 すいません。日本語の表現が苦手です。 >使用する逆FFT図はRGB値各8ビット×4の組み合わせでモノクロかもしれませんが、その32ビット値をフーリエ変換してしまうと別の色を表現することになってしまいます。常にグレースケール上に配分できるように変換する作業はできているのでしょうか。 すいません。勉強不足です。 グレースケール上に配分という処理はどのような処理ですか? 詳しく教えてください。お願いします。

関連するQ&A

  • VB バリアント型の配列の例について

    長々と失礼します。私の使用している教科書に 「バリアント型の2次元配列」と「バリアントに2次元配列を代入」というのを組み合わると「行列i要素とする行列」たとえば 2 5 9 4 1 8 7 3 6 1 5 9 8 0 1 6を的確に表現できます。 と書いており、下のように書かれているのですが上のような配列を表示しません。どこが間違っているのでしょうか?そもそも上のように表示できるのか理解に苦しんでおります Option Base 1 Private Sub Command1_Click() Dim a(2,2) As Variant Dim c(2,2) As Integer For i = 1 To 2 For j = 1 To 2 For p = 1 To 2 For q = 1 To 2 c(p,q) = p + q + i * j Next q Next p a(i,j) Next j Next i For i = 1 To 2 For p = 1 To 2 For j = 1 To 2 For q = 1 To 2 Print a(i,j)(p,q), Next q Next j Print Next p Next i End Sub

  • 2次元データの複素フーリエ変換するコードの作成

    数値計算等の2次元や3次元の空間データ(実数)をFFTによって複素フーリエ変換する実際のプログラム化についてお尋ねします。プログラムの実装ということなので実際的な質問で長文になっています。すみません。 まず、手持ちに1次元のFFTプログラムがあるということを前提とします(逆フーリエ変換すると、元の実数の系列が出ることは確認済のコード)。そして2次元配列の実数のデータがあるとします。この2次元のデータを2次元の複素フーリエ成分に変換することが目的です。(私の分野では波数空間への展開ということになり、複素数ですから位相情報も含まれることになります。) 例えば、x,y方向に16x16のデータあるとすると、 do j=1,16 ここでjを固定してi:1~16の実数データについて1次元のFFTをかける。 このとき、FFTにかける16個の実数データを複素数の実部に入れて、虚部はゼロとする。 FFTの出力も複素数となっている。 ここで出てくる複素フーリエ変換の結果は実部・虚部で前半(0~7)であり、後半(8~15)はその対称とか点対称(符号が逆)とかになっている(虚部をゼロとしているから)。それを複素数の2次元配列として保存する。 enddo 次いで、 do i=1,16 iを固定してj方向にFFTをかける。このとき、FFTに放り込むデータは上記の複素フーリエ変換の出力結果である2次元データを使う。具体的には複素数の2次元データをj方向の1次元の複素数配列にコピーしてFFTをかけて、その出力結果を新たな2次元配列の複素数に保存する。 enddo この結果、得られた2次元の複素数のデータが、私の所望のデータである、ということです。 式が指し示すとおりのことをすればいいのだ、ということに尽きるのだろうと思いますが、アルゴリズム的にアンバランスのように見えてこれでいいのかなと思えてしまいます。最初に虚部をゼロにするというようなこととかです。そのため確信が持てません。また、結果を見てもわかりにくい面があります。 このような考え方で実装するということいいのでしょうか。全く間違っているでしょうか。もしその場合、考え方の間違いを指摘して頂けると助かりますが(根本的な間違いだったら指摘しようがないということにもなりますが。) また、例えば、始めから実数の2次元配列をすぐに2次元複素数の実部に入れて、虚部をゼロとしてそこからコード方がすっきりするのかなと思いますが。 この辺が確定すると、3次元は同じことということになります。 サンプルコードがネットに出ているという面もありますが、自分でやる方が組み込みやすいのでお尋ねしました。 長文で申し訳ありませんが、よろしくお願いします。

  • vb6で覚えたことがvb2010で活かせれない。。

    グラフの目盛表示をしたくて、 vb2010で下記のコードを入力したのですが、何回やってもエラーがでます。 どなたか教えてください。 --------------------------------- J = 0 For I = 0 To 200 Step 40 CurrentX = 120 CurrentY = 100 + I strB = CStr(0.2 - (2 / 5) * J * 0.1) Print strB J = J + 1 Next J = 0 For I = 0 To 200 Step 40 CurrentX = 120 CurrentY = 300 + I strB = CStr(0 - (2 / 5) * J * 0.1) Print strB J = J + 1 Next -------------------------------------

  • FFTをc言語でプログラミング

    助けてください↓c言語でFFTをプログラミングしているのですがバグが発見できずに困り果て居ます。 プログラミングは以下の通りです。画像はカラーではなく、グレースケールのMANDRILLに対して行っています。 for(n=0;n<M;n++){    for(i=0;i<N;i++){ for(j=0;j<N;j++){ Imbatx[n][i][j]=0; } } } //行FFT //まずはソート for(i=0;i<N;i++){ int x=1; for(j=0;j<N;j++){ if(j<N/2){        //左半分 if(j%2!=0) //jが奇数 batx[0][i][j]=imagein[i][j+N/2-1]; if(j%2==0) //jが偶数 batx[0][i][j]=imagein[i][j]; } if(N/2<=j && j<N){ //右半分 if(j%2!=0) //jが奇数 batx[0][i][j]=imagein[i][x+N/2-1];      if(j%2==0) //jが偶数 batx[0][i][j]=imagein[i][x]; x++; } } } for(i=0;i<N;i++){ for(n=1;n<M+1;n++){ k=0; for(j=0;j<N;j++){ mul=(int)pow(2.0,(double)n); if(j%mul < mul/2){ //偶数列 batx[n][i][j] = batx[n-1][i][j]+cos(2*PI*k/mul)*batx[n-1][i][j+mul/2]- sin(2*PI*k/mul)*Imbatx[n-1][i][j+mul/2]; Imbatx[n][i][j]=Imbatx[n-1][i][j]+sin(2*PI*k/mul)*batx[n-1][i][j+mul/2]+ cos(2*PI*k/mul)*Imbatx[n-1][i][j+mul/2]; k++; } else{ //奇数列 batx[n][i][j] = cos(2*PI*k/mul)*batx[n-1][i][j] + batx[n-1][i][j-mul/2]- sin(2*PI*k/mul)*Imbatx[n-1][i][j]; Imbatx[n][i][j]=Imbatx[n-1][i][j-mul/2]+sin(2*PI*k/mul)*batx[n-1][i][j]+cos(2*PI*k/mul)*Imbatx[n-1][i][j]; k++; } Re_countx[i][j] = batx[M][i][j]; Im_countx[i][j] = Imbatx[M][i][j]; } } } for(i=0;i<N;i++){ for(j=0;j<N;j++){ FFT[i][j]=pow(pow(Re_countx[i][j],2)+pow(Im_countx[i][j],2),0.5); FFT[i][j]=log10(FFT[i][j]); if(FFT[i][j]>max) max=FFT[i][j]; imageout[i][j]=(unsigned char)255*FFT[i][j]/max; } } 結果的に出力される画像は以下の画像になります。 ごらんのように縞模様が出てしまいます。 分かる方どうかお願いいたします。

  • VB2005での画像処理

    各ピクセルの色情報を取得し,そのままコピーするプログラムです. 同じ大きさのPictureBox1とPictureBox2,それとButton1があります. エラーや警告は出ませんが,Button1をクリックしてもまったく動きません. 最終的にはPictureBox1を画像処理してPictureBox2に結果を表示させたいのですが,そのままコピーも出来ないため原因を探しています. A = picture1.GetPixel(i, j).ToArgb() picture2.SetPixel(i, j, color.FromArgb(A)) ではだめなのでしょうか.ご教授ください. -----以下プログラム------ Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim i As Integer Dim j As Integer Dim A As Integer Dim picture1 As New Bitmap(PictureBox1.Image) Dim picture2 As New Bitmap(PictureBox2.Image) For j = 0 To PictureBox1.Width - 1 For i = 0 To PictureBox1.Height - 1 A = picture1.GetPixel(i, j).ToArgb() picture2.SetPixel(i, j, color.FromArgb(A)) Next Next End Sub

  • Cプログラムによる画像の高速フーリエ変換FFT

    Cプログラムにる画像処理について教えてください。逆高速フーリエ変換(IFFT)によって周波数領域から実空間領域に変換する際、周波数帯域を(低周波数領域に)制限してIFFTを実行できるという文献があるのですが可能でしょうか?通常の逆離散フーリエ変換(IDFT)では可能でした。 以下のコードの修正で可能でしょうか? 例) 512*512の空間周波数領域データを212*212(仮に)の低周波数領域に帯域制限してIFFTで画像に戻したいのです。 以下の以下の一次元FFTコードを用いてX方向とY方向にIFFTしたいと考えています。 void FFT(int ir, int nx, float *xr, float *xi, float *si, float *co, unsigned short *brv) // 1次元フーリエ変換 // int ir; 順変換(1)と逆変換(-1) // int nx; 1次元FFTのデータ数 // float *xr; 実部のデータ xr[nx] // float *xi; 虚部のデータ xi[nx] // float *si; FFT用のサインデータ si[nx/2] // float *co; FFT用のコサインデータ co[nx/2] // unsigned short *brv; FFT用の入れ替えデータ brv[nx] { int i, j, n1, n2=nx, j3, j4, k, l, ll, d=1, g; float a, b, c, s; for(l = 1; l <= nx/2; l *= 2, d += d) { g = 0; ll = n2; n2 /= 2; for(k = 1; k <= n2; k++) { n1 = k-ll; c = co[g]; s = -ir*si[g]; g += d; for(j = ll; j <= nx; j += ll) { j3 = j+n1-1; j4 = j3+n2; a = xr[j3]-xr[j4]; b = xi[j3]-xi[j4]; xr[j3] += xr[j4]; xi[j3] += xi[j4]; xr[j4] = c*a+s*b; xi[j4] = c*b-s*a; } } } 通常のDFTでの帯域制限はこのように行い可能でした。 void fourier1d(int ir, float *fr, float *fi, int nx) { int i, j, n = 1; float *gr, *gi; double u, x; gr = (float *)malloc((unsigned long)nx*sizeof(float)); gi = (float *)malloc((unsigned long)nx*sizeof(float)); for(i = 0 ; i < nx ; i++) { u = i-nx/2; gr[i] = gi[i] = 0; for(j = 150 ; j < 362 ; j++) { x = j-nx/2; gr[i] += (float)( fr[j]*cos(2*PI*u*x/nx)+ir*fi[j]*sin(2*PI*u*x/nx)); gi[i] += (float)(-ir*fr[j]*sin(2*PI*u*x/nx)+fi[j]*cos(2*PI*u*x/nx)); } } if(ir == -1) n = 212; // 逆変換はデータ数で割る for(i = 0 ; i < nx ; i++) { fr[i] = gr[i]/n; fi[i] = gi[i]/n; } free(gr); free(gi); }

  • C言語でのFFTについて

    http://tsuyu.cocolog-nifty.com/blog/2007/03/publi.html に掲載されているVBAのFFTプログラムをC言語に書き換えて 実行しているのですがうまくいきません。 どこが、間違っているか教えてください。 ======以下FFTのサブルーチンソースコード===== void FFT(float Xr[], float Xi[]) { i=0,j=0,k=0,l=0,m=0,n=0,p=0,q=0; n=DN; m = log10(n)/log10(2); Table(c,s); l=n,h=1; for(g=1;g<=m;g++){ l/=2,k=0; for(q=1;q<=h;q++){ p=0; for(i=k;i<=l+k-1;i++){ j=i+l; a=Xr[i]-Xr[j], b=Xi[i]-Xi[j]; Xr[i] = Xr[i] + Xr[j], Xi[i] = Xi[i] + Xi[j]; if(p==0){ Xr[j]=a,Xi[j]=b; }else{ Xr[j] = a * c[p] + b * s[p], Xi[j] = b * c[p] - a * s[p]; } p+=h; } k+=l+l; } h+=h; } j=n/2; for(i=1;i<=n-1;i++){ k=n; if(j<i){ //ビットリバース swap(&Xr[i],&Xr[j]); swap(&Xi[i],&Xi[j]); } k=k/2; while(j>=k){ j=j-k; k /=2; } j = j + k; } }

  • C言語FFTからのパワースペクトル表示の質問

    手元にはC言語で作成したFFT/IFFTの処理を行うプログラムがあります。FFT,IFFTともに1次元です。 それを使って、図の信号をフーリエ変換し、パワースペクトルを図示できません。 どうすればいいでしょうか? できたら、結果も含めて教えてください。 詳細は画像を張ります。

  • Excel VBAライフゲーム

    ExcelのVBAでライフゲームを作りたいのですが、次のプログラムの途中以降がわかりません。 もしよろしければ、このつづきの簡単な実行できるVBAライフゲームを教えてください。 続きのプログラムを教えていただけたら幸いです。 Option Explicit Const ALIVE As Integer = 1 Const DEAD As Integer = 0 Const SIZE As Integer = 19 Const Tmax As Integer = 100 Dim C(SIZE, SIZE) As Integer Sub LifeGame() Dim InitRate As Single Dim T As Integer Dim N As Integer Dim Cnext(SIZE, SIZE) As Integer Dim I As Integer, J As Integer InitRate = -1 Do While InitRate < 0 Or 1 < InitRate Loop For I = 0 To SIZE For J = 0 To SIZE If Rnd() < InitRate Then C(I, J) = ALIVE Else C(I, J) = DEAD End If Next J Next I For T = 1 To Tmax For I = 0 To SIZE For J = 0 To SIZE If C(I, J) = ALIVE Then Cells(I + 1, J + 1).Value = "■" Else Cells(I + 1, J + 1).Vallue = "" End If Next J Next I For I = 0 To SIZE For J = 0 To SIZE N = Count(I, J) Next J Next I For I = 0 To SIZE For J = 0 To SIZE C(I, J) = Cnext(I, J) Next J Next I Next T End Sub Function Count(I As Integer, J As Integer) As Integer End Function

  • VB2010でのコントロール多次元配列について

    教えてください。 実行中にコントロールを生成したいのですが、 Public Class Form1  Private myTxt(,) As System.Windows.Forms.TextBox  Me.myTxt = New System.Windows.Forms.TextBox(59, 2) {}  Dim i As Integer  Dim j As Integer  Dim h As Integer  Dim p As Integer  h = 10  p = 100  For i = 0 To Me.myTxt.GetLength(0) - 1   For j = 0 To Me.myTxt.GetLength(1) - 1    Me.myTxt(i, j) = New System.Windows.Forms.TextBox    Me.myTxt(i, j).Name = "myTxt" + i.ToString() + j.ToString()    Me.myTxt(i, j).Size = New Size(100, 30)    Me.myTxt(i, j).Location = New Point(p, h)    p = p + 100   Next j   h = h + 30  Next i  Me.myPnl.Controls.AddRange(Me.myTxt) と書くと最後の行が波線になり、 “型 'System.Windows.Forms.TextBox の 2 次元配列' の値を 'System.Windows.Forms.Control' に変換できません。”とエラーになります。 これはAddRangeは多次元配列に使用できないということなのでしょうか? 色々検索してみましたが、コントロールの生成に関する多次元配列が見つけられずに 困っていました。 最後のAddRange(Me.myTxt)をAdd(Me.myTxt(i,j))などと変えたりしても別のエラーになり、 基本的に間違っている気がしますがどこだかがわかりません。 詳しい方、宜しくお願い致します。