fixed bug with partly uninitialized output of dft with DFT_COMPLEX_OUTPUT flag (bug...
authorVadim Pisarevsky <vadim.pisarevsky@itseez.com>
Wed, 10 Oct 2012 20:53:43 +0000 (00:53 +0400)
committerVadim Pisarevsky <vadim.pisarevsky@itseez.com>
Wed, 10 Oct 2012 20:53:43 +0000 (00:53 +0400)
modules/core/src/dxt.cpp
modules/core/test/test_dxt.cpp

index 04e9010..d89e627 100644 (file)
@@ -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<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;
     }
 }
 
@@ -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;
         }
     }
index fd3fdd6..ff3aa7c 100644 (file)
@@ -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(); }
+