Harmonic Notes on MATLAB and Image Processing

Concepts, examples, new code, tutorials, tips, stories, history, etc.

« Making a Simple...

Improved Registration Algorithm for IMREGCORR

Steve Eddins
October 16, 2025

Contents

image_0.jpeg

Introduction

My last significant development project before retiring from MathWorks was to improve the algorithm for imregcorr, which is used to register images based on translation, rigid, or similarity transformation types. This enhancement shipped with Image Processing Toolbox in R2024b, and I want to tell you about it. If you have ever used imregcorr before and gotten unsatisfying results, then you should definitely try it again in R2024b or later.

I will demonstrate the improvements using several image registration questions that I found on MATLAB Answers. When you see filenames in the code below, those files were originally uploaded in the MATLAB Answers post. You can find them there if you want to reproduce these examples yourselves.

I’ll start with one example, then I’ll talk about the algorithm changes, and finally I’ll show more examples.

Example: Star-Field Image Alignment

Nathan posted on 03-Jul-2024 that imregcorr failed to align these two star-field images.

load srcimg SourceImageAdj
load srcref.mat SourceRef
load targetim.mat TargetImageAdj6
load tgtref.mat TargetRef

tiledlayout(1,2)
nexttile
imshow(SourceImageAdj)
title("SourceImageAdj")
nexttile
imshow(TargetImageAdj6)
title("TargetImageAdj6")

figure_0.png

The registration result using imregcorr in R2024a is poor. In this visualization, created using imshowpair, misregistered objects show up in color. As you can see, everything is in color.

image_1.jpeg

In R2024b and later, the output of imregcorr is much better.

tform = imregcorr(SourceImageAdj, SourceRef, ...
    TargetImageAdj6, TargetRef, ...
    TransformType = "similarity")
tform = 
  simtform2d with properties:

    Dimensionality: 2
             Scale: 0.9981
     RotationAngle: -1.0487
       Translation: [0.0617 -0.0056]
                 R: [2x2 double]

                 A: [ 0.9979    0.0183    0.0617
                     -0.0183    0.9979   -0.0056
                           0         0    1.0000]

Nathan said that he expected the scale to be $1$, the rotation angle to be $-1$, and the translation to be $(0.0640,0)$. You can see from the display of tform above that the output from imregcorr is very close to the expected values.

Visualize the results using imshowpair:

registered_image = imwarp(SourceImageAdj, SourceRef, tform, "linear", ...
    OutputView = TargetRef);
figure
imshowpair(TargetImageAdj6, TargetRef, registered_image, TargetRef)

figure_1.png

New Algorithm: Normalized Gradient Correlation

In R2024a and earlier, imregcorr was based on Reddy, B. S. and Chatterji, B. N. “An FFT-Based Technique for Translation, Rotation, and Scale-Invariant Image Registration,” IEEE Transactions on Image Processing, Vol. 5, No. 8, August 1996. Roughly speaking, this method looks for the peak in the correlation of the log-polar frequency-domain phases of the two images to estimate the scale and rotation from one image to the other. In many cases, this method fails because there is not a single, well-defined peak at an easily estimated location. With the star-field image pair above, for example, the matrix of correlation values looks like this:

image_2.jpeg

Starting in R2024b, imregcorr uses a technique called normalized gradient correlation (NGC), mostly as described in Tzimiropoulos, Argyriou, Zafeiriou, and Stathaki. “Robust FFT-Based Scale-Invariant Image Registration with Image Gradients,” IEEE Transactions on Pattern Analysis and Machine Intelligence 32, no. 10 (October 2010): 1899–1906, https://doi.org/10.1109/TPAMI.2010.107.

This method directly incorporates gradient information by forming a complex gradient image from each input image:

$$ G(\mathbf{x})=G_x (\mathbf{x})+jG_y (\mathbf{x}) $$

where $G_x (\mathbf{x})$ is the horizontal gradient of the input image, and $G_y (\mathbf{x})$ is the vertical gradient.

The paper argues that this form of correlation weights edge pixels more strongly, suppresses contributions from slowly-varying image regions, and produces a sharp peak even when the images contain dissimilar regions, as is often the case in practice. Here is the matrix of normalized gradient correlation values from the star-field image pair above, displayed as an image. The narrow peak is barely visible. The second image shows a zoomed-in view of the peak.

image_3.jpeg image_4.jpeg

Assessing the New IMREGCORR Algorithm

Changing the output of an existing function in a MathWorks product is risky. Such changes could cause compatibility issues in user code, so they must be very well motivated and thoroughly tested. We were considering such a change, despite the risk, because we had evidence that many users have been unsuccessful trying to apply imregcorr to their data.

To assess the new imregcorr algorithm, I gathered a test suite of 163 images, chosen from a variety of sources and containing a variety of content. Here are thumbnails of the test suite images.

image_5.jpeg

I then ran these images through about a dozen different experiments, covering the similarity, rigid, and translation transformation types, with a range of parameters, as well as speed and memory comparisons. I think there may have been somewhere around 10,000 image registration pairs tested in all.

From the test results, I concluded that the new algorithm’s output was significantly more accurate and precise than the old algorithm in roughly 95% of test cases. The two algorithms produced comparable results in about 4% of test cases. In a very small number of cases, the old algorithm produced a better result than the new one, according to the error metric I was using. However, in almost all of those cases, both algorithms had essentially failed to find a usable registration result.

I also observed that the new algorithm could produce a usable registration result with much less overlap between the two input images. Also, it was mostly faster (but not always), and it used less memory most of the time (but not always).

I put all this data in front of the Image Processing Toolbox team, and everyone agreed with the plan to change the underlying algorithm for imregcorr.

Additional Examples from MATLAB Answers

Registering a High Resolution Image with a Blurry Image

Jeff asked on 07-Dec-2020 for help with registering images having different sizes and resolutions. They were taken with different devices. Here’s what the originals look like.

moving = imread("Smp180_VIS_1.png");
fixed = imread("Smp180_VIS_ref.png");
imshowpair(fixed, moving, "montage")

figure_2.png

When you use imregcorr to register these two images in R2024a or earlier, you get a warning message:

Warning: Phase correlation did not result in a strong peak. Resulting registration could be poor.

Indeed, the resulting registration computed in R2024a is poor.

image_6.jpeg

Here is what you get with the improved imregcorr in R2024b or later:

tform = imregcorr(moving, fixed)
tform = 
  simtform2d with properties:

    Dimensionality: 2
             Scale: 0.3675
     RotationAngle: 8.4500
       Translation: [87.4448 63.7681]
                 R: [2x2 double]

                 A: [0.3635   -0.0540   87.4448
                     0.0540    0.3635   63.7681
                          0         0    1.0000]

[moving_reg, moving_reg_ref] = imwarp(moving, imref2d(size(moving)), tform);
figure
imshowpair(moving_reg, moving_reg_ref, fixed, imref2d(size(fixed)))

figure_3.png

Registering a Rotated Camerman

Eirik posted on 28-Oct-2021 that imregcorr could not detect the correct rotation in a synthetically generated example using the cameraman image.

fixed_image = imread("cameraman.tif");
moving_image = imrotate(fixed_image, 125);
tiledlayout(1,2)
nexttile
imshow(fixed_image), title("fixed image")
nexttile
imshow(moving_image), title("moving image")

figure_4.png

In R2024a and earlier, imregcorr estimates a rotation angle of about 17 degrees, obviously very far off. In R2024a and later, the function produces a good result.

tform = imregcorr(moving_image, fixed_image)
tform = 
  simtform2d with properties:

    Dimensionality: 2
             Scale: 1.0001
     RotationAngle: 124.9967
       Translation: [377.8203 84.5295]
                 R: [2x2 double]

                 A: [-0.5736   -0.8193  377.8203
                      0.8193   -0.5736   84.5295
                           0         0    1.0000]

[moving_image_reg,moving_reg_ref] = imwarp(moving_image, imref2d(size(moving_image)), tform);
clf
imshowpair(fixed_image,imref2d(size(fixed_image)),moving_image_reg,moving_reg_ref)

figure_5.png

Simple Patterns

MATLAB user cr posted on 19-Aug-2020 that they had trouble getting a good registration on images with simple patterns using feature-based methods in Computer Vision Toolbox. The new version of imregcorr handles the given example correctly.

A2 = imread("A2.png");
A0 = imread("A0.png");
tiledlayout(1,2)
nexttile
imshow(A2), title("A2")
nexttile
imshow(A0), title("A0")

figure_6.png

tform = imregcorr(A2,A0)
tform = 
  simtform2d with properties:

    Dimensionality: 2
             Scale: 1.0000
     RotationAngle: -32.5015
       Translation: [317.9212 1.4153e+03]
                 R: [2x2 double]

                 A: [1.0e+03 *
                      0.0008    0.0005    0.3179
                     -0.0005    0.0008    1.4153
                           0         0    0.0010]

[A2_reg,A2_reg_ref] = imwarp(A2,tform);
figure
imshowpair(A2_reg, A2_reg_ref, A0, imref2d(size(A0)))

figure_7.png