How to recreate a FourierDCT from phase and amplitude ?

Hi,

I have two stock tiff images called elaine and lena. Both are 8-bit 512x512. I am trying to show that phase caries more info than the amplitude by following Jim Fienup’s slideshow from here: http://www.eecs.umich.edu/systems/FienupSeminar.pdf
The code is relatively simple:

(* reading the two images in *) 
    elaineTiff = Import["elaine.tiff"];
    elaine = ImageData[ColorNegate[elaineTiff]]; 
    lenaTiff = Import["Lena.tiff"]; 
    lena = ImageData[ColorNegate[lenaTiff ]];
     
    (* Fourier tranform them and calculate amplitude and phase *) 
    elaineFt = FourierDCT[elaine]; 
    lenaFt = FourierDCT[lena]; 
    
    elaineFtAbs = Abs[elaineFt]; 
    lenaFtAbs = Abs[lenaFt]; 
    elaineFtPhase = Table[ArcTan[Im[elaineFt[[i, j]] ]/Re[elaineFt[[i, j]] ] ], {i, 1, Length[elaineFt]}, {j, 1, Length[elaineFt[[i]] ]}]; 
    lenaFtPhase =  Table[ArcTan[Im[lenaFt[[i, j]] ]/Re[lenaFt[[i, j]] ] ], {i, 1, Length[lenaFt]}, {j, 1, Length[lenaFt[[i]] ]}];
    
    (* then matching elaine amplitude to lena phase and vica verse and
     matching elaine amplitude to elaine phase and lena amplitude to lena phase *) 
    elaineFtAbslenaFtPhase = elaineFtAbs*Exp[I*lenaFtPhase ];
    lenaFtAbselaineFtPhase = lenaFtAbs*Exp[I*elaineFtPhase ];
    elaineFtAbselaineFtPhase = elaineFtAbs*Exp[I*elaineFtPhase ];
    lenaFtAbslenaFtPhase = lenaFtAbs*Exp[I*lenaFtPhase ];
    
    (* then using Fourier transform again to convert them back to image space *) 
    elainelena = FourierDCT[elaineFtAbslenaFtPhase]; 
    lenaelaine = FourierDCT[lenaFtAbselaineFtPhase]; 
    elaineelaine = FourierDCT[elaineFtAbselaineFtPhase]; 
    lenalena = FourierDCT[lenaFtAbslenaFtPhase];
    
    (* finally taking the Abs values and display them by Image *)
    {Image[Abs[elainelena] ], Image[Abs[lenaelaine]]}
     {Image[Abs[elaineelaine] ], Image[Abs[lenalena] ]}

I expected to see the original images on the last line, but I did not get that.
What am I doing wrong?

Dear Janos,

Thank you for this interesting question and sorry for the late response!
I think the basic problem in your code is the use of the discrete Fourier cos transformation in general, but specifically: The use of FourierDCT[list] is equivalent with FourierDCT[list, 2] and the inversion of this is FourierDCT[foulist, 3], according to the documentation (“Details”).

A slight modification of your code then works:

ClearAll["Global`*"]
SetDirectory[NotebookDirectory[]];
(*reading the two images in*)
elaineTiff = Import["elaine.tiff"];
elaine = ImageData[elaineTiff];
lenaTiff = Import["Lena.tiff"];
lena = ImageData[lenaTiff];

(*Fourier tranform them and calculate amplitude and phase*)

elaineFt = Fourier[elaine];
lenaFt = Fourier[lena];

elaineFtAbs = Abs[elaineFt];
lenaFtAbs = Abs[lenaFt];
elaineFtPhase = Arg[elaineFt];
lenaFtPhase = Arg[lenaFt];

(*then matching elaine amplitude to lena phase and vica verse and \
matching elaine amplitude to elaine phase and lena amplitude to lena \
phase*)
elaineFtAbslenaFtPhase = elaineFtAbs Exp[I lenaFtPhase];
lenaFtAbselaineFtPhase = lenaFtAbs*Exp[I*elaineFtPhase];
elaineFtAbselaineFtPhase = elaineFtAbs*Exp[I*elaineFtPhase];
lenaFtAbslenaFtPhase = lenaFtAbs*Exp[I*lenaFtPhase];

(*then using Fourier transform again to convert them back to image \
space*)
elainelena = InverseFourier[elaineFtAbslenaFtPhase];
lenaelaine = InverseFourier[lenaFtAbselaineFtPhase];
elaineelaine = InverseFourier[elaineFtAbselaineFtPhase];
lenalena = InverseFourier[lenaFtAbslenaFtPhase];

(*finally taking the Abs values and display them by Image*)
{Image[Abs[elainelena]], Image[Abs[lenaelaine]]}
{Image[Abs[elaineelaine]], Image[Abs[lenalena]]}

I do not agree that in general the phase data contain more information than the amplitude data. The point seems to be that inside certain classes of data (e.g. “pictures”) the spectra are much more similar than the phases. In contrast you might want to try the same with e.g. random data.

Cheers Henrik

To tell the truth, I tried Fourier and InverseFourier before I tried FourierDCT. I think the real problem with my approach was in the phase calculation, because I took in all case the ArcTan[Im[z]/Re[z]] regardless of the sign of them. That was wrong. This line shows it clearly:

In[30]:= Table[
  ArcTan[Im[elaineFt[[i, j]] ]/Re[elaineFt[[i, j]] ] ], {i, 1, 
   Length[elaineFt]}, {j, 1, Length[elaineFt[[i]] ]}] === Arg[elaineFt]

Out[30]= False

Arg[z] probably has the right definition coded in.
Thanks a lot for your help, now I can go further.
With the best,
János

I had meant to mention that. What you might use is the two argument form of ArcTan, that is, ArcTan[x,y].