diff --git a/modules/imgproc/src/phasecorr.cpp b/modules/imgproc/src/phasecorr.cpp index 6e9edfad61..348cdd310e 100644 --- a/modules/imgproc/src/phasecorr.cpp +++ b/modules/imgproc/src/phasecorr.cpp @@ -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)); + 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)); - q0.copyTo(tmp); - q3.copyTo(q0); - tmp.copyTo(q3); + if(!(isXodd || isYodd)) + { + Mat tmp; + q0.copyTo(tmp); + q3.copyTo(q0); + tmp.copyTo(q3); - q1.copyTo(tmp); - q2.copyTo(q1); - tmp.copyTo(q2); + 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))); + } } } diff --git a/modules/imgproc/test/test_pc.cpp b/modules/imgproc/test/test_pc.cpp index ce876ba88a..64bed46622 100644 --- a/modules/imgproc/test/test_pc.cpp +++ b/modules/imgproc/test/test_pc.cpp @@ -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.); } }