I am creating a 2D DCT-II in labview but want to be able to check my outputs are correct. SciPy has a nice DCT function which defaults to DCT-II but is 1D.
I want to make it work for a 2D array. To do this the DCT must be applied to the columns and then the DCT must be again applied to the rows of this outcome.
I'm not sure what function I want to use to do this. I have tried np.rot90 which rotates the numpy array 90 degrees counter clockwise as follows:
import numpy as np from scipy.fftpack import dct a = np.array([[1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0], [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0], [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0], [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0], [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0], [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0], [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0], [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0]]) b = dct(np.rot90(dct(a),3)) However this outputs the following:
array([[ 1152. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ -412.30867345, 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ -43.10110726, 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ -12.85778584, 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ -3.24494866, 0. , 0. , 0. , 0. , 0. , 0. , 0. ]]) I think that rot90 is not the right function to do what I want to do, perhaps there is a better one?
3 Answers
@Jaime's answer is fine. I'll add that dct has an axis argument for just this purpose. First apply it along, say, axis 0, then along axis 1 of the result:
In [30]: from scipy.fftpack import dct In [31]: a.shape Out[31]: (8, 8) In [32]: t1 = dct(dct(a, axis=0), axis=1) In [33]: t2 = dct(dct(a.T).T) In [34]: np.abs(t1 - t2).max() Out[34]: 0.0 1I don't think that a rotation is what you want, since it converts rows into columns, but it also messes with the order of the data. Use np.transpose instead.
To apply dct first by columns, then by rows, you would do something like:
dct(dct(a.T).T) The trailing .T is equivalent to np.transpose. Note how you need to undo the transposition after you operate on the columns, to get the return aligned by rows again.
I don't think that the order in which you apply the dct, i.e. columns then rows vs. rows then columns, makes any difference, but you could get rows then columns as:
dct(dct(a).T).T There is now a multidimensional DCT function (and inverse) as well:
>>> from scipy.fft import dctn, idctn >>> b = dctn(a) >>> np.allclose(a, idctn(b)) True