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