0

I have two dicom images and can compute the mean squared error of the images using the code below. However, there can be an inherent shift in one image compared to another (if my imager is slightly misaligned). Is there an easy way to compute a shift of two numpy arrays?

I have tried shifting the array by a few pixels each direction and computing the minimum MSQ. However, this is not robust enough. Any help or advice would be very much appreciated!

import numpy as np
import dicom

#first image
ds = dicom.read_file("U:\\temp\\1.dcm")
array1 = ds.pixel_array
#second image
ds1 = dicom.read_file("U:\\temp\\5.dcm")
array2 = ds1.pixel_array

#shifting image by a number of pixels in any direction
arr1 = np.roll(array2, 100,  axis=1)
imshow(arr1)

def mse(imageA, imageB):
    # the 'Mean Squared Error' between the two images is the
    # sum of the squared difference between the two images;
    err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2)
    err /= float(imageA.shape[0] * imageA.shape[1])

    # return the MSE, the lower the error, the more "similar"
    # the two images are
    return err

first_try = mse(array1, array2)
second_try = mse(arr1, array2)
ali_m
  • 71,714
  • 23
  • 223
  • 298
Ciaran
  • 478
  • 1
  • 8
  • 23
  • If the 'shift' is always a translation, [phase correlation](http://en.wikipedia.org/wiki/Phase_correlation) often works quite well, and has the advantage that it's quite robust to noise and variation in luminance between images – ali_m Apr 21 '15 at 12:37

2 Answers2

2

If you are sure that the images will be exactly identical except for this shift, think the best solution is scipy.signal.correlate2d:

import numpy as np
from scipy.signal import correlate2d

a = np.random.random((200, 200))
b = np.roll(np.roll(a, 15, axis=0),-33, axis=1)

corr = correlate2d(a, b)

shift = np.where(corr==corr.max())
shift = (shift[0]%a.shape[0], shift[1]%a.shape[1])

This gives the correct values:

(array([184]), array([32]))
Saullo G. P. Castro
  • 56,802
  • 26
  • 179
  • 234
TheBlackCat
  • 9,791
  • 3
  • 24
  • 31
  • 1
    Standard cross-correlation tends to be rather sensitive to variations in the brightness and contrast of the template and reference images. For realistic images it's often necessary to [normalize](http://en.wikipedia.org/wiki/Cross-correlation#Normalized_cross-correlation) by subtracting the mean and dividing by the standard deviation under the region of overlap. – ali_m Apr 21 '15 at 12:44
  • @ali_m Yes, that is why I said "If you are sure that the images will be exactly identical except for this shift". – TheBlackCat Apr 21 '15 at 14:14
  • 1
    Sure - I only meant to suggest a way to deal with the more common case where they are not identical – ali_m Apr 21 '15 at 14:24
1

It's hard to say without seeing the images, and what works on one image may not work on the next. However in general try:

  • Multi-scale estimation - downsample your arrays, compute the shift at the coarse scale and initialize with this shift (compensating for the scaling) at the next scale.
  • A robust error score like sum of absolute differences.
YXD
  • 31,741
  • 15
  • 75
  • 115