10

I am trying to implement JPEG compression using python. When I tried to apply the DCT, quantization, IDCT process for a tiff image, I found something strange for scipy.fftpack.dct/idct.

Since there is only 1D dct/idct within scipy package, I was doing this for a 2D dct

import numpy as np
from scipy.fftpack import dct, idct

def dct2(block):
    return dct(dct(block.T).T)

def idct2(block):
    return idct(idct(block.T).T)

I tested the 2D dct/idct using a simple 3x3 matrix. I was expecting to get a True matrix with this test case.

a = np.random.randint(0,255,9).reshape(3,3)
print a == idct2(dct2(a))

However it turned out that after idct2(dct2(a)) the result was scaled by a constant factor compared with the original a matrix.

I would like to ask if there is a way to implement a set of 2D dct/idct such that after a idct(dct(a)) operation I can get the same output as the input.

Reti43
  • 9,656
  • 3
  • 28
  • 44
yc2986
  • 1,101
  • 3
  • 20
  • 23
  • Possible duplicate of [Scipy's fftpack dct and idct](http://stackoverflow.com/questions/14325795/scipys-fftpack-dct-and-idct) – Reti43 Feb 15 '16 at 21:08
  • Some trivia. Instead of transposing your array every time, you can do `def dct2(a): dct(dct(a, axis=0), axis=1)`. And `dct(..., type=3) == idct(...)`. – Reti43 Feb 15 '16 at 21:12

1 Answers1

13

You need to set scaling to ortho for both dct2 and idct2:

def dct2 (block):
  return dct(dct(block.T, norm = 'ortho').T, norm = 'ortho')

also, you cannot expect the values to be exactly the same, but almost the same within some margin of error:

np.allclose (a, idct2(dct2(a)))
gauteh
  • 16,435
  • 4
  • 30
  • 34