Skip to content

Commit 3f794cd

Browse files
committed
Merge pull request opencv#9147 from sovrasov:phase_corr_fix
2 parents a0d3d11 + bb0f9d6 commit 3f794cd

File tree

2 files changed

+76
-18
lines changed

2 files changed

+76
-18
lines changed

modules/imgproc/src/phasecorr.cpp

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -372,37 +372,57 @@ static void fftShift(InputOutputArray _out)
372372

373373
if(is_1d)
374374
{
375+
int is_odd = (xMid > 0 && out.cols % 2 == 1) || (yMid > 0 && out.rows % 2 == 1);
375376
xMid = xMid + yMid;
376377

377378
for(size_t i = 0; i < planes.size(); i++)
378379
{
379380
Mat tmp;
380-
Mat half0(planes[i], Rect(0, 0, xMid, 1));
381-
Mat half1(planes[i], Rect(xMid, 0, xMid, 1));
381+
Mat half0(planes[i], Rect(0, 0, xMid + is_odd, 1));
382+
Mat half1(planes[i], Rect(xMid + is_odd, 0, xMid, 1));
382383

383384
half0.copyTo(tmp);
384-
half1.copyTo(half0);
385-
tmp.copyTo(half1);
385+
half1.copyTo(planes[i](Rect(0, 0, xMid, 1)));
386+
tmp.copyTo(planes[i](Rect(xMid, 0, xMid + is_odd, 1)));
386387
}
387388
}
388389
else
389390
{
391+
int isXodd = out.cols % 2 == 1;
392+
int isYodd = out.rows % 2 == 1;
390393
for(size_t i = 0; i < planes.size(); i++)
391394
{
392395
// perform quadrant swaps...
393-
Mat tmp;
394-
Mat q0(planes[i], Rect(0, 0, xMid, yMid));
395-
Mat q1(planes[i], Rect(xMid, 0, xMid, yMid));
396-
Mat q2(planes[i], Rect(0, yMid, xMid, yMid));
397-
Mat q3(planes[i], Rect(xMid, yMid, xMid, yMid));
398-
399-
q0.copyTo(tmp);
400-
q3.copyTo(q0);
401-
tmp.copyTo(q3);
402-
403-
q1.copyTo(tmp);
404-
q2.copyTo(q1);
405-
tmp.copyTo(q2);
396+
Mat q0(planes[i], Rect(0, 0, xMid + isXodd, yMid + isYodd));
397+
Mat q1(planes[i], Rect(xMid + isXodd, 0, xMid, yMid + isYodd));
398+
Mat q2(planes[i], Rect(0, yMid + isYodd, xMid + isXodd, yMid));
399+
Mat q3(planes[i], Rect(xMid + isXodd, yMid + isYodd, xMid, yMid));
400+
401+
if(!(isXodd || isYodd))
402+
{
403+
Mat tmp;
404+
q0.copyTo(tmp);
405+
q3.copyTo(q0);
406+
tmp.copyTo(q3);
407+
408+
q1.copyTo(tmp);
409+
q2.copyTo(q1);
410+
tmp.copyTo(q2);
411+
}
412+
else
413+
{
414+
Mat tmp0, tmp1, tmp2 ,tmp3;
415+
q0.copyTo(tmp0);
416+
q1.copyTo(tmp1);
417+
q2.copyTo(tmp2);
418+
q3.copyTo(tmp3);
419+
420+
tmp0.copyTo(planes[i](Rect(xMid, yMid, xMid + isXodd, yMid + isYodd)));
421+
tmp3.copyTo(planes[i](Rect(0, 0, xMid, yMid)));
422+
423+
tmp1.copyTo(planes[i](Rect(0, yMid, xMid, yMid + isYodd)));
424+
tmp2.copyTo(planes[i](Rect(xMid, 0, xMid + isXodd, yMid)));
425+
}
406426
}
407427
}
408428

modules/imgproc/test/test_pc.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,50 @@ void CV_PhaseCorrelatorTest::run( int )
7878
Point2d phaseShift = phaseCorrelate(r1, r2, hann);
7979

8080
// test accuracy should be less than 1 pixel...
81-
if((expectedShiftX - phaseShift.x) >= 1 || (expectedShiftY - phaseShift.y) >= 1)
81+
if(std::abs(expectedShiftX - phaseShift.x) >= 1 || std::abs(expectedShiftY - phaseShift.y) >= 1)
8282
{
8383
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
8484
}
8585
}
8686

8787
TEST(Imgproc_PhaseCorrelatorTest, accuracy) { CV_PhaseCorrelatorTest test; test.safe_run(); }
8888

89+
TEST(Imgproc_PhaseCorrelatorTest, accuracy_real_img)
90+
{
91+
Mat img = imread(cvtest::TS::ptr()->get_data_path() + "shared/airplane.png", IMREAD_GRAYSCALE);
92+
img.convertTo(img, CV_64FC1);
93+
94+
const int xLen = 129;
95+
const int yLen = 129;
96+
const int xShift = 40;
97+
const int yShift = 14;
98+
99+
Mat roi1 = img(Rect(xShift, yShift, xLen, yLen));
100+
Mat roi2 = img(Rect(0, 0, xLen, yLen));
101+
102+
Mat hann;
103+
createHanningWindow(hann, roi1.size(), CV_64F);
104+
Point2d phaseShift = phaseCorrelate(roi1, roi2, hann);
105+
106+
ASSERT_NEAR(phaseShift.x, (double)xShift, 1.);
107+
ASSERT_NEAR(phaseShift.y, (double)yShift, 1.);
108+
}
109+
110+
TEST(Imgproc_PhaseCorrelatorTest, accuracy_1d_odd_fft) {
111+
Mat r1 = Mat::ones(Size(129, 1), CV_64F)*255; // 129 will be completed to 135 before FFT
112+
Mat r2 = Mat::ones(Size(129, 1), CV_64F)*255;
113+
114+
const int xShift = 10;
115+
116+
for(int i = 6; i < 20; i++)
117+
{
118+
r1.at<double>(i) = 1;
119+
r2.at<double>(i + xShift) = 1;
120+
}
121+
122+
Point2d phaseShift = phaseCorrelate(r1, r2);
123+
124+
ASSERT_NEAR(phaseShift.x, (double)xShift, 1.);
125+
}
126+
89127
}

0 commit comments

Comments
 (0)