在scipy中,为什么idct(dct(a))不等于a?

d4so4syb  于 2023-11-19  发布在  其他
关注(0)|答案(2)|浏览(125)

我正在尝试使用python实现JPEG压缩。当我尝试对tiff图像应用DCT,量化,IDCT过程时,我发现scipy.fftpack.dct/idct有些奇怪。
由于scipy包中只有1D dct/idct,所以我这样做是为了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)

字符串
我使用一个简单的3x 3矩阵测试了2D dct/idct。我希望通过这个测试用例得到一个True矩阵。

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


然而,事实证明,在idct 2(dct 2(a))之后,与原始a矩阵相比,结果被缩放了一个常数因子。
我想问一下,是否有一种方法可以实现一组2D dct/idct,使得在idct(dct(a))操作之后,我可以得到与输入相同的输出。

yftpprvb

yftpprvb1#

您需要将dct2idct2的缩放设置为ortho

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

字符串
此外,您不能期望这些值完全相同,而是在一定的误差范围内几乎相同:

np.allclose (a, idct2(dct2(a)))

ecbunoof

ecbunoof2#

您需要规范化idct2(dct2(a))并将数据类型转换为uint8。一种选择是使用cv2进行此规范化:

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)
a = np.random.randint(0,255,9).reshape(3,3)

# convert to uint8
norm_image = cv2.normalize(idct2(dct2(a)), None, 
                           alpha = a.min(), beta = a.max(), 
                           norm_type = cv2.NORM_MINMAX, 
                           dtype = cv2.CV_32F).astype(np.uint8)
print(a == norm_image)
# [[ True  True  True]
#  [ True  True  True]
#  [ True  True  True]]

字符串

相关问题