1

I am trying to implement image compression using fft. I follow these steps:

  1. Pad the height and weight of the input image to be powers of two (for easier DFT application)
  2. For each of the red, green and blue channels:
    • Transform each row to its DFT
    • Transform each column to its DFT
    • Turn the bottom CR% (compression rate) of the elements into zero (according to the size of the absolute value)
    • Inverse transform each column
    • Inverse transform each row
  3. Unpad the image to it's original dimensions

I tried this experiment on the image below with compression rates 10, 50, and 90, and here are the results

Original Image

10% compression

50% compression

90% Compression

As you can see, it mostly works fine, except there some patchy areas in certain dark regions of the image.

My question is, is this an expected behavior assuming the steps above are followed? If yes, what kind of mitigation techniques exist to avoid this? Also, could this be caused by numerical errors and why exactly does this happen mostly on dark areas?

I tried adjusting the compression rate, but the patchy areas appear as low as at 20% compression rate, which means I am not able to get a reasonable compression.

EDIT: I also get interesting results with this picture:

enter image description here

enter image description here

enter image description here

Looks like thing break when there are areas that are too dark or too light

SOLUTION: As was mentioned in the comments, I was converting to uint8 which cased small negatives to turn into large values and vice versa. Clipping at 0 and 255 after applying the inverse transform fixed the issue.

Mushegh
  • 119
  • 4
  • 1
    Please provide enough code so others can better understand or reproduce the problem. – Community Nov 15 '22 at 04:23
  • 1
    We don't know what you're doing if you don't provide code. Please read [mre]. However, my guess is that you are casting the result of the IFFT to uint8, and negative values wrap around to large values. You want to clip (clamp, saturate) the values before casting. – Cris Luengo Nov 15 '22 at 07:50
  • @CrisLuengo That was it. I was converting to uint8 which cased small negative to turn into large value and vice versa. Clipping at 0 and 255 fixed the issue. Thanks! – Mushegh Nov 15 '22 at 12:48

1 Answers1

0

As was mentioned in the comments, I was converting to uint8 which cased small negatives to turn into large values and vice versa. Clipping at 0 and 255 after applying the inverse transform fixed the issue.

Mushegh
  • 119
  • 4