diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index 129127820..3d3d58906 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -60,7 +60,6 @@ namespace cv #undef USE_IPP_DFT #endif - /****************************************************************************************\ Discrete Fourier Transform \****************************************************************************************/ @@ -2426,6 +2425,47 @@ static bool ocl_dft_amdfft(InputArray _src, OutputArray _dst, int flags) #endif // HAVE_CLAMDFFT +namespace cv +{ +static void complementComplexOutput(Mat& dst, int len, int dft_dims) +{ + int i, n = dst.cols; + size_t elem_size = dst.elemSize1(); + if( elem_size == sizeof(float) ) + { + float* p0 = dst.ptr(); + size_t dstep = dst.step/sizeof(p0[0]); + for( i = 0; i < len; i++ ) + { + float* p = p0 + dstep*i; + float* q = dft_dims == 1 || i == 0 || i*2 == len ? p : p0 + dstep*(len-i); + + for( int j = 1; j < (n+1)/2; j++ ) + { + p[(n-j)*2] = q[j*2]; + p[(n-j)*2+1] = -q[j*2+1]; + } + } + } + else + { + double* p0 = dst.ptr(); + size_t dstep = dst.step/sizeof(p0[0]); + for( i = 0; i < len; i++ ) + { + double* p = p0 + dstep*i; + double* q = dft_dims == 1 || i == 0 || i*2 == len ? p : p0 + dstep*(len-i); + + for( int j = 1; j < (n+1)/2; j++ ) + { + p[(n-j)*2] = q[j*2]; + p[(n-j)*2+1] = -q[j*2+1]; + } + } + } +} +} + void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) { #ifdef HAVE_CLAMDFFT @@ -2705,7 +2745,11 @@ void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) } if( stage != 1 ) + { + if( !inv && real_transform && dst.channels() == 2 ) + complementComplexOutput(dst, nonzero_rows, 1); break; + } src = dst; } else @@ -2847,41 +2891,7 @@ void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) if( stage != 0 ) { if( !inv && real_transform && dst.channels() == 2 && len > 1 ) - { - int n = dst.cols; - if( elem_size == (int)sizeof(float) ) - { - float* p0 = dst.ptr(); - size_t dstep = dst.step/sizeof(p0[0]); - for( i = 0; i < len; i++ ) - { - float* p = p0 + dstep*i; - float* q = i == 0 || i*2 == len ? p : p0 + dstep*(len-i); - - for( int j = 1; j < (n+1)/2; j++ ) - { - p[(n-j)*2] = q[j*2]; - p[(n-j)*2+1] = -q[j*2+1]; - } - } - } - else - { - double* p0 = dst.ptr(); - size_t dstep = dst.step/sizeof(p0[0]); - for( i = 0; i < len; i++ ) - { - double* p = p0 + dstep*i; - double* q = i == 0 || i*2 == len ? p : p0 + dstep*(len-i); - - for( int j = 1; j < (n+1)/2; j++ ) - { - p[(n-j)*2] = q[j*2]; - p[(n-j)*2+1] = -q[j*2+1]; - } - } - } - } + complementComplexOutput(dst, len, 2); break; } src = dst; diff --git a/modules/core/test/test_dxt.cpp b/modules/core/test/test_dxt.cpp index 2e7bb38ea..ad75e52dd 100644 --- a/modules/core/test/test_dxt.cpp +++ b/modules/core/test/test_dxt.cpp @@ -866,3 +866,24 @@ protected: }; TEST(Core_DFT, complex_output) { Core_DFTComplexOutputTest test; test.safe_run(); } + +TEST(Core_DFT, complex_output2) +{ + for( int i = 0; i < 100; i++ ) + { + int type = theRNG().uniform(0, 2) ? CV_64F : CV_32F; + int m = theRNG().uniform(1, 10); + int n = theRNG().uniform(1, 10); + Mat x(m, n, type), out; + randu(x, -1., 1.); + dft(x, out, DFT_ROWS | DFT_COMPLEX_OUTPUT); + double nrm = norm(out, NORM_INF); + double thresh = n*m*2; + if( nrm > thresh ) + { + cout << "x: " << x << endl; + cout << "out: " << out << endl; + ASSERT_LT(nrm, thresh); + } + } +}