I'm using OpenCV to detect shift between 2 images, here is sample code (based on cv::phaseCorrelate function):
cv::Mat ShiftTransform(const cv::Mat &source, const cv::Mat &target, bool bUseHanningWindow)
{
CV_Assert(source.type() == CV_32FC1);
CV_Assert(target.type() == CV_32FC1);
Point2d shift;
if(bUseHanningWindow)
{
Mat hann;
createHanningWindow(hann, source.size(), CV_32F);
shift= phaseCorrelate(source, target, hann);
}
else
{
shift= phaseCorrelate(source, target);
}
cout << "Detected shift: " << shift << endl;
Mat H = (Mat_<float>(2, 3) << 1.0, 0.0, shift.x, 0.0, 1.0, shift.y);
Mat res;
warpAffine(source, res, H, target.size());
CV_Assert(res.size() == target.size());
CV_Assert(res.type() == CV_32FC1);
return res;
}
For example images from wikipedia seems it works.
source
target
result
response map
But for some real life images it gives wrong shift, maybe because of this problems described in wikipedia:
In practice, it is more likely that $g_{b}$ will be a simple linear shift of $g_{a}$ , rather than a circular shift as required by the explanation above. In such cases, $r$ will not be a simple delta function, which will reduce the performance of the method. In such cases, a window function (such as a Gaussian or Tukey window) should be employed during the Fourier transform to reduce edge effects, or the images should be zero padded so that the edge effects can be ignored. If the images consist of a flat background, with all detail situated away from the edges, then a linear shift will be equivalent to a circular shift, and the above derivation will hold exactly. The peak can be sharpened by using edge or vector correlation.
For periodic images (such as a chessboard), phase correlation may yield ambiguous results with several peaks in the resulting output.
But I'm not sure how to debug such cases if something goes wrong.
Here is suggested not to blur images.
What are other practical advices for applying phase correlation in image registration task?