image_registration.chi2_shifts.chi2_shift(im1, im2, err=None, upsample_factor='auto', boundary='wrap', nthreads=1, use_numpy_fft=False, zeromean=False, nfitted=2, verbose=False, return_error=True, return_chi2array=False, max_auto_size=512, max_nsig=1.1)[source] [edit on github]

Find the offsets between image 1 and image 2 using the DFT upsampling method ( combined with \(\chi^2\) to measure the errors on the fit

Equation 1 gives the \(\chi^2\) value as a function of shift, where Y is the model as a function of shift:

\[\chi^2(dx,dy) = \Sigma_{ij} \frac{(X_{ij}-Y_{ij}(dx,dy))^2}{\sigma_{ij}^2}\]

Equation 2-4: blahha

\begin{align} \mathrm{Term~1:} & f(dx,dy) & = & \Sigma_{ij} \frac{X_{ij}^2}{\sigma_{ij}^2} \\ & f(dx,dy) & = & f(0,0) , \forall dx,dy \\ \mathrm{Term~2:} & g(dx,dy) & = & -2 \Sigma_{ij} \frac{X_{ij}Y_{ij}(dx,dy)}{\sigma_{ij}^2} = -2 \Sigma_{ij} \left(\frac{X_{ij}}{\sigma_{ij}^2}\right) Y_{ij}(dx,dy) \\ \mathrm{Term~3:} & h(dx,dy) & = & \Sigma_{ij} \frac{Y_{ij}(dx,dy)^2}{\sigma_{ij}^2} = \Sigma_{ij} \left(\frac{1}{\sigma_{ij}^2}\right) Y^2_{ij}(dx,dy) \end{align}

The cross-correlation can be computed with fourier transforms, and is defined

\[CC_{m,n}(x,y) = \Sigma_{ij} x^*_{ij} y_{(n+i)(m+j)}\]

which can then be applied to our problem, noting that the cross-correlation has the same form as term 2 and 3 in \(\chi^2\) (term 1 is a constant, with no dependence on the shift)

\begin{align} \mathrm{Term~2:} & CC(X/\sigma^2,Y)[dx,dy] & = & \Sigma_{ij} \left(\frac{X_{ij}}{\sigma_{ij}^2}\right)^* Y_{ij}(dx,dy) \\ \mathrm{Term~3:} & CC(\sigma^{-2},Y^2)[dx,dy] & = & \Sigma_{ij} \left(\frac{1}{\sigma_{ij}^2}\right)^* Y^2_{ij}(dx,dy) \end{align}

Technically, only terms 2 and 3 has any effect on the resulting image, since term 1 is the same for all shifts, and the quantity of interest is \(\Delta \chi^2\) when determining the best-fit shift and error.


im1 : np.ndarray

im2 : np.ndarray

The images to register.

err : np.ndarray

Per-pixel error in image 2

boundary : ‘wrap’,’constant’,’reflect’,’nearest’

Option to pass to map_coordinates for determining what to do with shifts outside of the boundaries.

upsample_factor : int or ‘auto’

upsampling factor; governs accuracy of fit (1/usfac is best accuracy) (can be “automatically” determined based on chi^2 error)

return_error : bool

Returns the “fit error” (1-sigma in x and y) based on the delta-chi2 values

return_chi2_array : bool

Returns the x and y shifts and the chi2 as a function of those shifts in addition to other returned parameters. i.e., the last return from this function will be a tuple (x, y, chi2)

zeromean : bool

Subtract the mean from the images before cross-correlating? If no, you may get a 0,0 offset because the DC levels are strongly correlated.

verbose : bool

Print error message if upsampling factor is inadequate to measure errors

use_numpy_fft : bool

Force use numpy’s fft over fftw? (only matters if you have fftw installed)

nthreads : bool

Number of threads to use for fft (only matters if you have fftw installed)

nfitted : int

number of degrees of freedom in the fit (used for chi^2 computations). Should probably always be 2.

max_auto_size : int

Maximum zoom image size to create when using auto-upsampling


dx,dy : float,float

Measures the amount im2 is offset from im1 (i.e., shift im2 by -1 * these #’s to match im1)

errx,erry : float,float

optional, error in x and y directions

xvals,yvals,chi2n_upsampled : ndarray,ndarray,ndarray,

x,y positions (in original chi^2 coordinates) of the chi^2 values and their corresponding chi^2 value


Create a 2d array, shift it in both directions, then use chi2_shift to determine the shift

>>> import image_registration
>>> rr = ((np.indices([100,100]) - np.array([50.,50.])[:,None,None])**2).sum(axis=0)**0.5
>>> image = np.exp(-rr**2/(3.**2*2.)) * 20
>>> shifted = np.roll(np.roll(image,12,0),5,1) + np.random.randn(100,100)
>>> dx,dy,edx,edy = chi2_shift(image, shifted, upsample_factor='auto')
>>> shifted2 = image_registration.fft_tools.shift2d(image,3.665,-4.25) + np.random.randn(100,100)
>>> dx2,dy2,edx2,edy2 = chi2_shift(image, shifted2, upsample_factor='auto')