# Why does the 2D-DFT of a sinus gradient not show energy along the diagonal straigh lines and only vertical/horizontal from the diagonal point?

I have been experimenting a little bit with simple examples of the 2D DFT to get a better sense for it's interpretation.

For this purpose I have been using sinus gratings with the following code:

import matplotlib.pyplot as plt

x = np.arange(-500, 501, 1)
X, Y = np.meshgrid(x, x)
wavelength = 100
angle = np.pi/9
# use np.sign(np.sin(...)) for square wave grating instead of sine wave grating
grating = np.sin(
2*np.pi*(X*np.cos(angle) + Y*np.sin(angle)) / wavelength
)

plt.set_cmap("gray")
plt.subplot(131)
plt.imshow(grating)
plt.axis("off")

ft = np.fft.ifftshift(grating)
ft = np.fft.fft2(ft)
ft = np.fft.fftshift(ft)
plt.subplot(132)
plt.imshow(abs(ft))
plt.axis("off")
plt.xlim([480, 520])
plt.ylim([520, 480])

plt.show()

Now I get the following outcome:

So my question is why I am not getting further diagonal frequencies for the image with the rotated sine grating from the points on the diagonal line? It only has energiy along the horizontal and vertical axes. Where does this energy come from?

• The origin is in the middle of the image, you have two peaks on either side of the origin, they sit on a line at an angle parallel to the direction of the sine wave. It is unclear to me why you say there is only energy along horizontal and vertical axes, because the axes are blank. Jan 11, 2022 at 1:02
• thats right maybe putting it another way why do the points at diagonal line have energy along vertical and horizontal lines and not along the diagonal line? Thanks, I clarified the question. Jan 11, 2022 at 7:47
• Oh, you're referring to the streaks coming out of the two peaks. Did you look at the output of np.fft.ifftshift(grating)? It will contain a horizontal and vertical line where the sinus wave doesn't match up. If you apply a window function to your image first, you will strongly reduce the horizontal and vertical streaks. Jan 11, 2022 at 8:30
• No I haven't I am actually still wondering what the point of performing np.fft.ifftshift(grating) first is, because without this line I get the same result just less blurrly in some cases. Do you know what the point of performing the window function here is? I am not familiar with their application. Jan 11, 2022 at 8:58

One way to interpret the DFT, that I personally find most useful, is by comparing it to the DTFT (Discrete Tome Fourier Transform, which has an infinite input domain) of a repeated function. That is, imagine tiling your image out to infinity, and applying the DTFT, to obtain a periodic, continuous Fourier domain that you then sample. Because of the periodicity of the input, the output is a pulse train, so by sampling we only discard the parts of the function that have a zero value.

With this mental model, look at your input: a repeating version of your input image. At the edges between repetitions there is a discontinuity, the sine wave in one repetition doesn’t match up correctly to the next one. The output of np.fft.ifftshift(grating) shows you what this looks like, but you can also do np.tile(grating, (2,2)).

The discontinuity at the edges of your image causes the streaks to appear in the DFT.

To avoid this effect, you need to apply a window function to your input:

ft = grating * np.hamming(grating.shape)
ft = np.fft.fft2(ft)
ft = np.fft.fftshift(ft)

Note that you don’t need to apply ifftshift to the input in this case, that is only relevant for the convolution kernel when computing a convolution through the DFT. It only changes the phase in the frequency domain (because it introduces a shift in the spatial domain), and you plot the absolute values, discarding that phase. So the result is identical with of without the shift.