MatLab - Shifting an image using FFT
Asked Answered
E

1

9

I want to shift an image (represented by a 2D matrix) using the multiplication of its fft by exp(-j*2*pi*x*F), where x is the displacement. I have:

input=peaks(200);
H=fftshift(fft2(fftshift(input)));
x=19;
H=H*exp(-1i*x*2*pi*F);
IF_image=fftshift(ifft2(fftshift(H)));
imshow(IF_image)

But I'm having troubles identifying/representing the F in H[F] since my input is a 2 dimensional array. How could I do this? The desired output will be my original image shifted in the horizontal axis (by x units) in the same frame so it would start at x+1. As an example:

If input=

1 2 3 4 5
6 7 8 9 0

and x=2, I want:

4 5 1 2 3
9 0 6 7 8
Enfeoff answered 13/9, 2014 at 21:33 Comment(4)
just saying, isn't it simpler to use circshift?Liven
Yes, it is. But in principle, this can be done using the described method, in which I'm interested. (:Enfeoff
@CeciliaGuerra - I agree with circshift, but I'm assuming you are doing this as a demonstration of the Fourier Transform's translation / shift property. Either way, I've written an answer.Rubble
circshift only helps when you're shifting by an integer number of pixelsKampong
R
14

You identified the property for translation / shifting in 1D. For 2D, it's slightly different but based on the same principle. To achieve the translation in 2D, this is the translation / shift property, which is defined as:

enter image description here

x0,y0 would be the shift you want to introduce. As such, positive value of x0 would shift your 2D signal to the right, while a negative value would shift to the left. Similarly, a positive value of y0 would shift your 2D image downwards, while a negative value would shift upwards.

Therefore, given your Fourier Transform in 2D, you would need to add an additional term to the exponent. In addition, you must normalize by N or the size of your 2D signal. This is assuming that your 2D signal has the same number of rows and columns. If this isn't the case, then you would have to take u*x0 and you would divide by the number of columns and v*y0 would be divided by the number of rows.
Now, the reason why you're confused about F in your above code is because you aren't sure how to define this in 2D. You must define a frequency value for every point in the 2D grid. Because of your fftshift call, we would define the x and y values between -100 and 99, as your 2D signal is of size 200 x 200 and this would centre our 2D signal to be in the middle. This is actually what fftshift is doing. Similarly, ifftshift undoes the centering done by fftshift. To define these points in 2D, I use meshgrid. Once you define these points, you would take each pair of (x,y) co-ordinates, then create the complex exponential as you see in the above property.

As such, your code would have to be modified in this fashion. Bear in mind that I got rid of redundant fftshift and ifftshift calls in your original code. You would call the fft, then do fftshift to centre the spectrum. I also changed your variable input to in, as input is a function in MATLAB, and we don't want to unintentionally shadow the function with a variable.

I've also defined the x shift to be -35, and the y shift to be -50. This will mean that the resultant signal will shift to the left by 35, and up by 50.

Therefore:

in=peaks(200); %// Define input signal
H=fftshift(fft2(in)); %// Compute 2D Fourier Transform
x0=-35; %// Define shifts
y0=-50;

%// Define shift in frequency domain
[xF,yF] = meshgrid(-100:99,-100:99);

%// Perform the shift
H=H.*exp(-1i*2*pi.*(xF*x0+yF*y0)/200);

%// Find the inverse Fourier Transform
IF_image=ifft2(ifftshift(H));

%// Show the images
figure;
subplot(1,2,1);
imshow(in);
subplot(1,2,2);
imshow(real(IF_image));

Take note that I displayed the real component of the resultant image. This is due to the fact that once you take the inverse Fourier Transform, there may be some numerical imprecision and the complex part of the signal is actually quite small. We can ignore this by just using the real component of the signal.

This is the image I get:

enter image description here

As you can see, the image did shift properly, as verified by the property seen above. If you want to specify different shifts, you just need to change x0 and y0 to suit your tastes. In your case, you would specify y0 = 0, then x0 can be whatever you wish as you want a horizontal translation.

Rubble answered 14/9, 2014 at 5:35 Comment(1)
@Sandino - Can't believe I didn't notice that typo. I answered this question so long ago. Thanks for the correction.Rubble

© 2022 - 2024 — McMap. All rights reserved.