Example #1
0
    def test_subpixel(self):
        anarr = np.zeros((4, 5))
        anarr[2, 3] = 1
        # The correspondence principle should hold
        first_guess = (2, 3)
        second_guess = utils._interpolate(anarr, first_guess, rad=1)
        np.testing.assert_equal(second_guess, (2, 3))

        # Now something more meaningful
        anarr[2, 4] = 1
        second_guess = utils._interpolate(anarr, first_guess, rad=1)
        np.testing.assert_almost_equal(second_guess, (2, 3.5))
Example #2
0
    def test_subpixel_edge(self):
        anarr = np.zeros((4, 5))
        anarr[3, 0] = 1
        anarr[3, 4] = 1
        first_guess = (4, 0)
        second_guess = utils._interpolate(anarr, first_guess, rad=2)
        np.testing.assert_almost_equal(second_guess, (3, -0.5))

        anarr[3, 0] += 1
        anarr[0, 4] = 1
        second_guess = utils._interpolate(anarr, first_guess, rad=2)
        np.testing.assert_almost_equal(second_guess, (3.25, -0.5))
Example #3
0
    def test_subpixel_edge(self):
        anarr = np.zeros((4, 5))
        anarr[3, 0] = 1
        anarr[3, 4] = 1
        first_guess = (4, 0)
        second_guess = utils._interpolate(anarr, first_guess, rad=2)
        np.testing.assert_almost_equal(second_guess, (3, -0.5))

        anarr[3, 0] += 1
        anarr[0, 4] = 1
        second_guess = utils._interpolate(anarr, first_guess, rad=2)
        np.testing.assert_almost_equal(second_guess, (3.25, -0.5))
Example #4
0
    def test_subpixel(self):
        anarr = np.zeros((4, 5))
        anarr[2, 3] = 1
        # The correspondence principle should hold
        first_guess = (2, 3)
        second_guess = utils._interpolate(anarr, first_guess, rad=1)
        np.testing.assert_equal(second_guess, (2, 3))

        # Now something more meaningful
        anarr[2, 4] = 1
        second_guess = utils._interpolate(anarr, first_guess, rad=1)
        np.testing.assert_almost_equal(second_guess, (2, 3.5))
Example #5
0
def compute_motion_shifts(scan, template, in_place=True, num_threads=8):
    """ Compute shifts in y and x for rigid subpixel motion correction.

    Returns the number of pixels that each image in the scan was to the right (x_shift)
    or below (y_shift) the template. Negative shifts mean the image was to the left or
    above the template.

    :param np.array scan: 2 or 3-dimensional scan (image_height, image_width[, num_frames]).
    :param np.array template: 2-d template image. Each frame in scan is aligned to this.
    :param bool in_place: Whether the scan can be overwritten.
    :param int num_threads: Number of threads used for the ffts.

    :returns: (y_shifts, x_shifts) Two arrays (num_frames) with the y, x motion shifts.

    ..note:: Based in imreg_dft.translation().
    """
    import pyfftw
    from imreg_dft import utils

    # Add third dimension if scan is a single image
    if scan.ndim == 2:
        scan = np.expand_dims(scan, -1)

    # Get some params
    image_height, image_width, num_frames = scan.shape
    taper = np.outer(signal.tukey(image_height, 0.2), signal.tukey(image_width, 0.2))

    # Prepare fftw
    frame = pyfftw.empty_aligned((image_height, image_width), dtype='complex64')
    fft = pyfftw.builders.fft2(frame, threads=num_threads, overwrite_input=in_place,
                               avoid_copy=True)
    ifft = pyfftw.builders.ifft2(frame, threads=num_threads, overwrite_input=in_place,
                                 avoid_copy=True)

    # Get fourier transform of template
    template_freq = fft(template * taper).conj() # we only need the conjugate
    abs_template_freq = abs(template_freq)
    eps = abs_template_freq.max() * 1e-15

    # Compute subpixel shifts per image
    y_shifts = np.empty(num_frames)
    x_shifts = np.empty(num_frames)
    for i in range(num_frames):
        # Compute correlation via cross power spectrum
        image_freq = fft(scan[:, :, i] * taper)
        cross_power = (image_freq * template_freq) / (abs(image_freq) * abs_template_freq + eps)
        shifted_cross_power = np.fft.fftshift(abs(ifft(cross_power)))

        # Get best shift
        shifts = np.unravel_index(np.argmax(shifted_cross_power), shifted_cross_power.shape)
        shifts = utils._interpolate(shifted_cross_power, shifts, rad=3)

        # Map back to deviations from center
        y_shifts[i] = shifts[0] - image_height // 2
        x_shifts[i] = shifts[1] - image_width // 2

    return y_shifts, x_shifts
Example #6
0
def compute_motion_shifts(scan, template, in_place=True, num_threads=8):
    """ Compute shifts in y and x for rigid subpixel motion correction.

    Returns the number of pixels that each image in the scan was to the right (x_shift)
    or below (y_shift) the template. Negative shifts mean the image was to the left or
    above the template.

    :param np.array scan: 2 or 3-dimensional scan (image_height, image_width[, num_frames]).
    :param np.array template: 2-d template image. Each frame in scan is aligned to this.
    :param bool in_place: Whether the scan can be overwritten.
    :param int num_threads: Number of threads used for the ffts.

    :returns: (y_shifts, x_shifts) Two arrays (num_frames) with the y, x motion shifts.

    ..note:: Based in imreg_dft.translation().
    """
    import pyfftw
    from imreg_dft import utils

    # Add third dimension if scan is a single image
    if scan.ndim == 2:
        scan = np.expand_dims(scan, -1)

    # Get some params
    image_height, image_width, num_frames = scan.shape
    taper = np.outer(signal.tukey(image_height, 0.2), signal.tukey(image_width, 0.2))

    # Prepare fftw
    frame = pyfftw.empty_aligned((image_height, image_width), dtype='complex64')
    fft = pyfftw.builders.fft2(frame, threads=num_threads, overwrite_input=in_place,
                               avoid_copy=True)
    ifft = pyfftw.builders.ifft2(frame, threads=num_threads, overwrite_input=in_place,
                                 avoid_copy=True)

    # Get fourier transform of template
    template_freq = fft(template * taper).conj() # we only need the conjugate
    abs_template_freq = abs(template_freq)
    eps = abs_template_freq.max() * 1e-15

    # Compute subpixel shifts per image
    y_shifts = np.empty(num_frames)
    x_shifts = np.empty(num_frames)
    for i in range(num_frames):
        # Compute correlation via cross power spectrum
        image_freq = fft(scan[:, :, i] * taper)
        cross_power = (image_freq * template_freq) / (abs(image_freq) * abs_template_freq + eps)
        shifted_cross_power = np.fft.fftshift(abs(ifft(cross_power)))

        # Get best shift
        shifts = np.unravel_index(np.argmax(shifted_cross_power), shifted_cross_power.shape)
        shifts = utils._interpolate(shifted_cross_power, shifts, rad=3)

        # Map back to deviations from center
        y_shifts[i] = shifts[0] - image_height // 2
        x_shifts[i] = shifts[1] - image_width // 2

    return y_shifts, x_shifts
Example #7
0
 def test_subpixel_crazy(self):
     anarr = np.zeros((4, 5))
     first_guess = (0, 0)
     second_guess = utils._interpolate(anarr, first_guess, rad=2)
     np.testing.assert_array_less(second_guess, anarr.shape)
Example #8
0
 def test_subpixel_crazy(self):
     anarr = np.zeros((4, 5))
     first_guess = (0, 0)
     second_guess = utils._interpolate(anarr, first_guess, rad=2)
     np.testing.assert_array_less(second_guess, anarr.shape)