tags:

views:

521

answers:

2

I have two images I'm trying to co-register - ie, one could be of a ball in the centre of the picture, the other is of the same ball near the edge and I'm trying to find the numbed of pixels I have to move the second image so that the balls would be in the same place. (I'm actually using 3D MRI brain scans, but the principle is the same).

I've written a function that will move the ball left, right, up or down by a given number of pixels as well as another function that compares the correlation of the ball-in-the-centre image with the translated ball-at-the-edge image. When the two balls are in the same place the correlation function will return 0 and a number larger than 0 for other positions.

I'm trying to use fminsearch (documentation) to find the optimal translation for the correlation function's minimum (ie, the balls being in the same place) like so:

global reference_im unknown_im;

starting_trans = [0 0 0];
trans_vector = fminsearch(@correlate_images,starting_trans)

correlate_images.m:

function r = correlate_images(translate)
global reference_im unknown_im;

new_im = move_image(unknown_im,translate(1),translate(2),translate(3));

% This bit is unimportant to the question
% but you can see how I calculate my correlation
r = 1 - corr(reshape(new_im,[],1),reshape(reference_im,[],1));

There are two problems, firstly fminsearch insists on passing float values for the translation vector into the correlate_images function. Is there any way to inform it that only integers are necessary? (I would save a large number of cpu cycles!)

Secondly, when I run this program the resulting trans_vector is always the same as starting_trans - I assume this is because no minimum has been found, but is there another reason its just plain not working?

Many thanks!

EDIT

I've discovered what I think is the reason the output trans_vector is always the same as starting_trans. The fminsearch looks at the starting value, then a small increment in each direction from there, this small increment is always less than one, which means that the result from the correlation will be a perfect match (as the move_image will return the same as the input image for sub-pixel movements). I'm going to continue working on convincing matlab to only fminsearch over integer values!

+1  A: 

First, I'd say that Matlab might not be the best tool for this problem. I'd look at Elastix, which is a pretty user-friendly wrapper around the registration functions in ITK. You get a variety of registration techniques, and the manuals for both programs do a good job of explaining the specifics of image registration.

Second, for this kind of simple translational registration, you can use the FFT. Forward transform both images, multiply the images together (pointwise! That is, use A .* B, not A * B, as those are different operations, and the first is what you want), and there should be a peak in the inverse transform whose offset from the origin is the translational amount you need. Numerical Recipes in C has a good explanation; here's a link to an index pdf. The speed difference between the FFT version and the direct correlation version is huge; the FFT is O(N log N), while the correlation method will be O (N * M), where M is the number of pixels in your search neighborhood. If you want to allow the entire image to be searched, then correlation becomes O (N*N), which will take much longer than the FFT version. Changing parameters from floats to integers won't solve the problem.

The reason the fminsearch function uses floats (if I can guess at the reasons behind the coders' decisions) is that for problems that aren't test problems (ie, spheres in a volume), you often need sub-pixel resolution to perform a correct registration. Take a look at the ITK documentation about the reasons behind this approach.

Third, I'd suggest that a good way to write this program in Matlab (if you still want to do so!) while still forcing integer correlations would be to avoid the fminsearch function, which will want to use floats. Try something like:

startXPos = -10; %these parameters dictate the size of your search neighborhood
startYPos = -10; %corresponds to M in the above explanation
endXPos = 10;
endYPos = 10;
optimalX = 0;
optimalY = 0;
maxCorrVal = 0;
for i=startXPos:endXPos
   for j = startYPos:endYPos
      %test the correlation of the two images here, where one image is shifted to another
      currCorrVal = Correlate(image1, image2OffsetByiAndj);
      if (currCorrVal > maxCorrVal)
          maxCorrVal = currCorrVal;
          optimalX = i;
          optimalY = j;
      end
   end
end

From here, you just have to write the offset function. This way, you avoid the float problem, and you're also incrementing your translation vector (I don't see any way for that vector to move in your provided functions, which probably explains your lack of movement).

mmr
Here is a good introduction to FFT (also 2D) with MATLAB: http://blogs.mathworks.com/steve/category/fourier-transforms/
Mikhail
Thank you very much indeed for your detailed response! Unfortunately MATLAB is the tool of choice here (this is part of one of my final year experiments as a Physics Masters student), but Elastix looks like it could be useful with the next project on this which is more open to us!...
JP
FFTs could be very useful - thanks! I'll have to investigate into how much the frequency domain changes between the rotated datasets...
JP
Unfortunately writing my own minimum search (like you've described above) would probably be inefficient, as I will be searching though all 6 degrees of freedom (3 translation and 3 rotation) - if I'm looking for pixel and half-degree accuracy up to 5 steps (lets say) then I'll need to make up to 10^6 tests! Although correlation in the Frequency Domain will speed them up, that could still take a while. (The translation vector is incremented inside `fminsearch` as part of the function)
JP
Well, 3 comments just about held all I wanted to say, thanks again
JP
As soon as you start looking at translation and rotation (sure you don't want to also do scale and shear?), you're going to need a very robust registration solution. I highly recommend checking out elastix, because it has that solution right out of the box-- I think it might even be their sample program. You can run shell scripts from matlab as well, if you need the registration to be part of a larger pipeline.
mmr
A: 

There is a very similar demo in the Image Processing Toolbox that uses the normalized cross-correlation function normxcorr2 to perform image registration. To avoid repeating the same thing, check out the demo directly:

Registering an Image Using Normalized Cross-Correlation

Amro
This should be really helpful, thanks! The only problem (as I mentioned to mmr above) is that I will (at some point) need to account for rotation as well as movement, and I'll need to do them both at the same time, so I can't use normxcorr2 out of the box. I will hunt around the image processing toolbox though, they probably have a decent function or two in there! Cheers
JP

related questions