Asked by Joe
on 11 Oct 2013

I've been trying everything I can find, but I can't seem to come up with a code that aligns my images very well. I have been using the pressure taps on the image to align the images manually, so using those again would be great. I've gotten to within a few pixels, but I need it to be with at least pixel accuracy, ideally subpixel accuracy. Here's an example of one of the codes that seems to do semi well.

img1 = 255-mean(imread('01_wing.png'),3);

img2 = 255-mean(imread('02_wing.png'),3);

c = normxcorr2(img2,img1);

[y x] = find(c==max(c(:)));

y = y-size(img2,1);

x = x-size(img2,2);

TFORM = maketform('affine',[1 0 x;0 1 y; 0 0 1]');

NEWimg2 = imtransform(img2,TFORM,'xdata',[1 size(img1,2)],'ydata',[1 size(img1,1)]);

I've attached the wing images in a zip file. The image below is an example of the pressure taps not aligning correctly.

What should I do differently?

Answer by Matt J
on 15 Oct 2013

Edited by Matt J
on 15 Oct 2013

Accepted Answer

If you can extract the coordinates of the pressure taps in each image e.g., using regionprops(...,'WeightedCentroid'), then you could try using

to find the transformation that aligns them.

Even better would be if you already knew the 2D coordinates of the pressure taps with high accuracy in some prior template image. Then you could register both '01_wing.png' and '02_wing.png' to that.

Matt J
on 15 Oct 2013

Notice also that it is not necessary to measure the coordinates of the taps with sub-pixel accuracy in order to obtain sub-pixel alignment. Below for example is a simulation in which the 80 coordinates in B contain errors of more than 3 pixels, but the alignment is accurate to 0.82 pixels.

Atrue(2,1:80)=1:80; %coordinates image 1

A=Atrue+rand(size(Atrue));

Btrue(2,1:80)=(1:80)-5; %coordinates image 2

B= Btrue+randn(size(Btrue));

[~,Bfit]=absor(A,B); %register A to B

err=@(a,b) max(sqrt(dot(a-b,a-b))); %max error function

And then at the command line

>> err(B,Btrue) %measurement error

ans =

3.1219

>> err(Bfit,Btrue) %alignment error

ans =

0.8152

Matt J
on 15 Oct 2013

My reason for wanting to use the corner() function is mainly because I have been having problems turning my image into a binary image.

Don't understand why. The pressure taps in your posted image appear to have very distinct intensities from the background. I'd imagine a simple thresholding operation would give you your binary image.

Joe
on 25 Oct 2013

Sign in to comment.

Answer by Image Analyst
on 11 Oct 2013

Why not use imregister()? It's in the Image Processing Toolbox.

Image Analyst
on 15 Oct 2013

Joe
on 15 Oct 2013

Matt J
on 15 Oct 2013

I can imagine imregister() having difficulty if the pressure taps in image A do not have any initial overlap with the taps in image B. The initial gradient of the registration metric will be zero in that case and the algorithm won't be able to move.

With normxcorr2, you would hopefully be able to obtain that initial overlap, but since the taps are so small, it is unclear.

Sign in to comment.

Answer by Eric
on 15 Oct 2013

Here's what works well for me:

1. Get dftregistration.m from www.mathworks.com/matlabcentral/fileexchange/18401-efficient-subpixel-image-registration-by-cross-correlation

2. Register the gradients of the images, not the images themselves.

Here's my code:

%Load data

im1Orig = double(imread('01_wing.png'));

im2Orig = double(imread('02_wing.png'));

%Calculate gradients

im1 = imgradient(im1Orig);

im2 = imgradient(im2Orig);

%Get registration values

[output, Greg] = dftregistration(fft2(im1),fft2(im2),50);

%Translate image

imOut = TranslateImage(im2, output(3), output(4),'method','Fourier');

I get a row shift of -0.36 pixels and a column shift of +3.06 pixels. My function TranslateImage is basically:

img_out = TranslateImage(img_in, rowshift, colshift)

%%Create frequency space sampling vectors

[numrows, numcols] = size(img_in);

[n,m] = meshgrid(-fix(numcols/2):fix((numcols-1)/2),-fix(numrows/2):fix((numrows-1)/2));

m = m/numrows;

n = n/numcols;

%%Perform translation in the Fourier domain

img_fft = fftshift(fft2(ifftshift(double(img_in))));%Cast the input image to a double

shiftOtf = exp(-1i*2*pi*m*rowshift) .* exp(-1i*2*pi*n*colshift);

img_fft_trans = img_fft .* shiftOtf;

img_out = real(fftshift(ifft2(ifftshift(img_fft_trans))));

return

end

For monomodal image registration with pure translation, there are many algorithms that work better than imregister().

Good luck,

Eric

Opportunities for recent engineering grads.

Apply Today
## 1 Comment

## Joe (view profile)

## Direct link to this comment

https://www.mathworks.com/matlabcentral/answers/89960-image-alignment-code-in-matlab#comment_176448

Sign in to comment.