Question about computing diffraction patterns

  • Context: High School 
  • Thread starter Thread starter Ax_xiom
  • Start date Start date
Join the discussion
Ask a follow-up here, or get your own question answered by working scientists, mathematicians and engineers — people, not an autocomplete.
Real named experts · corrections over time · the nuance an AI answer skips
7 replies · 748 views
Ax_xiom
Messages
79
Reaction score
4
So I'm using python to compute the fourier transform of a black and white image and the images I've been getting have been different to what I expected.

Input image:
HubbleOutline.webp

Output FFT:
1784331567482.webp

What I expected:
1784331703537.webp

Image from MinutePhysics's video Why are Stars Star-Shaped?

So why is there a difference?
 
Physics news on Phys.org
The aperture of Hubble is round and the spider legs are connected to it. With the aperture function you've drawn you are not modelling the telescope tube at all, just the secondary and its legs floating in empty space. I suspect you have the spider legs too thick as well, although I haven't checked. Try something more like this:
4a58f1a5-c3e9-480d-8a23-c1703be72747.webp

Also remember that numeric computation does a discrete FFT, not a continuous one. Are you padding and block swapping your aperture function before the transform?
 
Last edited:
Reply
  • Like
Likes   Reactions: sbrothy
Ibix said:
Try something more like this:
I tried it and I get this:
1784371521557.webp

Which does have the same general structure as what I'm aiming for, but doesn't "glow" as much
Ibix said:
Are you padding and block swapping your aperture function before the transform?
Here is the code I'm using, I'm not sure if it uses block swapping
 
Blockswapping is what fftshift does. You want the center of the aperture at [0,0] before the FFT.

The page you linked is a generic page about doing FFTs. It would probably help if you posted your actual code. You can use code=python tags like this:
Python:
print("Hello world!")
 
Ibix said:
Blockswapping is what fftshift does. You want the center of the aperture at [0,0] before the FFT.
I'll create a new image with the centre at 0,0 so no shifting is required.
Ibix said:
The page you linked is a generic page about doing FFTs. It would probably help if you posted your actual code. You can use code=python tags like this:
Here it is:
Python:
# fourier_synthesis.py

import numpy as np
import matplotlib.pyplot as plt

image_filename = "HubbleOutline10.jpg"

def calculate_2dft(input):
    ft = np.fft.ifftshift(input)
    ft = np.fft.fft2(ft)
    return np.fft.fftshift(ft)

# Read and process image
image = plt.imread(image_filename)
image = image[:, :, :3].mean(axis=2)  # Convert to grayscale

plt.set_cmap("gray")

ft = calculate_2dft(image)

plt.subplot(121)
plt.imshow(image)
plt.axis("off")
plt.subplot(122)
plt.imshow(abs(ft)**0.5)
plt.axis("off")
plt.show()
 
Ax_xiom said:
I'll create a new image with the centre at 0,0 so no shifting is required.

Here it is:
Python:
# fourier_synthesis.py

import numpy as np
import matplotlib.pyplot as plt

image_filename = "HubbleOutline10.jpg"

def calculate_2dft(input):
    ft = np.fft.ifftshift(input)
    ft = np.fft.fft2(ft)
    return np.fft.fftshift(ft)

# Read and process image
image = plt.imread(image_filename)
image = image[:, :, :3].mean(axis=2)  # Convert to grayscale

plt.set_cmap("gray")

ft = calculate_2dft(image)

plt.subplot(121)
plt.imshow(image)
plt.axis("off")
plt.subplot(122)
plt.imshow(abs(ft)**0.5)
plt.axis("off")
plt.show()
Coming from C/C++ and DirectX (and now the outdated OpenGL), I'm always flabbergasted at the shortness of these "scripts".
 
Ax_xiom said:
I'll create a new image with the centre at 0,0 so no shifting is required.

Here it is:
Python:
# fourier_synthesis.py

import numpy as np
import matplotlib.pyplot as plt

image_filename = "HubbleOutline10.jpg"

def calculate_2dft(input):
    ft = np.fft.ifftshift(input)
    ft = np.fft.fft2(ft)
    return np.fft.fftshift(ft)

# Read and process image
image = plt.imread(image_filename)
image = image[:, :, :3].mean(axis=2)  # Convert to grayscale

plt.set_cmap("gray")

ft = calculate_2dft(image)

plt.subplot(121)
plt.imshow(image)
plt.axis("off")
plt.subplot(122)
plt.imshow(abs(ft)**0.5)
plt.axis("off")
plt.show()
Looks sensible. Except why are you taking ##\sqrt{|F|}##? Surely you just want the absolute value. Also , don't use jpg for binary images, because the compression causes ringing. Use something lossless - a bmp or a png or gif.
 
Ibix said:
Looks sensible. Except why are you taking ##\sqrt{|F|}##? Surely you just want the absolute value. Also , don't use jpg for binary images, because the compression causes ringing. Use something lossless - a bmp or a png or gif.
I'm taking the square root so the image looks brighter compare the regular image
Figure_1.webp

to the image when the values are squarerooted
Figure_3.webp

The squarerooted version is the closest to what I'm trying to do, but my target image has the centre much brighter and the edges much darker