如何将使用numpy.fft.rfft的代码从python移植到C ++?

时间:2014-01-22 23:05:57

标签: opencv numpy fft fftw

我有用python编写的代码。它使用numpy计算实数输入的FFT的正部分。我需要将此代码移植到C ++。

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

rfft的结果是[659.27700000 + 0.j,1.27932533-1.4548977j,-3.15032533 + 2.1158917j]

我尝试将OpenCV用于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;

cv :: dft的结果是{1.42109e-14,-127.718,-94.705,6.26856,23.0231}。它与numpy.fft.rfft有很大不同。在计算OpenCV的dft之后,所有输入的DC值(零元素)接近于零看起来很奇怪。

使用FFTW3库给我的结果与OpenCV的结果相同:

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);

此代码给出了与OpenCV相同的结果。它打印:(1.42109e-14,0)( - 127.718,-94.705)(6.26856,23.0231)。

为什么我在C ++和python中得到不同的dft结果?我做错了什么?

谢谢!

2 个答案:

答案 0 :(得分:2)

我目前正在使用gcc 4.6,它没有C ++ 11,所以我使用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;
}

输出

659.277 1.27933 -1.4549 -3.15033 2.11589

同意numpy和cv2 python模块:

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]])

我不知道为什么你的代码不起作用,所以我想这不仅仅是一个很长的评论而不是答案。

答案 1 :(得分:0)

请查看文档。 libfft rfft方法将实数输入的矢量变换为复傅立叶系数。使用傅立叶系数对实数信号的共轭,输出可以与输入长度相同的数组给出。

通用fft和dft方法将复数向量转换为复系数向量。旧代码使用双精度数组用于输入和输出,其中复数的实部和虚部交替给出,即一个偶数长度的数组。奇数输入长度会发生什么变化可能是未记录的行为。