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 << i << "/" << j << 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 的链接器错误