Source code for subpixal.cc

"""
A module that provides algorithm for creating sub-pixel cross-correlation
images and computing displacements.

:Author: Mihai Cara (for help, contact `HST Help Desk <https://hsthelp.stsci.edu>`_)

:License: :doc:`../LICENSE`

"""
import numpy as np
from scipy import signal

from .centroid import find_peak
from . import __version__, __version_date__


__all__ = ['find_displacement']


[docs]def find_displacement(ref_image, image00, image10, image01, image11): """ Find subpixel displacements between one reference cutout and a set of four "dithered" cutouts. This is achieved by finding peak position in a "supersampled" cross-correlation image obtained by interlacing cross-correlation maps of reference cutout with each dithered cutout. Parameters ---------- ref_image : numpy.ndarray Image of a reference cutout. image00 : numpy.ndarray Image whose displacement relative to reference image needs to be computed. It must have same shape as ``ref_image``. image10 : numpy.ndarray "Same" image as ``image00`` but sampled at a 1/2 pixel displacement along the X-axis. It must have same shape as ``ref_image``. image01 : numpy.ndarray "Same" image as ``image00`` but sampled at a 1/2 pixel displacement along the Y-axis. It must have same shape as ``ref_image``. image11 : numpy.ndarray "Same" image as ``image00`` but sampled at a 1/2 pixel displacement along both X-axis and Y-axis. It must have same shape as ``ref_image``. Returns ------- dx : float Displacement of ``image00`` with regard to ``ref_image`` along the X-axis (columns). dy : float Displacement of ``image00`` with regard to ``ref_image`` along the Y-axis (rows). """ icc = _build_icc_image(ref_image, image00, image10, image01, image11) xm, ym = find_peak(icc, peak_fit_box=5, peak_search_box='all') # find center of the auto-correlation peak when using signal.fftconvolve: xc = (icc.shape[1] - 1) // 4 yc = (icc.shape[0] - 1) // 4 dx = 0.5 * xm - xc dy = 0.5 * ym - yc return (dx, dy)
def _build_icc_image(ref, im00, im10, im01, im11): """ Build interlaced ("oversampled") cross-correlation image. """ # Check that all images have the same size. This is not really required, # but it simplifies things and, moreover, the rest of the code is designed # to produce images of the same size: if not np.all(np.equal(ref.shape, [im00.shape, im10.shape, im01.shape, im11.shape])): raise ValueError("All cutouts must have same shape.") # cross-correlate images of different shifts cc00 = signal.fftconvolve(ref, im00[::-1, ::-1], mode='same') cc10 = signal.fftconvolve(ref, im10[::-1, ::-1], mode='same') cc01 = signal.fftconvolve(ref, im01[::-1, ::-1], mode='same') cc11 = signal.fftconvolve(ref, im11[::-1, ::-1], mode='same') # combine/interlace cross-correlated images into # an "over-sampled" cross-correlation image: ny, nx = cc00.shape icc = np.empty((2 * ny, 2 * nx), dtype=cc00.dtype.type) icc[::2, ::2] = cc00[::-1,::-1] icc[::2, 1::2] = cc10[::-1,::-1] icc[1::2, ::2] = cc01[::-1,::-1] icc[1::2, 1::2] = cc11[::-1,::-1] return icc