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?
Description. The 2-D DCT block calculates the two-dimensional discrete cosine transform of an image. Suppose f(x,y) is the input image of dimension M-by-N, the equation for the 2-D DCT is. F ( m , n ) = 2 M N C ( m ) C ( n ) ∑ x = 0 M − 1 ∑ y = 0 N − 1 f ( x , y ) cos ( 2 x + 1 ) m π 2 M cos ( 2 y + 1 ) n π 2 N.
dct() method, we can compute the discrete cosine transform by selecting different types of sequences and return the transformed array by using this method. Return value: It will return the transformed array. Example #1: In this example, we can see that by using scipy. fft.
In a DCT algorithm, an image (or frame in an image sequence) is divided into square blocks which are processed independently from each other, then the DCT of these blocks is taken, and the resulting DCT coefficients are quantized. This process can cause blocking artifacts, primarily at high data compression ratios.
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
https://docs.scipy.org/doc/scipy/reference/generated/scipy.fft.dctn.html
@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
I 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With