File Exchange

image thumbnail

Efficient subpixel image registration by cross-correlation

version (182 KB) by Manuel Guizar
Registers two images (2-D rigid translation) within a fraction of a pixel specified by the user.


Updated 16 Jun 2016

View Version History

View License

Registers two images (2-D rigid translation) within a fraction of a pixel specified by the user. Instead of computing a zero-padded FFT (fast Fourier transform), this code uses selective upsampling by a matrix-multiply DFT (discrete FT) to dramatically reduce computation time and memory without sacrificing accuracy. With this procedure all the image points are used to compute the upsampled cross-correlation in a very small neighborhood around its peak. This algorithm is referred to as the single-step DFT algorithm in [1].
[1] Manuel Guizar-Sicairos, Samuel T. Thurman, and James R. Fienup, "Efficient subpixel image registration algorithms," Opt. Lett. 33, 156-158 (2008).
Please refer to the attached HTML for more details and a sample implementation.

Cite As

Manuel Guizar (2021). Efficient subpixel image registration by cross-correlation (, MATLAB Central File Exchange. Retrieved .

Comments and Ratings (83)

Yingchen Li

Rui Ma

sina jazani

brown alexander

Akshat Karambe


This script works great but when I run the similar code in python (link_to_python_equivalent: i get different results. On digging deep i figured that the values of "output" and "greg" variables in Matlab code and python code differs. Is there anyone who encountered the same issue? Any help will be appreciated.

Thank you




Super code et est-ce possible de récupérer la matrice des pixels de l'image Greg pour les enregistrer et faire la moyenne de toutes les images Greg?

Lars Loetgering

Haon Zhang

Great code and very helpful!

Bryan Schulz

Mohamed Eldib male

Komail Mehrgan


Aaron Blanchard

Great code, I use it for all of my microparticle tracking needs and I'll definitely be citing in an upcoming paper :)

One very simple change I made that gave me a 10-20% increase in speed was changing line 115:

CCabs = abs(CC);

to the equivalent but slightly faster:

CCabs = sqrt(real(CC).^2 + imag(CC).^2);

not sure exactly why this speeds things up but any user should definitely consider this change.

Rob Campbell

imregister in the Image Processing Toolbox will do it. Or there are alternatives like Nifty or Elastix. The latter I made a really simple wrapper for:

N R Anthony

Hi Manuel. Thanks for this great function; works really well.

I was wondering if you could help me understand where it might be changed to work for 3D arrays? If you can point me in the right direction I'll give it a go, or if it's easy for you could you create a 3D version?

Thanks in advance for your time.


Matlabber 1.0


great piece of work

Fabian Schlieper


songsheng He

Tiago Ramos

Kathryn Tabor

Great code! Is there a way to use the output from the registration of one image to a reference image to transform a second image with the same algorithm? Thanks!

Anna Golos

Suresh Manchikanti

Working good for only translational error images. But is it possible to extend to cover angular rotations and scale shifts as well? (e.g. Fourier Mellin transform) as commented earlier by Philip. Any update in this code?

Yuyang Wang

Ehren M.




Does this algorithm only work for translation? How about image rotation?

hui cheng


is there a way to limit the rotation angle?
I want to use to to rotate square images to a shape template (a binary frame). It then randomly rotates the images n*89° instead of -1°, which would be the closest.

I'm clueless at this point how to implement that, does anyone have an idea?

Song Ming


Sung Soo Kim



Tom Wright

This is great. I made a few minor modifications to limit translation to only the x or y axis. Do you have this under version control anywhere?





Simply fantastic. So much more efficient and accurate for 2D translation than everything else I tried. The subpixel resolution is a bonus as well.

Rob Campbell

It would be really useful if the code could do rotation as well.


Is this only for shifts? can we register rotation as well?

Ahmed Fasih



wow, that one is really fast and seems to be robust. thanks a lot!


Great algorithm, it has helped so much with my image stabilization project



works very well. i'm amazed with the speed and accuracy of the algorithm.

thanks manuel!



do images need to be square - as in 2^n for the fft shift to work properly?

Aron Sceidt

can this be applied to colour images in some way?

Yan G

Nafise b

ThX, I did it, hopefully some one answer me.

Sean de

Nafise, post your situation/goals, your images, and what you've tried to the newsgroup ( From there people can help you.

Nafise b

ThX sean,
I did it, but it is not true, because my image has black regions, and it determines that part with zero pad part.

Sean de

Nafise b, pad your smaller image with zeros so that it is the same size.

Nafise b

Thanks for your code.
I want to work with your code, but I have a problem with it.
In fact, my images are 2 blocks which don't have the same size, and I want to find the best place for small block in the big block.
Something that I got from your code is for your code 2 images have same size.
What should I do now, if I want to use your code for subpixel image registration?

Best regards,

Yu Yinghuai

Great work! Question about the codes " kernr=exp((-i*2*pi/(nr*usfac))*( [0:nor-1].' - roff )*( ifftshift([0:nr-1]) - floor(nr/2) )) " :
Why does the vector [0:nr-1] need be ifftshift ?


Re: my comment on 14 Jul 2010:
I owe an apology. It seems at the point when I wrote my comment I was feeding an accidentally reshaped array into the code. Because of the artifacts in my data, it caused a wrap around artifact in the output (and the registration worked in one axis only, but I didn't notice because that happened to be the axis containing almost all of the shifts).

Great code - no resrvations! Thanks much.



Great code. Any plans to extend to cover angular rotations and scale shifts as well? (e.g. Fourier Mellin transform)


Code registers images very well. Question about the supplementary output:
output = [error,diffphase,net_row_shift,net_col_shift]

On my data it seems that some times the row_shift variable seems to 'wrap around' in away that is not intuitive. For example though the data is only 512 pixels wide, I get row shifts of -512.3, 1024.3 etc which I assume are actually very small pixel shifts that have a somewhat random multiple of the image size thown on for fun.

Rob Campbell

Wonderful. Fast and accurate.


Is there a way to extend this to 3D CT images?

Thank you!

Raymond Cheng

Thanks for your sharing.

su su

I want to register the pair of visible and theraml images with this one, but I don't get the required resutl.


Tremendously useful! Thanks very much.

Lucas Koorneef

Works right out of the box. Thanks for sharing !

Tobias Henn

Great Work - fast and accurate!!!

Manuel Guizar

This method is equally robust to noise as the standard FFT upsampling, but much faster. It computes the same upsampled cross correlation but only in a small neighborhood around the peak.

Manuel Guizar

Thanks to everyone for the positive comments! The published M-file is intended to get the user started with the syntax and explain what the code does. For technical documentation please refer to the reference above [1] and references within.


forgot to rate. wow this code is brutally fast and accurate, if you define a ROI even faster. this code needs some kind of award. how much faster would it be if it was compiled in to a mex?


works but i had to re=write code for UINT16 images, very fast and accurate. why are you using double? do you really need that accuracy in the dft?


works but i had to re=write code for UINT16 images, very fast and accurate.

Robert Reed

Is this method less robust to noise than standard upsampling?


Always nice to see a published .m, but the images tell us nothing. A zoomed in display, abs error or something would be more relevant than two identially looking images.

Robert Reed

Elegant solution in simple understandable code + sound documentation.

Zhi Zhang

Excellent Work!

Jiang Jun

Thank you for you job, I will enjoy it.

Matt Sochor

Very good and excellent documentation to get you started with the syntax. Great job and thanks for including the paper reference.

Chris Cookson

did i mention it was easy to use?

Chris Cookson

easy to use, extremely fast, and easy to use. amazing work.

MATLAB Release Compatibility
Created with R2015a
Compatible with any release
Platform Compatibility
Windows macOS Linux

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!