OpenCV中的DFT_INVERSE与Matlab中的ifft有所不同

3

我尝试使用opencv的dft函数来过滤信号。我尝试的方法是在时域中获取信号:

x = [0.0201920000000000 -0.0514940000000000 0.0222140000000000  0.0142460000000000  -0.00313500000000000    0.00270600000000000 0.0111770000000000  0.0233470000000000  -0.00162700000000000    -0.0306280000000000 0.0239410000000000  -0.0225840000000000 0.0281410000000000  0.0265510000000000  -0.0272180000000000 0.0223850000000000  -0.0366850000000000 0.000515000000000000    0.0213440000000000  -0.0107180000000000 -0.0222150000000000 -0.0888300000000000 -0.178814000000000  -0.0279280000000000 -0.144982000000000  -0.199606000000000  -0.225617000000000  -0.188347000000000  0.00196200000000000 0.0830530000000000  0.0716730000000000  0.0723950000000000]

使用以下方法将其转换为Fourier域:

cv::dft(x, x_fft, cv::DFT_COMPLEX_OUTPUT, 0);

消除不需要的频率:
for(int k=0; k<32;k++){
        if(k==0 || k>6 )
        {
            x_fft.ptr<float>(0)[2*k+0]=0;
            x_fft.ptr<float>(0)[2*k+1]=0;

        }
    }

将其转换回时间域:

cv::dft(x_fft, x_filt, cv::DFT_INVERSE, 0);

为了检查我的结果,我将它们与Matlab进行了比较。 我使用相同的信号x,使用x_mfft = fft(x)将其转换为傅里叶形式。 结果与我从opencv中得到的结果相似,除了在opencv中我只得到左侧,而在matlab中我也得到了对称值。 之后,在Matlab中我设置了x_mfft(0)和x_mfft(8:32)的值为0,现在信号看起来完全相同,除了在Matlab中它们以复杂形式存在,而在opencv中它们被分开,实部在一个通道,虚部在另一个通道。 问题是当我在Matlab中执行逆变换使用 x_mfilt = ifft(x_mfft) 时,结果与我在opencv中得到的结果完全不同。 Matlab:
0.0126024108604191 + 0.0100628178150509i    0.00278762121814893 - 0.00615997579216921i  0.0116716145588075 - 0.0150834711251450i    0.0204808089882897 - 0.00937680194210788i   0.0187164132302469 - 0.000843687942567208i  0.0132322795522116 - 0.000108642129381095i  0.0140282455278201 - 0.00325620843335947i   0.0190436542174946 - 0.000556561558544529i  0.0182379867325824 + 0.00764390022568001i   0.00964801276734883 + 0.0107158342431018i   0.00405220362962359 + 0.00339496875258604i  0.0108096973356501 - 0.00476499376334313i   0.0236507440224628 - 0.000415067678294738i  0.0266197220512826 + 0.0154626911663024i    0.0142805873081583 + 0.0267004219364679i    0.000314527358302778 + 0.0215255889620223i  0.00173512964620177 + 0.00865151513638104i  0.0169666351363477 + 0.00836162056544561i   0.0255915540012784 + 0.0277878383595920i    0.0118710562486680 + 0.0506446948330055i    -0.0160165379892836 + 0.0553846122152651i   -0.0354343989166415 + 0.0406080858067314i   -0.0370261047451452 + 0.0261077990289579i   -0.0365120038155127 + 0.0268311542287801i   -0.0541841640123775 + 0.0312446266697320i   -0.0854132555297956 + 0.0125342802025550i   -0.0989182320365535 - 0.0377079727602073i   -0.0686133217915410 - 0.0925138855355046i   -0.00474198249025186 - 0.111728716441247i   0.0515933837210975 - 0.0814138940625859i    0.0663201317560107 - 0.0279433757588921i    0.0426055814586485 + 0.00821080477569232i

cv::dft(x_fft, x_filt, cv::DFT_INVERSE, 0)之后的OpenCV处理

通道1:

0.322008 -0.197121 -0.482671 -0.300055 -0.026996 -0.003475 -0.104199 -0.017810 0.244606 0.342909 0.108642 -0.152477 -0.013281 0.494806 0.854412 0.688818 0.276848 0.267571 0.889207 1.620622 1.772298 1.299452 0.835450 0.858602 0.999833 0.401098 -1.206658 -2.960446 -3.575316 -2.605239 -0.894184 0.262747 

通道2:

0.403275 0.089205 0.373494 0.655387 0.598925 0.423432 0.448903 0.609397 0.583616 0.308737 0.129670 0.345907 0.756820 0.851827 0.456976 0.010063 0.055522 0.542928 0.818924 0.379870 -0.512527 -1.133893 -1.184826 -1.168379 -1.733893 -2.733226 -3.165383 -2.195622 -0.151738 1.650990 2.122242 1.363375 

我错过了什么吗?结果不应该很类似吗?我怎样可以检查opencv中的反向变换是否正确?

后期更新: 在苦苦挣扎了几个小时之后,我决定绘制Matlab和OpenCV的结果,令我惊讶的是它们非常相似。

虚部 enter image description here

实部: enter image description here

显然这是一个比例因子的问题。经过逐个元素的除法后,这个因子显然是32-信号的长度。有人能解释为什么会这样吗? 显然的解决方案是使用cv :: dft(x_fft,x_filt,cv :: DFT_INVERSE + cv :: DFT_SCALE,0);,所以我猜这个主题已经回答了,但我仍然对为什么会这样很感兴趣。


尝试通过将FFT频率置零来“消除”频率可能会给结果添加很多噪音。对于实数结果,IFFT的输入需要是共轭对称的,这意味着高频率必须镜像低频率的虚部,而不是置零。 - hotpaw2
为什么在 cv::dft(x, x_fft, cv::DFT_COMPLEX_OUTPUT, 0); 中使用 DFT_COMPLEX_OUTPUT?我也遇到了这个问题。如果设置了 DFT_COMPLEX_OUTPUT 标志,则会得到长度为2N的向量,如何对该向量进行滤波。如果没有设置 DFT_COMPLEX_OUTPUT 标志,则会得到长度为N的向量,滤波有什么区别。 - Phineas Lue
同样的问题也出现在iOS加速框架和OpenCV中,比例差异为2。而且结果的组织方式不同-据我所知(找不到文档),在OpenCV中,第一个元素是0频率的实部,然后是实部、虚部、实部、虚部...在加速框架中,它一直是实部、虚部、实部、虚部...编辑:好吧,在OpenCV的文档中说它是real(0) real(1) img(1) real(2) img(2).. http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#dft - dowi
好的,已经找到其他文档了。https://developer.apple.com/library/ios/documentation/Performance/Conceptual/vDSP_Programming_Guide/UsingFourierTransforms/UsingFourierTransforms.html#//apple_ref/doc/uid/TP40005147-CH202-15398 除了缩放因子之外,所有内容都在文档中呈现。 - dowi
1个回答

2

所有FFT库使用的比例因子都没有标准。有些不使用,有些包括1/N的比例因子,有些包括1/sqrt(N)的比例因子。您需要测试或查看每个特定库的文档。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接