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<float>* ptr = (Complex<float>*)_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<float> 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<double>* ptr = (Complex<double>*)_ptr;
-
- for( i = 1; i < (len+1)/2; i++ )
+ double* p = (double*)_ptr;
+ for( i = 1; i < (n+1)/2; i++ )
{
- Complex<double> 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;
}
}
}
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;
}
}
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;
}
}
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(); }
+