How can I port code that uses numpy.fft.rfft from

2019-05-30 00:34发布

I have code written in python. It computes positive part of FFT of real input using numpy. I need to port this code to C++.

import numpy as np
interp=[131.107, 133.089, 132.199, 129.905, 132.977]
res=np.fft.rfft(interp)
print res

Result of rfft is [ 659.27700000+0.j, 1.27932533-1.4548977j, -3.15032533+2.1158917j]

I tried to use OpenCV for 1D DFT:

std::vector<double> fft;
std::vector<double> interpolated = {131.107, 133.089, 132.199, 129.905, 132.977};
cv::dft( interpolated, fft );
for( auto it = fft.begin(); it != fft.end(); ++it ) {
    std::cout << *it << ' ';
}
std::cout << std::endl;

Result of cv::dft is {1.42109e-14, -127.718, -94.705, 6.26856, 23.0231}. It is much different from numpy.fft.rfft. It looks strange that DC value (zero element) is near zero on all inputs after OpenCV's dft computed.

Usage of FFTW3 library gave me the same results as OpenCV's results:

std::vector<double> interpolated = {131.107, 133.089, 132.199, 129.905, 132.977};
fftw_complex* out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * 3 );
fftw_plan plan = fftw_plan_dft_r2c_1d( interpolated.size( ), interpolated.data( ), out, FFTW_ESTIMATE );
fftw_execute(plan);
fftw_destroy_plan(plan);
for( size_t i = 0; i < interpolated.size( ); ++i ) {
    std::cout << " (" << out[ i ][ 0 ] << ", " << out[ i ][ 1 ] << ")";
}
fftw_free(out);

This code gives me the same results as OpenCV. It prints: (1.42109e-14, 0) (-127.718, -94.705) (6.26856, 23.0231).

Why do I get different results of dft in C++ and in python? What am I doing wrong?

Thanks!

2条回答
Explosion°爆炸
2楼-- · 2019-05-30 00:59

Please check the documentation. The libfft rfft method transforms a vector of real inputs into the complex Fourier coefficients. Using the conjugacy of Fourier coefficients for real signals, the output can be given in an array of the same length as the input.

The generic fft and dft methods transform vectors of complex numbers into vectors of complex coefficients. The older codes use arrays of doubles for input and output where the real and imaginary parts of the complex numbers are given alternatingly, i.e., one array of even length. What happens to odd input lengths may be undocumented behavior.

查看更多
贪生不怕死
3楼-- · 2019-05-30 01:00

I'm using gcc 4.6 at the moment, which doesn't have C++11, so I tried this version of your code, using OpenCV 2.4.8:

#include <iostream>
#include "opencv2/core/core.hpp"

int main(int argc, char *argv[])
{
    double data[] = {131.107, 133.089, 132.199, 129.905, 132.977};
    std::vector<double> interpolated (data, data + sizeof(data) / sizeof(double));
    std::vector<double> fft;

    cv::dft(interpolated, fft);

    for (std::vector<double>::const_iterator it = fft.begin(); it != fft.end(); ++it) {
        std::cout << *it << ' ';
    }
    std::cout << std::endl;
}

The output

659.277 1.27933 -1.4549 -3.15033 2.11589

agrees with numpy and with the cv2 python module:

In [55]: np.set_printoptions(precision=3)

In [56]: x
Out[56]: array([ 131.107,  133.089,  132.199,  129.905,  132.977])

In [57]: np.fft.rfft(x)
Out[57]: array([ 659.277+0.j   ,    1.279-1.455j,   -3.150+2.116j])

In [58]: cv2.dft(x)
Out[58]: 
array([[ 659.277],
       [   1.279],
       [  -1.455],
       [  -3.15 ],
       [   2.116]])

I don't know why your code is not working, so I guess this is more of a long comment than an answer.

查看更多
登录 后发表回答