Furijeova 2D transformacija

miroslav.demic

Početnik
Poruka
3
Молим Вас да ми помогнете око програмирања Фуријеове 2Д трансформације у паскалу. У том смислу дајем Вам изворни код у C. Унапред захвалан.



Well, according to the amount of E-mail I received, and as I cannot
answer to all of them, I am posting the 2D FFT program I have written in C.

How to use it : first, it can be used only on matrix of the type
complexe, as defined at the begining of the program, with a size in
2^maxlevel (2 power maxlevel). One just have to call the program as following :

InvFFT(matrix,maxlevel);

As you have noticed, it is in fact an Inverse Fourier Transform
(sampling matrix in the frequency space -> matrix of heights) which
is performed, but just an initialisation line at the begining of the
procedure InvFFT has to be change to obtain the FFT :

Omega = 2 * M_PI / dimension; must be change into
Omega = - 2 * M_PI / dimension;


I am clearly aware that this program has not been optimised as it
could be, mainly in order to keep the the clarity of the algorithm, but I am
open to any suggestion that you could make in order to improve the process.

I have tested it in a fractal landscape project and it seems to work
correctly (when there were bugs in it such as forgetting the multiplication
of omega by two at the recursive calls, I had funny landscapes looking like
a micro-chip seen through an electronic microscop).

Well, I think that is all, for the moment. Here comes the program.

Note : you will have probably to cut the signature at the end of the
file as well.

Jean-Marc

----cut here -----cut here -----cut here -----cut here -----cut here -----

/* It is a pity I have to add this notice, but it must be done. */

/* NOTICE *
* Copyright (c) 1990, Jean-Marc de Lauwereyns *
* for the procedures mirror, RecFFT, InvFFT. *
* These procedures can be used and given freely to anybody but can not *
* be sold or used in any commercial program or in any book without the *
* permission of the original author. *
* These procedures can be modified at the condition that the nature of *
* modification is mentioned in comments at the place of the modification *
* with the original lines accompanied by the name of the original author.*
* This notice itself can not be removed or modified except by the *
* original author himself. */

/* you must have included the file /usr/include/math.h at the begining of *
* your program */

typedef struct {
double a,b;
} complexe;

/****************************************************/
/* function mirror just transform the binary */
/* representation of an integer into its mirror */
/* binary representation on maxlevel bits */
/* eg : with maxlevel = 6, 000101 becomes 101000 */
/****************************************************/
int mirror(index,maxlevel)
int index;
int maxlevel;
{
register int i;
int res;

res = 0;
for (i=0;i<maxlevel;i++)
{
res = (res << 1) | (index & (int)1);
index = (index >> 1);
}
return(res);
}

/*****************************************************/
/* recursive procedure to calculate the FFT on 2^N */
/*****************************************************/
void RecFFT(A,k,l,p,q,Omega)
complexe **A;
int k,l; /* indexes for the begin and the end on the lines taken */
int p,q; /* indexes for the begin and the end of the columns taken */
double Omega;
{
int i,j,m;
complexe a,b,c,d;
double argument[3];

if (k != l)
{
m = (l-k)/2;

for (i = k;i < k + m;i++)
{
argument[0] = Omega * (double)(i-k);
for (j = p;j < p + m;j++)
{
argument[1] = Omega * (double)(j-p);
argument[2] = Omega * (double)(i-k + j-p);

a.a = A[j].a;a.b = A[j].b;
b.a = A[i+m][j].a;b.b = A[i+m][j].b;
c.a = A[j+m].a;c.b = A[j+m].b;
d.a = A[i+m][j+m].a;d.b = A[i+m][j+m].b;

A[j].a = a.a + b.a + c.a + d.a;
A[j].b = a.b + b.b + c.b + d.b;

A[i+m][j].a = (a.a - b.a + c.a - d.a)*cos(argument[0]) -
(a.b - b.b + c.b - d.b)*sin(argument[0]);
A[i+m][j].b = (a.a - b.a + c.a - d.a)*sin(argument[0]) +
(a.b - b.b + c.b - d.b)*cos(argument[0]);

A[j+m].a = (a.a + b.a - c.a - d.a)*cos(argument[1]) -
(a.b + b.b - c.b - d.b)*sin(argument[1]);
A[j+m].b = (a.a + b.a - c.a - d.a)*sin(argument[1]) +
(a.b + b.b - c.b - d.b)*cos(argument[1]);

A[i+m][j+m].a = (a.a - b.a - c.a + d.a)*cos(argument[2]) -
(a.b - b.b - c.b + d.b)*sin(argument[2]);
B[i+m][j+m].b = (a.a - b.a - c.a + d.a)*sin(argument[2]) +
(a.b - b.b - c.b + d.b)*cos(argument[2]);
}
}
if (m != 0)
{
RecFFT(k,k+m,p,p+m,Omega*2);
RecFFT(k+m,l,p,p+m,Omega*2);
RecFFT(k,k+m,p+m,q,Omega*2);
RecFFT(k+m,l,p+m,q,Omega*2);
}
}
}

/********************************************************/
/* InvFFT is a procedure which produce the inverse of */
/* Fourier Transformation. */
/********************************************************/
void InvFFT(A,interlevel)
complexe **A;
int interlevel;
{
int dimension;
int i,j,i1,j1;
double coeff,Omega;

dimension = (1 << interlevel);
Omega = 2 * M_PI / dimension;
RecFFT(A,0,dimension,0,dimension,Omega);

for (i=0;i<=(dimension - 1);i++)
/* swap every rows i with its mirror image */
{
i1 = mirror(i,interlevel);
if (i1 > i) /* if i1 <= i, the swaaping have been already made */
for (j=0;j<dimension;j++)
{
coeff = A[j].a;
A[j].a = A[i1][j].a;
A[i1][j].a = coeff;

/* this may be remove if you are sure that the result is a *
* matrix of real which means that the original matrix must *
* verify the following conditions : *
* ______ ______ *
* A(N-i,N-j) = A(i,j) , A(0,N-j) = A(0,j) *
* ______ *
* A(N-i,0) = A(i,0) for i,j > 0 and A(0,0) is a pure *
* real */

coeff = A[j].b;
A[j].a = A[i1][j].a;
A[i1][j].a = coeff;
}
}

for (j=0;j<=(dimension - 1);j++) /* idem for the columns */
{
j1 = mirror(j,interlevel);
if (j1 >j)
for (i=0;i<dimension;i++)
{
coeff = A[j].a;
A[j].a = A[j1].a;
A[j1].a = coeff;

/* part which may be removed if (see above) */
coeff = A[j].b;
A[j].b = A[j1].b;
A[j1].b = coeff;
}
}
}

----cut here -----cut here -----cut here -----cut here -----cut here ----
Jean-Marc de Lauwereyns | ____ | e-mail addresses :
Heriot-Watt University | |\ /| | \ | JANET: lauwer@uk.ac.hw.cs
Computer Science Department | | \/ | |___/ | ARPA.: lauwer@cs.hw.ac.uk
Edinburgh | \___/ |___| \ |
 
Да бих Вам помогао, прилажем и изворни код у Фортрану.



ccccccccccccccccccccccccc Program 5.3 cccccccccccccccccccccccccc
c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c c
c Please Note: c
c c
c (1) This computer program is part of the book, "An Introduction to c
c Computational Physics," written by Tao Pang and published and c
c copyrighted by Cambridge University Press in 1997. c
c c
c (2) No warranties, express or implied, are made for this program. c
c c
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c
SUBROUTINE FFT2D (FR,FI,N1,N2,M1,M2)
C
C Subroutine for the two-dimensional fast Fourier transform
C with N=N1*N2 and N1=2**M1 and N2=2**M2.
C
DIMENSION FR(N1,N2), FI(N1,N2), GR(N1), GI(N1)
C
C Transformation on the second index
C
DO 100 I = 1, N1
CALL FFT (FR(I,1),FI(I,1),N2,M2)
100 CONTINUE
C
C Transformation on the first index
C
DO 250 J = 1, N2
DO 230 I = 1, N1
GR(I) = FR(I,J)
GI(I) = FI(I,J)
230 CONTINUE
CALL FFT (GR,GI,N1,M1)
DO 240 I = 1, N1
FR(I,J) = GR(I)
FI(I,J) = GI(I)
240 CONTINUE
250 CONTINUE
RETURN
END
C
SUBROUTINE FFT (AR,AI,N,M)
C
C An example of the fast Fourier transform subroutine with
C N = 2**M. AR and AI are the real and imaginary part of
C data in the input and corresponding Fourier coefficients
C in the output.
C
DIMENSION AR(N),AI(N)
C
PI = 4.0*ATAN(1.0)
N2 = N/2
C
N1 = 2**M
IF(N1.NE.N) STOP 'Indices do not match'
C
C Rearrange the data to the bit reversed order
C
L = 1
DO 150 K = 1, N-1
IF(K.LT.L) THEN
A1 = AR(L)
A2 = AI(L)
AR(L) = AR(K)
AR(K) = A1
AI(L) = AI(K)
AI(K) = A2
ENDIF
J = N2
DO 100 WHILE (J.LT.L)
L = L - J
J = J/2
100 END DO
L = L + J
150 CONTINUE
C
C Perform additions at all levels with reordered data
C
L2 = 1
DO 200 L = 1, M
Q = 0.0
L1 = L2
L2 = 2*L1
DO 190 K = 1, L1
U = COS(Q)
V = -SIN(Q)
Q = Q + PI/L1
DO 180 J = K, N, L2
I = J + L1
A1 = AR(I)*U - AI(I)*V
A2 = AR(I)*V + AI(I)*U
AR(I) = AR(J) - A1
AR(J) = AR(J) + A1
AI(I) = AI(J) - A2
AI(J) = AI(J) + A2
180 CONTINUE
190 CONTINUE
200 CONTINUE
RETURN
END
END
 
Проблем се може усложити тако да се посматра функција од н променљивих. Прилажем подпрограм у Паскалу. Може ли неко да израчуна модуо и фазни угао за овај случај? Унапред се захваљујем.

PROCEDURE fourn(VAR data: gldarray; nn: glnnarray; ndim,isign: integer);
(* Programs using routine FOURN must define the types
TYPE
gldarray = ARRAY [1..ndat2] OF real;
glnnarray = ARRAY [1..ndim] OF integer;
where ndat2 is twice the product of the transform lengths nn(i). *)
VAR
i1,i2,i3,i2rev,i3rev,ibit,idim: integer;
ip1,ip2,ip3,ifp1,ifp2,k1,k2,n: integer;
ii1,ii2,ii3: integer;
nprev,nrem,ntot: integer;
tempi,tempr: real;
theta,wi,wpi,wpr,wr,wtemp: double;
BEGIN
ntot := 1;
FOR idim := 1 TO ndim DO BEGIN
ntot := ntot*nn[idim]
END;
nprev := 1;
FOR idim := 1 TO ndim DO BEGIN
n := nn[idim];
nrem := ntot DIV (n*nprev);
ip1 := 2*nprev;
ip2 := ip1*n;
ip3 := ip2*nrem;
i2rev := 1;
FOR ii2 := 0 TO ((ip2-1) DIV ip1) DO BEGIN
i2 := 1+ii2*ip1;
IF (i2 < i2rev) THEN BEGIN
FOR ii1 := 0 TO ((ip1-2) DIV 2) DO BEGIN
i1 := i2+ii1*2;
FOR ii3 := 0 TO ((ip3-i1) DIV ip2) DO BEGIN
i3 := i1+ii3*ip2;
i3rev := i2rev+i3-i2;
tempr := data[i3];
tempi := data[i3+1];
data[i3] := data[i3rev];
data[i3+1] := data[i3rev+1];
data[i3rev] := tempr;
data[i3rev+1] := tempi
END
END
END;
ibit := ip2 DIV 2;
WHILE ((ibit >= ip1) AND (i2rev > ibit)) DO BEGIN
i2rev := i2rev-ibit;
ibit := ibit DIV 2
END;
i2rev := i2rev+ibit
END;
ifp1 := ip1;
WHILE (ifp1 < ip2) DO BEGIN
ifp2 := 2*ifp1;
theta := isign*6.28318530717959/(ifp2 DIV ip1);
wpr := -2.0*sqr(sin(0.5*theta));
wpi := sin(theta);
wr := 1.0;
wi := 0.0;
FOR ii3 := 0 TO ((ifp1-1) DIV ip1) DO BEGIN
i3 := 1+ii3*ip1;
FOR ii1 := 0 TO ((ip1-2) DIV 2) DO BEGIN
i1 := i3+ii1*2;
FOR ii2 := 0 TO ((ip3-i1) DIV ifp2) DO BEGIN
i2 := i1+ii2*ifp2;
k1 := i2;
k2 := k1+ifp1;
tempr := sngl(wr)*data[k2]
-sngl(wi)*data[k2+1];
tempi := sngl(wr)*data[k2+1]
+sngl(wi)*data[k2];
data[k2] := data[k1]-tempr;
data[k2+1] := data[k1+1]-tempi;
data[k1] := data[k1]+tempr;
data[k1+1] := data[k1+1]+tempi
END
END;
wtemp := wr;
wr := wr*wpr-wi*wpi+wr;
wi := wi*wpr+wtemp*wpi+wi
END;
ifp1 := ifp2
END;
nprev := n*nprev
END
END;
 

Back
Top