FFTW 和 OpenCV 的 C++ 接口,Mat 输出中的实部和虚部

Posted

技术标签:

【中文标题】FFTW 和 OpenCV 的 C++ 接口,Mat 输出中的实部和虚部【英文标题】:FFTW and OpenCV's C++ interface, real and imaginary part in Mat output 【发布时间】:2012-11-26 11:18:35 【问题描述】:

我正在尝试使用 C++ 接口使用 FFTW 3.3 和 OpenCV 2.1 编写 FFT/IFFT 函数。我看过很多使用旧 OpenCV 格式的示例,我进行了直接转换,但有些东西不起作用。

我的函数的目标是返回一个具有 FFT 实部和虚部的 Mat 对象,就像 dft 默认 OpenCV 函数一样。这是函数的代码。程序在将 im_data 复制到 data_in 的行中因内存问题而阻塞。

有人知道我做错了什么吗?谢谢

Mat fft_sr(Mat& I)


double          *im_data;
double          *realP_data;
double          *imP_data;

fftw_complex    *data_in;
fftw_complex    *fft;      

fftw_plan       plan_f;

int width     = I.cols;
int height    = I.rows;
int step      = I.step;

int             i, j, k;

Mat realP=Mat::zeros(height,width,CV_64F); // Real Part FFT
Mat imP=Mat::zeros(height,width,CV_64F); // Imaginary Part FFT


im_data = ( double* ) I.data;
realP_data = ( double* ) realP.data;
imP_data = ( double* ) imP.data;


data_in = ( fftw_complex* )fftw_malloc( sizeof( fftw_complex ) * width * height );
fft     = ( fftw_complex* )fftw_malloc( sizeof( fftw_complex ) * width * height );

// Problem Here
for( i = 0, k = 0 ; i < height ; i++ ) 
    for( j = 0 ; j < width ; j++ ) 
        data_in[k][0] = ( double )im_data[i * step + j];
        data_in[k][1] = ( double )0.0;
        k++;
    



plan_f = fftw_plan_dft_2d( height, width, data_in, fft,  FFTW_FORWARD,  FFTW_ESTIMATE );


fftw_execute( plan_f );

// Copy real and imaginary data
for( i = 0, k = 0 ; i < height ; i++ ) 
    for( j = 0 ; j < width ; j++ ) 
        realP_data[i * step + j] = ( double )fft[k][0];
        imP_data[i * step + j] = ( double )fft[k][1];
        k++;

    




Mat fft_I(I.size(),CV_64FC2);
Mat fftplanes[] = Mat_<double>(realP), Mat_<double>(imP);
merge(fftplanes, 2, fft_I);

fftw_destroy_plan(plan_f);
fftw_free(data_in);
fftw_free(fft);
return fft_I;   

【问题讨论】:

step 设置为什么? “这里的问题”到底是什么意思?当您将行 std:cout &lt;&lt; i &lt;&lt; "/" &lt;&lt; j &lt;&lt; std::endl; 添加到产生问题的嵌套循环结构的内部循环主体时会发生什么? 步长固定为 4096(8 字节(CV_64F,64 位浮点数)* 512(行大小)),它们是 512x512 图像。添加这一行,它会在 i=64,j=506 处引发“访问冲突读取位置 0x04331000” 【参考方案1】:

您使用 step 错误。它旨在索引到Mat::data。由于您在将Mat::data 分配给im_data 时已经将Mat::data 转换为double*,因此您可以“通常”索引到im_data

data_in[k][0] = im_data[i * width + j];

当使用step时,正确的索引方式是:

data_in[k][0] = ( double )I.data[i * step + j];

更新:

尝试按行访问您的图像。这样您就可以避免遇到步幅/步幅问题,同时仍然可以利用快速访问:

for (int i = 0; i < I.rows; i++)

    double* row = I.ptr<double>(i);

    for (int j = 0; j < I.cols; j++)
    
        // Do something with the current pixel.
        double someValue = row[j];
    

【讨论】:

很遗憾,经过多次测试,还是不行。昨天,我更改了您建议的行(以两种方式),但没有出现内存错误,我认为结果还可以。在不同的场景下测试后,它不能正常工作(在fft/ifft函数的同一行或类似的内存访问行中得到相同的错误)。当没有内存错误时,该函数不会正确返回图像的 FFT。 @aristos 我猜你仍然在其他地方做一些错误的索引。您是否有理由直接访问Mat::data?为什么不先使用Mat::at() 以实现更安全的内存访问并在以后提高性能?无论如何,在我提供更多帮助之前,您必须更新问题中的代码并准确描述发生错误的位置。 Mat::at() 比直接访问Mat::data 慢,不是吗?嗯,我试过了,但时间成本太高了,这就是我寻找替代品的原因 @aristos 我用一个新建议更新了我的答案。如果这没有帮助,请将您的问题重新处理为一个最小但完整的示例。【参考方案2】:

我知道这很旧,但是当您使用 fftw 时,您需要初始化 fftw_complex *data_in 只有在为 fft 创建计划之后,如果我没记错的话,当您创建计划时,它会设置所有 *data_in 值为 0。 所以在计划之前分配,之后初始化!

【讨论】:

【参考方案3】:

声明

im_data = ( double* ) I.data;

im_data 定义为double 指向图像数据的指针。 我认为I 是双值图像应该是强制性的。

【讨论】:

以上是关于FFTW 和 OpenCV 的 C++ 接口,Mat 输出中的实部和虚部的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 fftw3 Visual Studio 2010 的 openCV 的链接器错误

fftw 来自幅度和相位阵列的 C++ 逆二维 FFT

FFTW 从 numpy.fft 产生不同的结果

FFTW 反向变换乘以 N

什么可能导致源自 fftw_destroy_plan 的分段错误

OpenCV学习C++接口 Mat像素遍历详解