如何对2型DCT结果去正交化以匹配scipy默认dctn输出?
自定义2D DCT匹配Scipy默认输出的解决方法
你的自定义DCT实现对应的是Scipy中dctn指定norm="ortho"的正交归一化版本,而Scipy默认的dctn(norm=None)没有做归一化处理,只需通过缩放调整即可让结果匹配,有两种简单方式:
方式一:修改自定义DCT矩阵,直接生成非归一化结果
调整dct_mat函数的系数,去掉正交归一化的缩放因子,生成标准DCT-II变换矩阵:
import numpy as np import scipy.fftpack def dct_mat_non_ortho(data): (n, m) = data.shape assert(m == n) mat = np.zeros((n, n)) # 第一行无缩放因子 for i in range(n): mat[0][i] = 1.0 # 其余行使用2倍余弦系数(标准DCT-II无归一化的定义) for r in range(1, n): for c in range(n): mat[r][c] = 2.0 * np.cos((np.pi * (2.0 * float(c) + 1.0) * float(r)) / (2.0 * float(n))) return mat test_data = np.array([ [13.4, 13.9, 0.1], [20.1, -20.3, 88.2], [0, 4.2, -53.5] ]) # Scipy默认结果 scipy_result = scipy.fftpack.dctn(test_data) # 自定义非归一化DCT结果 mat = dct_mat_non_ortho(test_data) custom_result = np.matmul(np.matmul(mat, test_data), mat.T) print("Scipy默认结果:") print(scipy_result) print("自定义匹配结果:") print(custom_result)
方式二:对现有正交归一化结果做后处理缩放
针对你已经生成的res(正交归一化结果),构造维度缩放向量,对每个元素按位置进行缩放:
n = test_data.shape[0] # 构造缩放向量:第一个元素为sqrt(n),其余为sqrt(n/2) scale = np.zeros(n) scale[0] = np.sqrt(n) scale[1:] = np.sqrt(n / 2.0) # 对正交结果进行缩放,匹配Scipy默认输出 scaled_result = (scale.reshape(-1, 1) * res) * scale.reshape(1, -1) print("Scipy默认结果:") print(scipy) print("缩放后自定义结果:") print(scaled_result)
原理说明
Scipy默认的dctn(norm=None)实现的是标准DCT-II变换,没有施加正交归一化的缩放因子;而你的自定义矩阵是正交归一化版本,两者的差异在于:
- 正交归一化版本对变换矩阵的第一行乘以
1/sqrt(n),其余行乘以sqrt(2/n) - 标准DCT-II版本第一行无缩放,其余行乘以
2
通过反向调整缩放因子,就能让两者结果完全匹配。
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

