From 8f0d36b8b6a81be8afb1cf6d1ccdfdd2882d0d56 Mon Sep 17 00:00:00 2001 From: Alexey Spizhevoy Date: Mon, 27 Dec 2010 07:35:41 +0000 Subject: [PATCH] refactored gpu::dft --- modules/gpu/include/opencv2/gpu/gpu.hpp | 11 +++--- modules/gpu/src/imgproc_gpu.cpp | 52 +++++++++---------------- tests/gpu/src/dft_routines.cpp | 10 ++--- 3 files changed, 28 insertions(+), 45 deletions(-) diff --git a/modules/gpu/include/opencv2/gpu/gpu.hpp b/modules/gpu/include/opencv2/gpu/gpu.hpp index 6c11c19ea..56758ce47 100644 --- a/modules/gpu/include/opencv2/gpu/gpu.hpp +++ b/modules/gpu/include/opencv2/gpu/gpu.hpp @@ -640,8 +640,9 @@ namespace cv CV_EXPORTS void mulAndScaleSpectrums(const GpuMat& a, const GpuMat& b, GpuMat& c, int flags, float scale, bool conjB=false); - //! performs a forward or inverse discrete Fourier transform (1D or 2D) of floating point matrix - //! + //! Performs a forward or inverse discrete Fourier transform (1D or 2D) of floating point matrix. + //! Param dft_size is the size of DFT transform. + //! //! If the source matrix is not continous, then additional copy will be done, //! so to avoid copying ensure the source matrix is continous one. If you want to use //! preallocated output ensure it is continuous too, otherwise it will be reallocated. @@ -649,10 +650,8 @@ namespace cv //! Being implemented via CUFFT real-to-complex transform result contains only non-redundant values //! in CUFFT's format. Result as full complex matrix for such kind of transform cannot be retrieved. //! - //! For complex-to-real transform it is assumed that the source matrix is packed in CUFFT's format, which - //! doesn't allow us to retrieve parity of the destiantion matrix dimension (along which the first step - //! of DFT is performed). You must specifiy odd case explicitely. - CV_EXPORTS void dft(const GpuMat& src, GpuMat& dst, int flags=0, int nonZeroRows=0, bool odd=false); + //! For complex-to-real transform it is assumed that the source matrix is packed in CUFFT's format. + CV_EXPORTS void dft(const GpuMat& src, GpuMat& dst, Size dft_size, int flags=0); //! computes convolution (or cross-correlation) of two images using discrete Fourier transform //! supports source images of 32FC1 type only diff --git a/modules/gpu/src/imgproc_gpu.cpp b/modules/gpu/src/imgproc_gpu.cpp index 0258c4250..6022beca1 100644 --- a/modules/gpu/src/imgproc_gpu.cpp +++ b/modules/gpu/src/imgproc_gpu.cpp @@ -76,7 +76,7 @@ void cv::gpu::cornerHarris(const GpuMat&, GpuMat&, int, int, double, int) { thro void cv::gpu::cornerMinEigenVal(const GpuMat&, GpuMat&, int, int, int) { throw_nogpu(); } void cv::gpu::mulSpectrums(const GpuMat&, const GpuMat&, GpuMat&, int, bool) { throw_nogpu(); } void cv::gpu::mulAndScaleSpectrums(const GpuMat&, const GpuMat&, GpuMat&, int, float, bool) { throw_nogpu(); } -void cv::gpu::dft(const GpuMat&, GpuMat&, int, int, bool) { throw_nogpu(); } +void cv::gpu::dft(const GpuMat&, GpuMat&, Size, int) { throw_nogpu(); } void cv::gpu::convolve(const GpuMat&, const GpuMat&, GpuMat&, bool) { throw_nogpu(); } @@ -1130,14 +1130,14 @@ void cv::gpu::mulAndScaleSpectrums(const GpuMat& a, const GpuMat& b, GpuMat& c, ////////////////////////////////////////////////////////////////////////////// // dft -void cv::gpu::dft(const GpuMat& src, GpuMat& dst, int flags, int nonZeroRows, bool odd) +void cv::gpu::dft(const GpuMat& src, GpuMat& dst, Size dft_size, int flags) { CV_Assert(src.type() == CV_32F || src.type() == CV_32FC2); // We don't support unpacked output (in the case of real input) CV_Assert(!(flags & DFT_COMPLEX_OUTPUT)); - bool is_1d_input = (src.rows == 1) || (src.cols == 1); + bool is_1d_input = (dft_size.height == 1) || (dft_size.width == 1); int is_row_dft = flags & DFT_ROWS; int is_scaled_dft = flags & DFT_SCALE; int is_inverse = flags & DFT_INVERSE; @@ -1156,63 +1156,49 @@ void cv::gpu::dft(const GpuMat& src, GpuMat& dst, int flags, int nonZeroRows, bo if (src_data.data != src.data) src.copyTo(src_data); + Size dft_size_ = dft_size; if (is_1d_input && !is_row_dft) - // If the source matrix is single column reshape it into single row - src_data = src_data.reshape(0, std::min(src.rows, src.cols)); + { + // If the source matrix is single column handle it as single row + dft_size_.width = std::max(dft_size.width, dft_size.height); + dft_size_.height = std::min(dft_size.width, dft_size.height); + } cufftType dft_type = CUFFT_R2C; if (is_complex_input) dft_type = is_complex_output ? CUFFT_C2C : CUFFT_C2R; - int dft_rows = src_data.rows; - int dft_cols = src_data.cols; - if (is_complex_input && !is_complex_output) - dft_cols = (src_data.cols - 1) * 2 + (int)odd; - CV_Assert(dft_cols > 1); + CV_Assert(dft_size_.width > 1); cufftHandle plan; if (is_1d_input || is_row_dft) - cufftPlan1d(&plan, dft_cols, dft_type, dft_rows); + cufftPlan1d(&plan, dft_size_.width, dft_type, dft_size_.height); else - cufftPlan2d(&plan, dft_rows, dft_cols, dft_type); - - int dst_cols, dst_rows; + cufftPlan2d(&plan, dft_size_.height, dft_size_.width, dft_type); if (is_complex_input) { if (is_complex_output) { - createContinuous(src.rows, src.cols, CV_32FC2, dst); + createContinuous(dft_size, CV_32FC2, dst); cufftSafeCall(cufftExecC2C( plan, src_data.ptr(), dst.ptr(), is_inverse ? CUFFT_INVERSE : CUFFT_FORWARD)); } else { - dst_rows = src.rows; - dst_cols = (src.cols - 1) * 2 + (int)odd; - if (src_data.size() != src.size()) - { - dst_rows = (src.rows - 1) * 2 + (int)odd; - dst_cols = src.cols; - } - - createContinuous(dst_rows, dst_cols, CV_32F, dst); + createContinuous(dft_size, CV_32F, dst); cufftSafeCall(cufftExecC2R( plan, src_data.ptr(), dst.ptr())); } } else { - dst_rows = src.rows; - dst_cols = src.cols / 2 + 1; - if (src_data.size() != src.size()) - { - dst_rows = src.rows / 2 + 1; - dst_cols = src.cols; - } + if (dft_size == dft_size_) + createContinuous(Size(dft_size.width / 2 + 1, dft_size.height), CV_32FC2, dst); + else + createContinuous(Size(dft_size.width, dft_size.height / 2 + 1), CV_32FC2, dst); - createContinuous(dst_rows, dst_cols, CV_32FC2, dst); cufftSafeCall(cufftExecR2C( plan, src_data.ptr(), dst.ptr())); } @@ -1220,7 +1206,7 @@ void cv::gpu::dft(const GpuMat& src, GpuMat& dst, int flags, int nonZeroRows, bo cufftSafeCall(cufftDestroy(plan)); if (is_scaled_dft) - multiply(dst, Scalar::all(1. / (dft_rows * dft_cols)), dst); + multiply(dst, Scalar::all(1. / (dft_size.area())), dst); } ////////////////////////////////////////////////////////////////////////////// diff --git a/tests/gpu/src/dft_routines.cpp b/tests/gpu/src/dft_routines.cpp index 6a5ad3880..3c7b0bf9d 100644 --- a/tests/gpu/src/dft_routines.cpp +++ b/tests/gpu/src/dft_routines.cpp @@ -328,7 +328,7 @@ struct CV_GpuDftTest: CvTest d_b = GpuMat(a.rows, a.cols, CV_32FC2, d_b_data.ptr(), a.cols * d_b_data.elemSize()); } - dft(GpuMat(a), d_b, flags); + dft(GpuMat(a), d_b, Size(cols, rows), flags); bool ok = true; if (ok && inplace && d_b.ptr() != d_b_data.ptr()) @@ -360,9 +360,6 @@ struct CV_GpuDftTest: CvTest Mat a; gen(cols, rows, 1, a); - bool odd = false; - if (a.cols == 1) odd = a.rows % 2 == 1; - else odd = a.cols % 2 == 1; bool ok = true; GpuMat d_b, d_c; @@ -382,8 +379,9 @@ struct CV_GpuDftTest: CvTest d_c_data.create(1, a.size().area(), CV_32F); d_c = GpuMat(a.rows, a.cols, CV_32F, d_c_data.ptr(), a.cols * d_c_data.elemSize()); } - dft(GpuMat(a), d_b, 0); - dft(d_b, d_c, DFT_REAL_OUTPUT | DFT_SCALE, 0, odd); + + dft(GpuMat(a), d_b, Size(cols, rows), 0); + dft(d_b, d_c, Size(cols, rows), DFT_REAL_OUTPUT | DFT_SCALE); if (ok && inplace && d_b.ptr() != d_b_data.ptr()) {