core: use matlab-style in 2d fftShift
authorVladislav Sovrasov <sovrasov.vlad@gmail.com>
Thu, 13 Jul 2017 10:33:02 +0000 (13:33 +0300)
committerVladislav Sovrasov <sovrasov.vlad@gmail.com>
Thu, 13 Jul 2017 10:33:02 +0000 (13:33 +0300)
modules/imgproc/src/phasecorr.cpp
modules/imgproc/test/test_pc.cpp

index 6e9edfa..348cdd3 100644 (file)
@@ -388,22 +388,41 @@ static void fftShift(InputOutputArray _out)
     }
     else
     {
+        int isXodd = out.cols % 2 == 1;
+        int isYodd = out.rows % 2 == 1;
         for(size_t i = 0; i < planes.size(); i++)
         {
             // perform quadrant swaps...
-            Mat tmp;
-            Mat q0(planes[i], Rect(0,    0,    xMid, yMid));
-            Mat q1(planes[i], Rect(xMid, 0,    xMid, yMid));
-            Mat q2(planes[i], Rect(0,    yMid, xMid, yMid));
-            Mat q3(planes[i], Rect(xMid, yMid, xMid, yMid));
-
-            q0.copyTo(tmp);
-            q3.copyTo(q0);
-            tmp.copyTo(q3);
-
-            q1.copyTo(tmp);
-            q2.copyTo(q1);
-            tmp.copyTo(q2);
+            Mat q0(planes[i], Rect(0,    0,    xMid + isXodd, yMid + isYodd));
+            Mat q1(planes[i], Rect(xMid + isXodd, 0,    xMid, yMid + isYodd));
+            Mat q2(planes[i], Rect(0,    yMid + isYodd, xMid + isXodd, yMid));
+            Mat q3(planes[i], Rect(xMid + isXodd, yMid + isYodd, xMid, yMid));
+
+            if(!(isXodd || isYodd))
+            {
+                Mat tmp;
+                q0.copyTo(tmp);
+                q3.copyTo(q0);
+                tmp.copyTo(q3);
+
+                q1.copyTo(tmp);
+                q2.copyTo(q1);
+                tmp.copyTo(q2);
+            }
+            else
+            {
+                Mat tmp0, tmp1, tmp2 ,tmp3;
+                q0.copyTo(tmp0);
+                q1.copyTo(tmp1);
+                q2.copyTo(tmp2);
+                q3.copyTo(tmp3);
+
+                tmp0.copyTo(planes[i](Rect(xMid, yMid, xMid + isXodd, yMid + isYodd)));
+                tmp3.copyTo(planes[i](Rect(0, 0, xMid, yMid)));
+
+                tmp1.copyTo(planes[i](Rect(0, yMid, xMid, yMid + isYodd)));
+                tmp2.copyTo(planes[i](Rect(xMid, 0, xMid + isXodd, yMid)));
+            }
         }
     }
 
index ce876ba..64bed46 100644 (file)
@@ -78,7 +78,7 @@ void CV_PhaseCorrelatorTest::run( int )
     Point2d phaseShift = phaseCorrelate(r1, r2, hann);
 
     // test accuracy should be less than 1 pixel...
-    if((expectedShiftX - phaseShift.x) >= 1 || (expectedShiftY - phaseShift.y) >= 1)
+    if(std::abs(expectedShiftX - phaseShift.x) >= 1 || std::abs(expectedShiftY - phaseShift.y) >= 1)
     {
          ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
     }
@@ -86,6 +86,27 @@ void CV_PhaseCorrelatorTest::run( int )
 
 TEST(Imgproc_PhaseCorrelatorTest, accuracy) { CV_PhaseCorrelatorTest test; test.safe_run(); }
 
+TEST(Imgproc_PhaseCorrelatorTest, accuracy_real_img)
+{
+    Mat img = imread(cvtest::TS::ptr()->get_data_path() + "shared/airplane.png", IMREAD_GRAYSCALE);
+    img.convertTo(img, CV_64FC1);
+
+    const int xLen = 129;
+    const int yLen = 129;
+    const int xShift = 40;
+    const int yShift = 14;
+
+    Mat roi1 = img(Rect(xShift, yShift, xLen, yLen));
+    Mat roi2 = img(Rect(0, 0, xLen, yLen));
+
+    Mat hann;
+    createHanningWindow(hann, roi1.size(), CV_64F);
+    Point2d phaseShift = phaseCorrelate(roi1, roi2, hann);
+
+    ASSERT_NEAR(phaseShift.x, (double)xShift, 1.);
+    ASSERT_NEAR(phaseShift.y, (double)yShift, 1.);
+}
+
 TEST(Imgproc_PhaseCorrelatorTest, accuracy_1d_odd_fft) {
     Mat r1 = Mat::ones(Size(129, 1), CV_64F)*255; // 129 will be completed to 135 before FFT
     Mat r2 = Mat::ones(Size(129, 1), CV_64F)*255;
@@ -100,7 +121,7 @@ TEST(Imgproc_PhaseCorrelatorTest, accuracy_1d_odd_fft) {
 
     Point2d phaseShift = phaseCorrelate(r1, r2);
 
-    ASSERT_NEAR(phaseShift.x, (double)xShift, .5);
+    ASSERT_NEAR(phaseShift.x, (double)xShift, 1.);
 }
 
 }