Search code examples
c++opencvdftfourier-descriptors

Discrete Fourier Transform implementation gives different result than OpenCV DFT


We have implemented DFT and wanted to test it with OpenCV's implementation. The results are different.

  1. our DFT's results are in order from smallest to biggest, whereas OpenCV's results are not in any order.
  2. the first (0th) value is the same for both calculations, as in this case, the complex part is 0 (since e^0 = 1, in the formula). The other values are different, for example OpenCV's results contain negative values, whereas ours does not.

This is our implementation of DFT:

// complex number
std::complex<float> j;
j = -1;
j = std::sqrt(j);
std::complex<float> result;
std::vector<std::complex<float>> fourier; // output

// this->N = length of contour, 512 in our case
// foreach fourier descriptor
for (int n = 0; n < this->N; ++n)
{
    // Summation in formula
    for (int t = 0; t < this->N; ++t)
    {
        result += (this->centroidDistance[t] * std::exp((-j*PI2 *((float)n)*((float)t)) / ((float)N)));
    }

    fourier.push_back((1.0f / this->N) * result);
}

and this is how we calculate the DFT with OpenCV:

std::vector<std::complex<float>> fourierCV; // output
cv::dft(std::vector<float>(centroidDistance, centroidDistance + this->N), fourierCV, cv::DFT_SCALE | cv::DFT_COMPLEX_OUTPUT);

The variable centroidDistance is calculated in a previous step.

Note: please avoid answers saying use OpenCV instead of your own implementation.


Solution

  • You forgot to initialise result for each iteration of n:

    for (int n = 0; n < this->N; ++n)
    {
        result = 0.0f;    // initialise `result` to 0 here <<<
    
        // Summation in formula
        for (int t = 0; t < this->N; ++t)
        {
            result += (this->centroidDistance[t] * std::exp((-j*PI2 *((float)n)*((float)t)) / ((float)N)));
        }
    
        fourier.push_back((1.0f / this->N) * result);
    }