diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index 033bf45120..79cb31ceed 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -1473,6 +1473,47 @@ typedef IppStatus (CV_STDCALL* IppDFTGetSizeFunc)(int, int, IppHintAlgorithm, in typedef IppStatus (CV_STDCALL* IppDFTInitFunc)(int, int, IppHintAlgorithm, void*, uchar*); #endif +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 ) { static DFTFunc dft_tbl[6] = @@ -1688,8 +1729,12 @@ void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) memset( dptr0, 0, dst_full_len ); } - if( stage != 1 ) + if (stage != 1) + { + if (!inv && real_transform && dst.channels() == 2) + complementComplexOutput(dst, nonzero_rows, 1); break; + } src = dst; } else @@ -1831,41 +1876,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 = (float*)dst.data; - 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 = (double*)dst.data; - 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 1c0c7b00bf..33ddb02660 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); + } + } +}