如何使用OpenCV CUDA傅立叶变换

时间:2018-09-18 16:42:52

标签: opencv

我想使用 firm date package price qty revenue 1 firm1 2009-12 7266 2749 4518 12419982 2 firm1 2010-12 10057 3254 6803 22136962 3 firm1 2011-12 11652 3433 8219 28215827 4 firm1 2012-03 22337 16857 5480 92376360 5 firm1 2013-03 33315 30396 2919 88725924 6 firm1 2014-03 45074 33045 12029 397498305 7 firm1 2015-03 125999 108193 17806 1926484558 8 firm1 2016-03 115696 106818 8878 948330204 9 firm1 2017-03 150801 143736 7065 1015494840 10 firm1 2018-03 210210 199309 10901 2172667409 11 firm2 2009-12 NA 38 NA NA 12 firm2 2010-12 NA 94 NA NA 13 firm2 2011-12 NA 559 NA NA 14 firm2 2012-03 97 1315 NA NA 15 firm2 2013-03 208 4952 NA NA 16 firm2 2014-03 191 16006 NA NA 17 firm2 2015-03 256 11163 NA NA 18 firm2 2016-03 451 11738 NA NA 19 firm2 2017-03 652 21374 NA NA 20 firm2 2018-03 NA 25370 4535 115052950 来代替OpenCV的常规dft。首先,我尝试执行正向和逆向转换,但结果看起来与输入的内容完全不同。这是使用OpenCV example image的一个最小示例:

cuda::dft

我玩过标志,但是// Load 8bit test image (https://raw.githubusercontent.com/opencv/opencv/master/samples/data/basketball1.png) Mat testImg; testImg = imread("basketball1.png", CV_LOAD_IMAGE_GRAYSCALE); // Convert input to complex float image Mat_<float> imgReal; testImg.convertTo(imgReal, CV_32F, 1.0/255.0); Mat imgImag = Mat(imgReal.rows, imgReal.cols, CV_32F, float(0)); vector<Mat> channels; channels.push_back(imgReal); channels.push_back(imgImag); Mat imgComplex; merge(channels,imgComplex); imshow("Img real", imgReal); waitKey(0); //Perform a Fourier transform cuda::GpuMat imgGpu, fftGpu; imgGpu.upload(imgComplex); cuda::dft(imgGpu, fftGpu, imgGpu.size()); //Performs an inverse Fourier transform cuda::GpuMat propGpu, convFftGpu; cuda::dft(fftGpu, propGpu, imgGpu.size(), DFT_REAL_OUTPUT | DFT_SCALE); Mat output(propGpu); output.convertTo(output, CV_8U, 255, 0); imshow("Output", output); waitKey(0); 看上去从来都不像输入。使用上面的代码,我将得到输出:

enter image description here

看起来应该像这样:

enter image description here

2 个答案:

答案 0 :(得分:0)

我找到了答案here。显然,从复杂的输入图像开始时,不可能使用标志options.DocInclusionPredicate((version, desc) => { if (!desc.TryGetMethodInfo(out MethodInfo methodInfo)) return false; var versions = methodInfo.DeclaringType .GetCustomAttributes(true) .OfType<ApiVersionAttribute>() .SelectMany(attr => attr.Versions); return versions.Any(v => $"v{v.ToString()}" == version); });

或者使用一个通道的浮点输入进行正向变换,然后从逆变换中获得与输出相同的结果,或者从两个通道的复数输入图像开始并获得该类型作为输出。使用复杂输入图像的好处是前向变换可提供完整大小的复杂字段以供处理,例如执行卷积(有关详细信息,请参见链接的答案)。

我将添加该值,以便从逆变换中获得8位图像,请自己计算幅度,如下所示:

DFT_REAL_OUTPUT

答案 1 :(得分:0)

要使用 OpenCV Cuda FFT 进入傅立叶域并返回空间域,您可以简单地按照以下示例进行操作(要了解更多信息,您可以参考 cufft documentation,其中 OpenCV Cuda FFT source code是基于)。

Mat test_im;
test_im = imread("frame.png", IMREAD_GRAYSCALE);

// Convert input input to real value type (CV_64F for double precision)
Mat im_real;
test_im.convertTo(im_real, CV_32F, 1.0/255.0);

imshow("Input Image", im_real);
waitKey(0);

// Perform The Fourier Transform
cuda::GpuMat in_im_gpu, fft_im;
in_im_gpu.upload(im_real);
cuda::dft(in_im_gpu, fft_im, in_im_gpu.size(), 0);

// Performs an inverse Fourier transform
cuda::GpuMat ifft_im_gpu;
//! int odd_size = imgGpu.size().width % 2;
//! cv::Size dest_size((fftGpu.size().width-1)*2 + (odd_size ? 1 : 0), fftGpu.size().height);
cv::Size dest_size = in_im_gpu.size();
int flag = (DFT_SCALE + DFT_REAL_OUTPUT) | DFT_INVERSE;
cuda::dft(fft_im, ifft_im_gpu, dest_size, flag);

Mat ifft_im(ifft_im_gpu);
ifft_im.convertTo(ifft_im, CV_8U, 255, 0);

imshow("Inverse FFT", ifft_im);
waitKey(0);