Is it possible to 'interpolate' in FFT data?
Show older comments
We kmow OTF and PSF are continuous, can be interpolate inside it (<cutoff freq ) even when we express them wIth matrix use integer row&col coordinate .
now I have a image, and get its FFT2, and find some feature like max or min only with row and col,
but I know true max or min not at that integer row and col exactly, It is really at a fraction position near that integer row and col in matrix.
How to get it if I know fraction or decimal position ?
In frequency domain, can exten matrix size with 0, but can not interpolate although we can interpolate at time domain.
How to do ?
Maybe I can do so like such method : in time domain , matrix .* with exp( - j ke), {ke is a decimal number part }, to realize freq shift effect, after that, FFT, now at that row&col coordinate really is a value corresponding to [ row&col + decimal ke ] position, so I get it .
Such idea is right ? I am not expert at FFT, who can tell me , Is it Right ?
or how to find the feature not exactly at discrete integer row&col coordinate ?
I need some value at real flot number row&col coordinate ?
-----------------------------------------------------------------------------------------------------------------
I mean :
For simple example:
there are 512 data point with coordinate 1~512, transfer to freq domain with FFT, it is 512 mag and phase with coordinate -256~255 * 1/256 .
now if I specially add a cosine wave with freq 10.324 *1/512 to 512 data point (I used it as a special inner reference), then transfer to freq domain with FFT.
here , how to find mag and phase information of this added cosine wave in freq domain ?
freq 10.324 , is not a integer -256~255 coordinate, so how to find it ?
now sample code in 1D list below. ( I need work in 2D in real world) : Is it possible? how?
% Time domain
t = linspace(1,512,512);
g = 2*sin(2*pi*t*16/512) + 0.5*sin(2*pi*t*64/512)+ 0.4*sin(2*pi*t*128/512);
% g = 2*sin(2*pi*t*16/512);
gadd = g+0.2*cos(2*pi*t*180.327/512);
% gadd = g + sin(2*pi*t*10.327/512);
% now add 180.324 or can be any another not N/512
subplot(2,2,1);
plot(g);
title("Time domain 3 sin")
subplot(2,2,2);
plot(g);
title("Time domain, 3 sin + cos")
% freq domain
fco = linspace(-256,255,512);
F=fftshift(fft(g));
F1=fftshift(fft(gadd));
subplot(2,2,3);
stem (fco,real(F));
title("Freq domain, 3 sin")
subplot(2,2,4);
stem (fco,real(F1));
title("Freq domain, 3 sin + cos")
% how to find that 180.327 accuratly ?
% watch freq plot, this wave's energe distrbute on 180 and 181 two point,but how to get 180.327 's ?
% condition : prior I know that freq wave inside them , how to get its information like mag or phase ?
% Maybe should I use Fourier formula directly by myself ?
% like result = sum(data.*exp(-i*2*pi*k*t));
% k is I needed freq, only not any n/datalength limited by data count --- integer numbers!
% if try :
result = sum(gadd.*exp(-1i*2*pi*t*180.327/512));
% now get result is 50.2839072265070 - 0.424971233625617i
% How relate this complex number with wave's Amp=0.2, and phase =0 ?
% try try
Amp=2*real(result)/512;
theta=angl(result);
% get 0.196 and -0.0085, compare with 0.2 and 0,
% not too bad, % I will try other..... Maybe OK can be usded.
% but still do not know how to do for 2D ? my god !
15 Comments
Rik
on 23 Jan 2025
It doesn't sound like it is really relevant that your data represents the result of an FFT. It sounds like you want to fit a surface to your data (at least locally) to find the location of a maximum on a sub-pixel level. Can you post the 2D array along with the code you tried so far?
Adam
on 23 Jan 2025
I don't understand a lot of what you are asking, but yes, in theory you can interpolate in the frequency domain just as you can in the time domain. It comes with the same caveats, that you are effectively introducing data where there wasn't any before, using an algorithm of your choice (e.g. linear, pchip, spline, etc), but so long as the frequency space is relatively smooth (as has been the case when I have interpolated in it) it is no different to interpolating in any other space, such as the time domain.
I have interpolated in 2d in the joint time-frequency space in the past, to give 'more accurate' locations of the peaks in that space.
Whether it makes sense in your exact situation or not I couldn't really say, just that in a general case there's no more reason against it than for any other sufficiently smooth domain. Obviously if it isn't smooth then interpolating is always risky, because the true data could be well off what you interpolate.
Mathieu NOE
on 23 Jan 2025
the result of fft2 can be viewed as an image so you could use this fex :
with the sub pixel resolution option (weighted centroids)
xd
on 23 Jan 2025
Star Strider
on 23 Jan 2025
One approach may be to increase the number of frequencies the Fourier transform is evaluated at. The easiest way to do that is to zero-pad the original data. This will increase the frequency resolution of the Fourier transform in the relevant dimension (or dimensions), so you may be able to actually calculate the value you want, rather than needing to interpolate it. Both the fft and fft2 functions offer this option.
The frequency limits themselves will not change, and will of necessity be between zero and the Nyquist frequency in the relevant dimensions. You can restrict these frequency limits after you calculate the Fourier transform, however you cannot exceed them.
The greatest computational effiiciency will result if the size value for fft (or values for fft2), are integer powers of 2, (use the nextpow2 function to determine the closest value, although you may increase it), since that corresponds to the way the Fast Fourier Transform iis coded.
It will be necessary for you to experiment with this in order to get the result you want.
Rik
on 23 Jan 2025
I would suggest reading Star Striders comment carefully, but if you still want to find the peak: a 2D Fourier transform of an image is also still a 2D array. If you are looking for a peak in a 2D array, you can use 2D array tools. Generally those tools will mention images, as that is the most common 2D array. However, the fact that your axes are frequency instead of spatial don't matter much for such functions.
xd
on 23 Jan 2025
Edited: Walter Roberson
on 23 Jan 2025
Rik
on 24 Jan 2025
It is not clear to me who you're replying to and what your currently remaining issue is.
If you have a 2D problem, you should provide a 2D example. I stand by my opinion that you can just use the 2D peak finder. If you want more accuracy than that, you will have to look into what Star Strider told you and not dismiss it out of hand.
Mathieu NOE
on 24 Jan 2025
again , show us a working example if you have it
Essentially the zero padding approach shown here. Will become problematic if any other significant component of the signal has frequency too close to the frequency of the added cosine, in which case I'm not sure what could be done.
% Time domain
%t = linspace(1,512,512);
t = 0:511;
g = 2*sin(2*pi*t*16/512) + 0.5*sin(2*pi*t*64/512)+ 0.4*sin(2*pi*t*128/512);
% g = 2*sin(2*pi*t*16/512);
% add some noise
gadd = g + 0.2*cos(2*pi*t*180.327/512) + .2*randn(size(t));
[h,w] = freqz(gadd,1,2^14);
figure
plot(subplot(211),w*512/2/pi,real(h))
xline(180.327);
plot(subplot(212),w*512/2/pi,imag(h))
xline(180.327)
copyobj(get(gcf,'children'),figure);
set(get(gcf,'Children'),'XLim',[175,185])
xd
on 26 Jan 2025
Edited: Walter Roberson
on 26 Jan 2025
Originally, I thought the issue is that you don't really know the frequency of the added reference wave and that you're trying to find it through spectral analysis, hence the suggested computation of the DTFT of the signal using freqz, which could also be done with fft with zero-padding.
If you know that the reference frequency is 180.327/512 cycles/sample, then I suppose we are trying to estimate the reference wave's amplitude and phase. If that's the case, then your approach is reasonable, as long as the original signal is sufficiently separated in frequency from the reference and you correct for the amplitude and phase induced by the rectangular window at the reference frequency.
rng(100);
t = 0:511;
g = 2*sin(2*pi*t*16/512) + 0.5*sin(2*pi*t*64/512)+ 0.4*sin(2*pi*t*128/512);
% g = 2*sin(2*pi*t*16/512);
% add some noise
noise = 0.2*randn(size(t));
gadd = g + 0.2*cos(2*pi*t*180.327/512) + noise;
% freqz approach. Need to call with at least two frequencies
tic
h1 = freqz(gadd,1,2*pi*180.327/512*[1 1]);h1 = h1(1,1);
toc
timeit(@() freqz(gadd,1,2*pi*180.327/512*[1 1]) )
% sum approach
tic
h2 = sum(gadd.*exp(-1i*2*pi*t*180.327/512));
toc
timeit(@() sum(gadd.*exp(-1i*2*pi*t*180.327/512)))
sum is about an order of magnitude faster using either timeit or tic/toc. Curious as to why the timeit times are two orders of magnitude lower.
The results are pretty close to each other.
format long e
h1-h2
Star Strider
on 27 Jan 2025
‘Interpolating’ risks creeating data that did not previously exist.
If you zero-pad before calculating the Fourier transform, you increase the frequency resolution of the transform. Those will be the actual, calculated results at more frequencies, so no interpolation is necessary, and you do not create data where none previously existed.
Accepted Answer
More Answers (0)
Categories
Find more on Spectral Measurements in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!





