How to perform image cross-correlation with subpixel accuracy with scipy
Asked Answered
D

2

5

The image below shows two circles of same radius, rendered with antialiasing, only that the left circle is shifted half pixel horizontally (notice that the circle horizontal center is at the middle of a pixel at the left, and at the pixel border at the right).

If I perform a cross-correlation, I can take the position of the maximum on the correlation array, and then calculate the shift. But since pixel positions are always integers, my question is:

"How can I obtain a sub-pixel (floating point) offset between two images using cross-correlation in Numpy/Scipy?"

In my scripts, am using either of scipy.signal.correlate2d or scipy.ndimage.filters.correlate, and they seem to produce identical results.

The circles here are just examples, but my domain-specific features tend to have sub-pixel shifts, and currently getting only integer shifts is giving results that are not so good...

Any help will be much appreciated!

enter image description here

Danelledanete answered 5/12, 2012 at 19:28 Comment(1)
Should this question be moved to Signal Processing? (dsp.stackexchange)Danelledanete
S
4

The discrete cross-correlation (implemented by those) can only have a single pixel precision. The only solution I can see is to interpolate your 2D arrays to a finer grid (up-sampling).

Here's some discussion on DSP about upsampling before cross-correlation.

Simonnesimonpure answered 5/12, 2012 at 23:8 Comment(3)
I found the accepted answer to the linked question very enlightening. I think I will interpolate (upsample) a sub-array (around the peak) of the correlation result. Thanks!Danelledanete
You mention "discrete cross correlation", but are you aware of any "non-discrete cross-correlation" that could be applied over (discrete) 2D arrays?Danelledanete
@heltonbiker, no I don't. But I'm not an expert on signal processing.Simonnesimonpure
M
4

I had a very similar issue, also with shifted circles, and stumbled upon a great Python package called 'image registration' by Adam Ginsburg. It gives you sub-pixel 2D images shifts and is fairly fast. I believe it's a Python implementation of a popular MATLAB module, which only upsamples images around the peak of the x-correlation.

Check it out: https://github.com/keflavich/image_registration

I've been using 'chi2_shifts.py' with good results.

Merritt answered 28/1, 2015 at 11:17 Comment(1)
Thanks for your answer! The code dealing with this problem is now off development, but it's good to know about an "off-the-shelf" library, in case I need to tinker with it again in the future!Danelledanete

© 2022 - 2024 — McMap. All rights reserved.