cv.dft - MATLAB File Help
cv.dft

Performs a forward or inverse Discrete Fourier transform of a 1D or 2D floating-point array

dst = cv.dft(src)
dst = cv.dft(src, 'OptionName',optionValue, ...)

Input

Output

Options

The function cv.dft performs one of the following:

In case of real (single-channel) data, the output spectrum of the forward Fourier transform or input spectrum of the inverse Fourier transform can be represented in a packed format called CCS (complex-conjugate-symmetrical). It was borrowed from IPL (Intel Image Processing Library). Here is how 2D CCS spectrum looks:

CCS = [
  ReY(0,0), ReY(0,1), ImY(0,1), ..., ReY(0,N/2-1), ImY(0,N/2-1), ReY(0,N/2)
  ReY(1,0), ReY(1,1), ImY(1,1), ..., ReY(1,N/2-1), ImY(1,N/2-1), ReY(1,N/2)
  ImY(1,0), ReY(2,1), ImY(2,1), ..., ReY(2,N/2-1), ImY(2,N/2-1), ImY(1,N/2)
  ...
  ReY(M/2-1,0), ReY(M-3,1), ImY(M-3,1), ..., ReY(M-3,N/2-1), ImY(M-3,N/2-1), ReY(M/2-1,N/2)
  ImY(M/2-1,0), ReY(M-2,1), ImY(M-2,1), ..., ReY(M-2,N/2-1), ImY(M-2,N/2-1), ImY(M/2-1,N/2)
  ReY(M/2,  0), ReY(M-1,1), ImY(M-1,1), ..., ReY(M-1,N/2-1), ImY(M-1,N/2-1), ReY(M/2,  N/2)
]

In case of 1D transform of a real vector, the output looks like the first row of the matrix above.

So, the function chooses an operation mode depending on the flags and size of the input array:

If Scale is set, the scaling is done after the transformation.

Unlike cv.dct, the function supports arrays of arbitrary size. But only those arrays are processed efficiently, whose sizes can be factorized in a product of small prime numbers (2, 3, and 5 in the current implementation). Such an efficient dft size can be calculated using the cv.getOptimalDFTSize method.

Note: cv.idft is equivalent to cv.dft(..., 'Inverse',true). Also note that none of cv.dft and cv.idft scales the result by default. So, you should pass Scale=true to one of cv.dft or cv.idft explicitly to make these transforms mutually inverse.

Example

The sample below illustrates how to calculate a dft-based convolution of two 2D real arrays:

function C = convolveDFT(A, B)
    % calculate the size of dft transform
    dftSize = size(A) + size(B) - 1;
    dftSize(1) = cv.getOptimalDFTSize(dftSize(1));
    dftSize(2) = cv.getOptimalDFTSize(dftSize(2));

    % allocate temporary buffers and initialize them with 0's
    tempA = zeros(dftSize, class(A));
    tempB = zeros(dftSize, class(B));

    % copy A/B to the top-left corners of tempA/tempB respectively
    tempA(1:size(A,1), 1:size(A,2)) = A;
    tempB(1:size(B,1), 1:size(B,2)) = B;

    % now transform the padded A & B in-place;
    % use 'NonzeroRows' hint for faster processing
    tempA = cv.dft(tempA, 'NonzeroRows',size(A,1));
    tempB = cv.dft(tempB, 'NonzeroRows',size(B,1));

    % multiply the spectrums;
    % the function handles packed spectrum representations well
    C = cv.mulSpectrums(tempA, tempB);

    % the output array size
    sz = abs(size(A) - size(B)) + 1;

    % transform the product back from the frequency domain.
    % Even though all the result rows will be non-zero,
    % you need only the first sz(1) of them
    C = cv.dft(C, 'Inverse',true, 'Scale',true, 'NonzeroRows',sz(1));

    % now slice the result part from C
    C = C(1:sz(1), 1:sz(2));
end

To optimize this sample, consider the following approaches:

All of the above improvements have been implemented in cv.matchTemplate and cv.filter2D. Therefore, by using them, you can get the performance even better than with the above theoretically optimal implementation. Though, those two functions actually calculate cross-correlation, not convolution, so you need to "flip" the second convolution operand B vertically and horizontally using cv.flip.

See also