使用Python的Scipy DCT-II进行2D或ND DCT

时间:2012-12-16 19:42:23

标签: python scipy dct

我想使用scipy的DCT-II,因为它已经编码且速度很快。看看doc,它似乎是一维实现。是否可以以这种方式使用它作为3D实现?我不确定数学。 2D和3D实现相当于在计算中使用不同的维度乘以1D的2或3倍?

2 个答案:

答案 0 :(得分:6)

基本上,以下是诀窍:

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

# Lets create a 3D array and fill it with some values
a = numpy.random.rand(3,3,3)

f,x,y = a.shape
b = np.zeros((f,x,y))

b = dct(dct(dct(a).transpose(0,2,1)).transpose(1,2,0)).transpose(1,2,0).transpose(0,2,1)

答案 1 :(得分:1)

这是一个更通用的功能:

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

def dctn(x, norm="ortho"):
    for i in range(x.ndim):
        x = dct(x, axis=i, norm=norm)
    return x

def idctn(x, norm="ortho"):
    for i in range(x.ndim):
        x = idct(x, axis=i, norm=norm)
    return x

然后:

>>> x = np.random.rand(2, 2, 2)

>>> x
array([[[0.316, 0.927],
        [0.197, 0.936]],

       [[0.832, 0.982],
        [0.768, 0.564]]])

>>> dctn(x)
array([[[ 1.952, -0.459],
        [ 0.209, -0.08 ]],

       [[-0.272, -0.496],
        [-0.132,  0.171]]])

>>> np.all(np.isclose(x, idctn(dctn(x))))
True

要使输出与@macrocosme的输出完全相同,请设置norm=None并在dctn的末尾运行它:

np.moveaxis(x, range(x.ndim), (-1, range(x.ndim - 1)))

再举一个例子,我们可以验证它与使用Wikipedia's calculations的JPEG 8x8 DCT-II相同:

>>> x = np.array([
...     [52, 55, 61, 66,  70,  61,  64, 73],
...     [63, 59, 55, 90,  109, 85,  69, 72],
...     [62, 59, 68, 113, 144, 104, 66, 73],
...     [63, 58, 71, 122, 154, 106, 70, 69],
...     [67, 61, 68, 104, 126, 88,  68, 70],
...     [79, 65, 60, 70,  77,  68,  58, 75],
...     [85, 71, 64, 59,  55,  61,  65, 83],
...     [87, 79, 69, 68,  65,  76,  78, 94],
... ]) - 128

>>> np.set_printoptions(precision=2, floatmode="fixed", suppress=True)

>>> print(dctn(x))
[[-415.38  -30.19  -61.20   27.24   56.12  -20.10   -2.39    0.46]
 [   4.47  -21.86  -60.76   10.25   13.15   -7.09   -8.54    4.88]
 [ -46.83    7.37   77.13  -24.56  -28.91    9.93    5.42   -5.65]
 [ -48.53   12.07   34.10  -14.76  -10.24    6.30    1.83    1.95]
 [  12.12   -6.55  -13.20   -3.95   -1.88    1.75   -2.79    3.14]
 [  -7.73    2.91    2.38   -5.94   -2.38    0.94    4.30    1.85]
 [  -1.03    0.18    0.42   -2.42   -0.88   -3.02    4.12   -0.66]
 [  -0.17    0.14   -1.07   -4.19   -1.17   -0.10    0.50    1.68]]