Reputation: 4791
For the 1D cosine transform the documentation is clear in here, and I can reproduce it easily:
The formula is:
and here it is reproduced manually, for example for the third harmonic:
import numpy as np
from scipy.fft import fft, dct
y = np.array([10,3,5])
# dct() call:
print(dct(y, 2))
# manual reproduction for k = 2:
N = 3
k = 2
n = np.array([0,1,2])
2 * (
y[0] * np.cos((np.pi*k*(2*n[0]+1))/(2*N)) +
y[1] * np.cos((np.pi*k*(2*n[1]+1))/(2*N)) +
y[2] * np.cos((np.pi*k*(2*n[2]+1))/(2*N)))
in both cases I get 9.
But there is no documentation for the 2D DCT, and my attempts at hacking the formula with a toy matrix are not working out:
Compare:
z = np.array([[ 2, 3 ],
[ 10, 15]])
dct(z, axis=0) # dct() call
to for instance:
N = 2
M = 2
k = 0
l = 0
n = np.array([0,1])
m = np.array([0,1])
M*N * (
z[0,0] * np.cos((np.pi*k*(2*n[0]+1))/(2*N)) * np.cos((np.pi*l*(2*m[0]+1))/(2*M)) +
z[0,1] * np.cos((np.pi*k*(2*n[0]+1))/(2*N)) * np.cos((np.pi*l*(2*m[1]+1))/(2*M)) +
z[1,0] * np.cos((np.pi*k*(2*n[1]+1))/(2*N)) * np.cos((np.pi*l*(2*m[0]+1))/(2*M)) +
z[1,1] * np.cos((np.pi*k*(2*n[1]+1))/(2*N)) * np.cos((np.pi*l*(2*m[1]+1))/(2*M))
)
for the first coefficient.
Can anyone help me reconcile the output of dct()
with my attempted manual calculation?
I guess the formula is not...
but it would be really easy to correct if I could get the same output manually for one of the coefficients on the example matrix above.
Upvotes: 2
Views: 659
Reputation: 35080
You can't find the formula for the multidimensional mode because the function doesn't do multidimensional cosine transforms. The axis
keyword should be suspicious: in NumPy, SciPy it typically determines the direction along which lower-dimensional operations should be performed.
In other words, dct(z, axis=0)
is just a columnwise 1d cosine transform:
import numpy as np
from scipy.fft import dct
z = np.array([[ 2, 3],
[ 10, 15]])
print(dct(z, axis=0)) # dct() call
print(np.array([dct(column) for column in z.T]).T)
# both outputs
# [[ 24. 36. ]
# [-11.3137085 -16.97056275]]
Note the two transposes on the last line: all that it did was first loop over the array to slice it according to columns, then join them again columnwise. The latter would probably be better spelled out as
res = np.stack([dct(column) for column in z.T], axis=1)
Upvotes: 1