How to discard coefficients in the frequency domain without losing too much quality?

I was reading a text that shows that one can throw away 66% of the coefficients and gets an image that is still acceptable.

I tried to replicate it using python (last example) and selectively throwing away some of the coefficients but I couldn't get a great image, mine is looking like a ghost.

How can I discard that not so important to the image?

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
from scipy import signal

# image in frequency domain
fft_original = np.fft.rfft2(img)

# discarding some coefficients (except initial square 80x80)
for x in range(300):
for y in range(300):

fft_original[x,y] = 0

# reverse from frequency to spatial
i_fft_original = np.fft.irfft2(fft_original)

f, (plt1, plt2) = plt.subplots(1, 2, figsize=(15,15))

plt1.axis('off');plt1.set_title('Original');plt1.imshow(img[:,:,0], cmap='gray');
plt2.axis('off');plt2.set_title('Reversed');plt2.imshow(i_fft_original[:,:,0], cmap='gray');

• Compare not real but absolute value of fft. Or just pick some radius in the fourier domain to throw away everything outside of that radius. – mathreadler Mar 9 '17 at 22:13

You are throwing away coefficients before checking to see if their current magnitudes are small (smaller than typically visible).

(You might also want to rescale what's left to preserve total energy.)

• Thanks, do you know how can I check if its magnitudes are small? (ex: fft_original[x,y] <= 0.01 ? ) – Leandro Moreira Mar 8 '17 at 20:51
• "small" is relative to the psychology and physiology of human vision. Test, or read published research for prior opinions. – hotpaw2 Mar 8 '17 at 20:55
• Thanks, a lot :D I'll try fft_original[x,y,0].real <= MIN – Leandro Moreira Mar 8 '17 at 20:59
• I tried fft_original[x,y,0].real < 20 but it caused also issues and then I tried a range query > -2 and < 20 but it still weird. – Leandro Moreira Mar 8 '17 at 21:08
• The size of a "small" enough coefficient is likely not a constant, but varies greatly depending on the location in the 2D FFT and what's nearby in both the FFT and the image. – hotpaw2 Mar 8 '17 at 21:38

Find largest value of fft_original and then Use a threshold which is 1/N times of it - say 1/10. Also compare with absolute value of each sample so that high magnitude negative values are preserved.

• Thanks, is it the highest real value? or the imaginary part? – Leandro Moreira Mar 8 '17 at 21:15
• I tried with 1/10, threshold = (1/10) * max_fft and then compared using absolutes values if abs(fft_original[x,y,0].real) <= threshold: but it still looking ghostly. – Leandro Moreira Mar 8 '17 at 21:23
• I changed the color plane which I was working on (from 0 to 2) and then it looks more acceptable now. – Leandro Moreira Mar 8 '17 at 21:33