File Exchange

image thumbnail

Efficient subpixel image registration by cross-correlation

version 1.1 (182 KB) by

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

39 Ratings



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.

Comments and Ratings (61)

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

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.


wei ying


Jiali (view profile)

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

hui cheng


arnold (view profile)

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?


chen (view profile)



chen (view profile)


Tom (view profile)

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

Rob Campbell (view profile)

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


Denis (view profile)

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

Ahmed Fasih


Jony (view profile)


Daniel (view profile)

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


Greg (view profile)

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


Greg (view profile)


Rui (view profile)

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

thanks manuel!


Rui (view profile)


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

Yan G (view profile)

Nafise b

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

Sean de

Sean de (view profile)

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

Sean de (view profile)

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 ?


Alex (view profile)

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.



Phillip (view profile)

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


Alex (view profile)

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

Rob Campbell (view profile)

Wonderful. Fast and accurate.


Sean (view profile)

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

Thank you!

Raymond Cheng

Thanks for your sharing.

su su

su su (view profile)

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


Eric (view profile)

Tremendously useful! Thanks very much.

Works right out of the box. Thanks for sharing !

Tobias Henn

Great Work - fast and accurate!!!

Manuel Guizar

Manuel Guizar (view profile)

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

Manuel Guizar (view profile)

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.


Chaos (view profile)

 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?


Chaos (view profile)

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?


Chaos (view profile)

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?


Petter (view profile)

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.



Small update


Revise license text


Rewrote portions of the code for improved consistency and better readability, added BSD license.

MATLAB Release
MATLAB 8.5 (R2015a)

Download apps, toolboxes, and other File Exchange content using Add-On Explorer in MATLAB.

» Watch video