diff --git a/modules/core/src/dxt.cpp b/modules/core/src/dxt.cpp index 04e90109ec..d89e6278b3 100644 --- a/modules/core/src/dxt.cpp +++ b/modules/core/src/dxt.cpp @@ -1362,38 +1362,44 @@ CopyTo2Columns( const uchar* _src0, const uchar* _src1, static void -ExpandCCS( uchar* _ptr, int len, int elem_size ) +ExpandCCS( uchar* _ptr, int n, int elem_size ) { int i; - _ptr -= elem_size; - memcpy( _ptr, _ptr + elem_size, elem_size ); - memset( _ptr + elem_size, 0, elem_size ); - if( (len & 1) == 0 ) - memset( _ptr + (len+1)*elem_size, 0, elem_size ); - - if( elem_size == sizeof(float) ) + if( elem_size == (int)sizeof(float) ) { - Complex* ptr = (Complex*)_ptr; - - for( i = 1; i < (len+1)/2; i++ ) + float* p = (float*)_ptr; + for( i = 1; i < (n+1)/2; i++ ) + { + p[(n-i)*2] = p[i*2-1]; + p[(n-i)*2+1] = -p[i*2]; + } + if( (n & 1) == 0 ) { - Complex t; - t.re = ptr[i].re; - t.im = -ptr[i].im; - ptr[len-i] = t; + p[n] = p[n-1]; + p[n+1] = 0.f; + n--; } + for( i = n-1; i > 0; i-- ) + p[i+1] = p[i]; + p[1] = 0.f; } else { - Complex* ptr = (Complex*)_ptr; - - for( i = 1; i < (len+1)/2; i++ ) + double* p = (double*)_ptr; + for( i = 1; i < (n+1)/2; i++ ) { - Complex t; - t.re = ptr[i].re; - t.im = -ptr[i].im; - ptr[len-i] = t; + p[(n-i)*2] = p[i*2-1]; + p[(n-i)*2+1] = -p[i*2]; } + if( (n & 1) == 0 ) + { + p[n] = p[n-1]; + p[n+1] = 0.f; + n--; + } + for( i = n-1; i > 0; i-- ) + p[i+1] = p[i]; + p[1] = 0.f; } } @@ -1723,13 +1729,13 @@ void cv::dft( InputArray _src0, OutputArray _dst, int flags, int nonzero_rows ) } else if( src.channels() == 1 ) { - CopyColumn( sptr0, src.step, buf0 + elem_size, elem_size, len, elem_size ); - ExpandCCS( buf0 + elem_size, len, elem_size ); + CopyColumn( sptr0, src.step, buf0, elem_size, len, elem_size ); + ExpandCCS( buf0, len, elem_size ); if( even ) { CopyColumn( sptr0 + (count-1)*elem_size, src.step, - buf1 + elem_size, elem_size, len, elem_size ); - ExpandCCS( buf1 + elem_size, len, elem_size ); + buf1, elem_size, len, elem_size ); + ExpandCCS( buf1, len, elem_size ); } sptr0 += elem_size; } @@ -1814,7 +1820,45 @@ 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]; + } + } + } + } break; + } src = dst; } } diff --git a/modules/core/test/test_dxt.cpp b/modules/core/test/test_dxt.cpp index fd3fdd6fd5..ff3aa7c156 100644 --- a/modules/core/test/test_dxt.cpp +++ b/modules/core/test/test_dxt.cpp @@ -827,4 +827,39 @@ TEST(Core_DCT, accuracy) { CxCore_DCTTest test; test.safe_run(); } TEST(Core_DFT, accuracy) { CxCore_DFTTest test; test.safe_run(); } TEST(Core_MulSpectrums, accuracy) { CxCore_MulSpectrumsTest test; test.safe_run(); } +class Core_DFTComplexOutputTest : public cvtest::BaseTest +{ +public: + Core_DFTComplexOutputTest() {} + ~Core_DFTComplexOutputTest() {} +protected: + void run(int) + { + RNG& rng = theRNG(); + for( int i = 0; i < 10; i++ ) + { + int m = rng.uniform(2, 11) & -2; + int n = rng.uniform(2, 11) & -2; + int depth = rng.uniform(0, 2) + CV_32F; + Mat src8u(m, n, depth), src(m, n, depth), dst(m, n, CV_MAKETYPE(depth, 2)); + Mat z = Mat::zeros(m, n, depth), dstz; + randu(src8u, Scalar::all(0), Scalar::all(10)); + src8u.convertTo(src, src.type()); + dst = Scalar::all(123); + Mat mv[] = {src, z}, srcz; + merge(mv, 2, srcz); + dft(srcz, dstz); + dft(src, dst, DFT_COMPLEX_OUTPUT); + if(norm(dst, dstz, NORM_INF) > 1e-3) + { + cout << "actual:\n" << dst << endl << endl; + cout << "reference:\n" << dstz << endl << endl; + CV_Error(CV_StsError, ""); + } + } + } +}; + +TEST(Core_DFT, complex_output) { Core_DFTComplexOutputTest test; test.safe_run(); } +