SciPy DCT for Discrete Cosine Transform

SciPy provides dct() to calculate the Discrete Cosine Transform of a real input sequence. A DCT represents data using cosine basis functions, so it is commonly used when the input is real-valued, such as a signal, measurement sequence, or image block.

The older scipy.fftpack.dct() function used in this tutorial still works, but scipy.fftpack is now treated as the legacy FFT interface. For new code, prefer scipy.fft.dct(). The examples below show both forms so that you can maintain old code and write current SciPy code correctly.

scipy.fftpack.dct() syntax used in existing SciPy code

</>
Copy
y = scipy.fftpack.dct(x, type=2, n=None, axis=-1, norm=None, overwrite_x=False)

The default transform is DCT type 2 along the last axis of the input array. If you do not pass n, SciPy uses the length of the selected axis.

scipy.fft.dct() syntax recommended for new SciPy programs

</>
Copy
y = scipy.fft.dct(x, type=2, n=None, axis=-1, norm=None, overwrite_x=False, workers=None, orthogonalize=None)

The modern scipy.fft.dct() API adds workers for parallel computation and orthogonalize for controlling the orthogonalized DCT variant. For simple one-dimensional examples, the result is the same as the older scipy.fftpack.dct() call when equivalent arguments are used.

SciPy DCT parameters: x, type, n, axis, norm and overwrite_x

ParameterRequired/OptionalDescription
xRequiredInput array or array-like object on which the Discrete Cosine Transform is computed.
typeOptionalDCT type. SciPy supports types 1, 2, 3, and 4. The default is 2, which is what most users mean by “the DCT”.
nOptionalLength of the transform along the selected axis. If n is smaller than the current length, the input is truncated. If n is larger, the input is zero-padded.
axisOptionalAxis along which the DCT is computed. The default is -1, meaning the last axis.
normOptionalNormalization mode. In scipy.fftpack.dct(), common values are None and 'ortho'. In scipy.fft.dct(), values include 'backward', 'ortho', and 'forward'.
overwrite_xOptionalIf True, SciPy may overwrite the input data while computing the transform. Keep it False when the original input must be preserved.
workersOptional in scipy.fft.dct()Maximum number of workers for parallel computation. This argument is not available in scipy.fftpack.dct().
orthogonalizeOptional in scipy.fft.dct()Controls whether SciPy uses the orthogonalized DCT variant. It is especially relevant when using norm='ortho'.
yReturned valueReal ndarray containing the transformed input values.

Values shown in the syntax are default values. In most programs, you will start with only the input array and add norm, axis, or n when the transform needs a specific scale, dimension, or length.

Example 1: calculate SciPy DCT of a NumPy array

scipy-example.py

</>
Copy
# import numpy
import numpy as np

# import dct
from scipy.fftpack import dct

# numpy array
x = np.array([1.0, 2.0, 1.0, 2.0, -1.0])
print("x      : ",x)

# apply dct function on array
y = dct(x)
print("dct(x) : ",y)

Output

x      :  [ 1.  2.  1.  2. -1.]
dct(x) :  [ 10.           3.80422607  -4.47213595   2.35114101  -4.47213595]

The first value in the output is the low-frequency coefficient. The remaining values represent cosine components at increasing frequencies for this input sequence.

Example 2: use scipy.fft.dct() with norm=’ortho’

Use norm='ortho' when you want an orthonormal transform. This is useful when you want a clean inverse relationship with idct() using the same normalization.

</>
Copy
import numpy as np
from scipy.fft import dct, idct

x = np.array([1.0, 2.0, 1.0, 2.0, -1.0])

coefficients = dct(x, norm='ortho')
reconstructed = idct(coefficients, norm='ortho')

print("DCT coefficients:", coefficients)
print("Reconstructed x :", reconstructed)

Output

DCT coefficients: [ 2.23606798  1.20300191 -1.41421356  0.74349607 -1.41421356]
Reconstructed x : [ 1.  2.  1.  2. -1.]

Here, idct() recovers the original array because both the forward and inverse transforms use norm='ortho'.

Example 3: apply SciPy DCT along rows or columns with axis

For a two-dimensional array, axis=-1 applies the DCT across each row because the last axis is the column direction. Use axis=0 to apply the DCT down each column.

</>
Copy
import numpy as np
from scipy.fft import dct

x = np.array([
    [1.0, 2.0, 3.0],
    [4.0, 5.0, 6.0]
])

row_dct = dct(x, axis=1, norm='ortho')
column_dct = dct(x, axis=0, norm='ortho')

print("DCT across rows:")
print(row_dct)

print("DCT down columns:")
print(column_dct)

Output

DCT across rows:
[[ 3.46410162 -1.41421356  0.        ]
 [ 8.66025404 -1.41421356  0.        ]]
DCT down columns:
[[ 3.53553391  4.94974747  6.36396103]
 [-2.12132034 -2.12132034 -2.12132034]]

This example is useful when the rows and columns have different meanings. For example, rows may represent separate signals, while columns may represent samples within each signal.

Example 4: control SciPy DCT length with n

The n parameter changes the logical length of the transform. When n is smaller than the input length, SciPy truncates the data. When n is larger, SciPy pads the input with zeros before applying the DCT.

</>
Copy
import numpy as np
from scipy.fft import dct

x = np.array([1.0, 2.0, 1.0, 2.0, -1.0])

print("n=3:", dct(x, n=3))
print("n=8:", dct(x, n=8))

Output

n=3: [ 8.  0. -2.]
n=8: [10.          7.56913141  0.76536686 -4.41241402 -1.41421356  2.56699766
 -1.84775907 -6.05387275]

Example 5: compute a two-dimensional DCT with scipy.fft.dctn()

Calling dct() once transforms one axis. For a true two-dimensional or N-dimensional DCT, use scipy.fft.dctn(). This applies the DCT across multiple axes in one call.

</>
Copy
import numpy as np
from scipy.fft import dctn, idctn

block = np.array([
    [52, 55, 61, 66],
    [70, 61, 64, 73],
    [63, 59, 55, 90],
    [67, 61, 68, 104]
], dtype=float)

coefficients = dctn(block, norm='ortho')
restored = idctn(coefficients, norm='ortho')

np.set_printoptions(precision=2, suppress=True)
print("2D DCT coefficients:")
print(coefficients)
print("Restored block:")
print(restored)

Output

2D DCT coefficients:
[[267.25 -28.08  25.25  -7.04]
 [-21.42  13.72 -15.91   6.63]
 [ -0.25  -8.75  -3.25   1.73]
 [ -9.26  -4.87   1.45  -5.72]]
Restored block:
[[ 52.  55.  61.  66.]
 [ 70.  61.  64.  73.]
 [ 63.  59.  55.  90.]
 [ 67.  61.  68. 104.]]

Use dctn() for image blocks, matrices, and multidimensional data. Use dct() with axis when you only want to transform one dimension of an array.

DCT type 2, DCT type 3 and inverse DCT in SciPy

In SciPy, DCT type 2 is the default and is the most common form in practical examples. DCT type 3 is closely related to the inverse of DCT type 2. When you use norm='ortho', a DCT-II followed by the matching inverse transform can reconstruct the original input without manually applying a scale factor.

Use type=1, type=3, or type=4 only when your formula, algorithm, or reference material specifically requires that DCT type. Otherwise, the default type=2 is usually the right starting point.

When to use norm=’ortho’ in scipy.fft.dct()

The norm argument controls scaling. Use norm='ortho' when you want orthonormal coefficients and straightforward reconstruction with idct() or idctn(). Leave normalization at the default when you are matching formulas or older code that expects SciPy’s unnormalized DCT output.

Common SciPy DCT mistakes and fixes

  • Using FFT wording for DCT output: dct() returns real DCT coefficients, not complex Fourier coefficients.
  • Forgetting the axis: On a 2D array, axis=-1 transforms rows. Use axis=0 for columns.
  • Mixing normalization modes: If you use norm='ortho' for dct(), use the same normalization for idct().
  • Expecting a full 2D transform from one dct() call: Use dctn() or apply dct() along both axes.
  • Using scipy.fftpack in new code: Existing code can keep it, but new code should generally import DCT functions from scipy.fft.

SciPy DCT function reference links

For exact API details, refer to the official SciPy pages for scipy.fft.dct(), scipy.fftpack.dct(), and scipy.fft.dctn().

FAQs on SciPy DCT

What does scipy dct() return?

dct() returns a real ndarray containing the Discrete Cosine Transform coefficients of the input array. It does not return complex FFT coefficients.

Should I use scipy.fft.dct() or scipy.fftpack.dct()?

Use scipy.fft.dct() for new code. Use scipy.fftpack.dct() when you are maintaining older code that already depends on the legacy FFT interface.

How do I calculate a 2D DCT in SciPy?

Use scipy.fft.dctn() for a 2D or N-dimensional DCT. If you use dct(), it transforms only one axis per call unless you apply it again along another axis.

Why is norm=’ortho’ used with SciPy DCT?

norm='ortho' gives orthonormal scaling. It is helpful when you want to reconstruct the original values with idct() or idctn() without manually handling scale factors.

What is the default DCT type in SciPy?

The default DCT type is type=2. This is the form most examples use unless a specific algorithm requires another DCT type.

Editorial QA checklist for this SciPy DCT tutorial

  • Confirm that new examples use scipy.fft while the original scipy.fftpack example remains available for legacy users.
  • Check that every added code block uses a PrismJS-compatible class such as language-python, language-python syntax, or output.
  • Verify that DCT output is described as a real ndarray, not as a complex FFT result.
  • Ensure that axis, n, norm, dctn(), and inverse reconstruction are covered with examples.
  • Review the official SciPy links when the API changes in a future SciPy release.