使用OpenCV作为数据源,使用CUFFT实现实到复FFT
我在尝试使用cuFFT对浮点数组执行二维变换时遇到了一个问题。我看了一下文档,但有些信息相互矛盾/不清楚;所以我有几个问题: 我的数据是使用OpenCV作为数据源,使用CUFFT实现实到复FFT,opencv,cuda,fft,Opencv,Cuda,Fft,我在尝试使用cuFFT对浮点数组执行二维变换时遇到了一个问题。我看了一下文档,但有些信息相互矛盾/不清楚;所以我有几个问题: 我的数据是480行,有640列(例如float data[480][640]但在单个维度中,所以float data[480*640]) 如果我们说我的输入维度(真实数据)是N1=480和N2=640。尺寸(经过实到复变换后)是否为N1=480、N2=321 我可以cudaMemcpy将数据直接放入相同大小的cufftReal数组中吗?或者它必须是一个cufftCompl
480
行,有640
列(例如float data[480][640]
但在单个维度中,所以float data[480*640]
)
N1=480
和N2=640
。尺寸(经过实到复变换后)是否为N1=480、N2=321cudaMemcpy
将数据直接放入相同大小的cufftReal
数组中吗?或者它必须是一个cufftComplex
数组
如果它必须是一个cufftComplex
数组,我假设元素需要位于真实组件的位置cufftPlan2d
、cufftExecR2C
和cufftC2R
的正确结构是什么cufftPlan2d
的使用存在歧义(因此我提出了问题)。在文档中,对于二维数组,数据应如上所述输入(float data[480][640]==float data[NY][NX]
),因此NY
表示行。但是,在cufftPlan2d
的函数列表中,它指出nx
(参数)用于行
在函数调用中交换NX
和NY
的值会得到与项目图像相同的结果(方向正确,但以正常大小的1/4分割为三个部分重叠的图像),但是,使用JackOLantern在其答案中陈述的参数会得到倾斜/扭曲的结果
我做错什么了吗?还是说cuFFT库在这方面有问题
另外:我已经撤销了JackOLantern对这个问题的一些编辑,因为我的问题可能源于我的数据来自OpenCV
1) 如果我们说我的输入维度(真实数据)是N1=480和N2=640。尺寸(从实到复变换后)N1=480,N2=321
cufftExecR2C的输出是一个NX*(NY/2+1)
cufftComplex
矩阵。因此,在您的例子中,您将有一个480x321
float2
矩阵作为输出
2) 我可以将数据直接压缩到相同大小的cufftReal
数组中吗?或者它必须是一个cufftComplex
数组
如果它必须是一个cufftComplex
数组,我假设元素需要位于真实组件的位置
可以,您可以将数据复制到cufftReal
数组和N1xN2
数据
3) 给定上述值,调用cufftPlan2d
、cufftExecR2C
和cufftC2R
的正确结构是什么
编辑:我最近发现是我在使用函数的方式上犯了错误 最初我认为函数定义指的是传递给它的数据的大小 然而,看起来这些参数实际上直接指的是真实零件的尺寸 这意味着参数指的是:
- 使用R2C时输入数据的大小(从实到复)
- 使用C2R时输出数据的大小(从复数到实数)
因此,cuFFT文档和库本身似乎不一致 当执行R2C后接C2R(分别为实数到复数、复数到实数)时,文件规定,对于NX NY维度的实数输入,复数输出为NX(地板(NY/2)+1);反之亦然 但是实际输出的尺寸为NX NY,实际输入的尺寸为NX NY。这个在第一页提到(一半),作为 C2R-对称复数输入到实输出 这意味着复杂数据必须是对称的,即除了非冗余数据外,还必须具有冗余数据 文档中还有许多其他矛盾之处,我将不详细介绍 不用说,问题已经解决了
我在下面附上了一个MWE。顶部附近有几行带有
#define NUM_C2
和适当注释。更改此项将更改是遵循文档格式还是我的“修复”
输出是
#include <iostream>
#include <math.h>
#include <cufft.h>
// e.g. float data[NUM_R][NUM_C]
#define NUM_R 12
#define NUM_C 16
// Documentation Version
//#define NUM_C2 (1+NUM_C/2)
// "Correct" Version
#define NUM_C2 NUM_C
using namespace std;
int main(int argc, char** argv)
{
cufftReal *in_h, *out_h, *in_d, *out_d;
cufftComplex *mid_d, *mid_h;
cufftHandle pF, pI;
int r, c;
in_h = (cufftReal*) malloc(NUM_R * NUM_C * sizeof(cufftReal));
out_h= (cufftReal*) malloc(NUM_R * NUM_C * sizeof(cufftReal));
mid_h= (cufftComplex*)malloc(NUM_C2*NUM_R*sizeof(cufftComplex));
cudaMalloc((void**) &in_d, NUM_R * NUM_C * sizeof(cufftReal));
cudaMalloc((void**)&out_d, NUM_R * NUM_C * sizeof(cufftReal));
cudaMalloc((void**)&mid_d, NUM_C2 * NUM_R * sizeof(cufftComplex));
cufftPlan2d(&pF, NUM_R, NUM_C, CUFFT_R2C);
cufftPlan2d(&pI, NUM_R,NUM_C2, CUFFT_C2R);
cout<<endl<<"------"<<endl;
for(r=0; r<NUM_R; r++)
{
for(c=0; c<NUM_C; c++)
{
in_h[c + NUM_C * r] = cos(2.0*M_PI*(c*7.0/NUM_C+r*3.0/NUM_R));
out_h[c+ NUM_C * r] = 0.f;
cout<<in_h[c+NUM_C*r];
if(c<(NUM_C-1)) cout<<", ";
else cout<<endl;
}
}
cudaMemcpy((cufftReal*)in_d, (cufftReal*)in_h, NUM_R * NUM_C * sizeof(cufftReal),cudaMemcpyHostToDevice);
cufftExecR2C(pF, (cufftReal*)in_d, (cufftComplex*)mid_d);
cudaMemcpy((cufftComplex*)mid_h, (cufftComplex*)mid_d, NUM_C2*NUM_R*sizeof(cufftComplex), cudaMemcpyDeviceToHost);
cout<<endl<<"------"<<endl;
for(r=0; r<NUM_R; r++)
{
for(c=0; c<NUM_C2; c++)
{
cout<<mid_h[c+(NUM_C2)*r].x<<"|"<<mid_h[c+(NUM_C2)*r].y;
if(c<(NUM_C2-1)) cout<<", ";
else cout<<endl;
}
}
cufftExecC2R(pI, (cufftComplex*)mid_d, (cufftReal*)out_d);
cudaMemcpy((cufftReal*)out_h, (cufftReal*)out_d, NUM_R*NUM_C*sizeof(cufftReal), cudaMemcpyDeviceToHost);
cout<<endl<<"------"<<endl;
for(r=0; r<NUM_R; r++)
{
for(c=0; c<NUM_C; c++)
{
cout<<out_h[c+NUM_C*r]/(NUM_R*NUM_C);
if(c<(NUM_C-1)) cout<<", ";
else cout<<endl;
}
}
cout<<endl<<"------"<<endl;
for(r=0; r<NUM_R; r++)
{
for(c=0; c<NUM_C; c++)
{
cout<<(out_h[c+NUM_C*r]/(NUM_R*NUM_C))/in_h[c+NUM_C*r];
if(c<(NUM_C-1)) cout<<", ";
else cout<<endl;
}
}
free(in_h);
free(out_h);
free(mid_h);
cudaFree(in_d);
cudaFree(out_h);
cudaFree(mid_d);
return 0;
}
#包括
#包括
#包括
//例如,浮点数据[NUM_R][NUM_C]
#定义NUM_R 12
#定义NUM_C 16
//文件版本
//#定义数量C2(1+数量C/2)
//“正确”版本
#定义NUM_C2 NUM_C
使用名称空间std;
int main(int argc,字符**argv)
{
卡夫特雷尔*进,出,进,出;
袖口复合体*mid_d,*mid_h;
f,pI;
int r,c;
in_h=(cufftReal*)malloc(NUM_R*NUM_C*sizeof(cufftReal));
out_h=(cufftReal*)malloc(NUM_R*NUM_C*sizeof(cufftReal));
mid_h=(袖套复合体*)malloc(NUM_C2*NUM_R*sizeof(袖套复合体));
cudamaloc((void**)和in_d,NUM_R*NUM_C*sizeof(cufftReal));
#include <iostream>
#include <math.h>
#include <cufft.h>
// e.g. float data[NUM_R][NUM_C]
#define NUM_R 12
#define NUM_C 16
// Documentation Version
//#define NUM_C2 (1+NUM_C/2)
// "Correct" Version
#define NUM_C2 NUM_C
using namespace std;
int main(int argc, char** argv)
{
cufftReal *in_h, *out_h, *in_d, *out_d;
cufftComplex *mid_d, *mid_h;
cufftHandle pF, pI;
int r, c;
in_h = (cufftReal*) malloc(NUM_R * NUM_C * sizeof(cufftReal));
out_h= (cufftReal*) malloc(NUM_R * NUM_C * sizeof(cufftReal));
mid_h= (cufftComplex*)malloc(NUM_C2*NUM_R*sizeof(cufftComplex));
cudaMalloc((void**) &in_d, NUM_R * NUM_C * sizeof(cufftReal));
cudaMalloc((void**)&out_d, NUM_R * NUM_C * sizeof(cufftReal));
cudaMalloc((void**)&mid_d, NUM_C2 * NUM_R * sizeof(cufftComplex));
cufftPlan2d(&pF, NUM_R, NUM_C, CUFFT_R2C);
cufftPlan2d(&pI, NUM_R,NUM_C2, CUFFT_C2R);
cout<<endl<<"------"<<endl;
for(r=0; r<NUM_R; r++)
{
for(c=0; c<NUM_C; c++)
{
in_h[c + NUM_C * r] = cos(2.0*M_PI*(c*7.0/NUM_C+r*3.0/NUM_R));
out_h[c+ NUM_C * r] = 0.f;
cout<<in_h[c+NUM_C*r];
if(c<(NUM_C-1)) cout<<", ";
else cout<<endl;
}
}
cudaMemcpy((cufftReal*)in_d, (cufftReal*)in_h, NUM_R * NUM_C * sizeof(cufftReal),cudaMemcpyHostToDevice);
cufftExecR2C(pF, (cufftReal*)in_d, (cufftComplex*)mid_d);
cudaMemcpy((cufftComplex*)mid_h, (cufftComplex*)mid_d, NUM_C2*NUM_R*sizeof(cufftComplex), cudaMemcpyDeviceToHost);
cout<<endl<<"------"<<endl;
for(r=0; r<NUM_R; r++)
{
for(c=0; c<NUM_C2; c++)
{
cout<<mid_h[c+(NUM_C2)*r].x<<"|"<<mid_h[c+(NUM_C2)*r].y;
if(c<(NUM_C2-1)) cout<<", ";
else cout<<endl;
}
}
cufftExecC2R(pI, (cufftComplex*)mid_d, (cufftReal*)out_d);
cudaMemcpy((cufftReal*)out_h, (cufftReal*)out_d, NUM_R*NUM_C*sizeof(cufftReal), cudaMemcpyDeviceToHost);
cout<<endl<<"------"<<endl;
for(r=0; r<NUM_R; r++)
{
for(c=0; c<NUM_C; c++)
{
cout<<out_h[c+NUM_C*r]/(NUM_R*NUM_C);
if(c<(NUM_C-1)) cout<<", ";
else cout<<endl;
}
}
cout<<endl<<"------"<<endl;
for(r=0; r<NUM_R; r++)
{
for(c=0; c<NUM_C; c++)
{
cout<<(out_h[c+NUM_C*r]/(NUM_R*NUM_C))/in_h[c+NUM_C*r];
if(c<(NUM_C-1)) cout<<", ";
else cout<<endl;
}
}
free(in_h);
free(out_h);
free(mid_h);
cudaFree(in_d);
cudaFree(out_h);
cudaFree(mid_d);
return 0;
}