예제 #1
0
def align(img1,img2,inc1,inc2,mask1=False,mask2=False):

	#align image1 with image2 
	##shift, error, diffphase = register_translation((img1), (img2),100)
	if mask1 is False:
		shift,error,diffphase = phase_cross_correlation((img1),(img2),upsample_factor=100)
	else:
		shift = phase_cross_correlation((img1),(img2),upsample_factor=100,reference_mask=mask1,moving_mask=mask2)

	if mask1 is False:
		print ('register images new shift (y,x): [{} : {}] mas'.format(shift[0]*inc1,shift[1]*inc2))
		print ('register images new shift (y,x): {} px +- {}'.format(shift,error))

	else:
		print ('register images new shift (y,x): [{} : {}] mas'.format(shift[0]*inc1,shift[1]*inc2))
		print ('register images new shift (y,x): {} px'.format(shift))

	
	#shift img2 to found position
	img2 = apply_shift(img2,shift)
	
	#return aligned image and the computed shift
	if mask1 is False:
		return {'align':img2, 'shift':shift, 'error':error, 'diffphase': diffphase}
	else:
		return {'align':img2, 'shift':shift}
예제 #2
0
def find_beam_offset_cross_correlation(z, radius_start, radius_finish):
    """Find the offset of the direct beam from the image center by a cross-correlation algorithm.
    The shift is calculated relative to an circle perimeter. The circle can be
    refined across a range of radii during the centring procedure to improve
    performance in regions where the direct beam size changes,
    e.g. during sample thickness variation.

    Parameters
    ----------
    radius_start : int
        The lower bound for the radius of the central disc to be used in the
        alignment.
    radius_finish : int
        The upper bounds for the radius of the central disc to be used in the
        alignment.

    Returns
    -------
    shift: np.array
        np.array [y, x] containing offset (from center) of the direct beam positon.
    """
    radiusList = np.arange(radius_start, radius_finish)
    errRecord = np.zeros_like(radiusList, dtype="single")
    origin = np.array(
        [[round(np.size(z, axis=-2) / 2),
          round(np.size(z, axis=-1) / 2)]])

    for ind in np.arange(0, np.size(radiusList)):
        radius = radiusList[ind]
        ref = reference_circle(origin, np.size(z, axis=-2),
                               np.size(z, axis=-1), radius)
        h0 = np.hanning(np.size(ref, 0))
        h1 = np.hanning(np.size(ref, 1))
        hann2d = np.sqrt(np.outer(h0, h1))
        ref = hann2d * ref
        im = hann2d * z
        shift, error, diffphase = phase_cross_correlation(ref,
                                                          im,
                                                          upsample_factor=10)
        errRecord[ind] = error
        index_min = np.argmin(errRecord)

    ref = reference_circle(origin, np.size(z, axis=-2), np.size(z, axis=-1),
                           radiusList[index_min])
    h0 = np.hanning(np.size(ref, 0))
    h1 = np.hanning(np.size(ref, 1))
    hann2d = np.sqrt(np.outer(h0, h1))
    ref = hann2d * ref
    im = hann2d * z
    shift, error, diffphase = phase_cross_correlation(ref,
                                                      im,
                                                      upsample_factor=100)

    shift = shift[::-1]
    return shift - 0.5
예제 #3
0
def align_image(image_in: np.ndarray,
                im_index: int,
                interpolation: str,
                accuracy: float,
                resize: Optional[float],
                num_references: int,
                subframe: Optional[float],
                ref_images_reshape: np.ndarray,
                ref_images_shape: Tuple[int, int, int]) -> np.ndarray:

    offset = np.array([0., 0.])

    # Reshape the reference images back to their original 3D shape
    # The original shape can not be used directly because of util.module.update_arguments
    ref_images = ref_images_reshape.reshape(ref_images_shape)

    for i in range(num_references):
        if subframe is None:
            tmp_offset, _, _ = phase_cross_correlation(ref_images[i, :, :],
                                                       image_in,
                                                       upsample_factor=accuracy)

        else:
            sub_in = crop_image(image_in, None, subframe)
            sub_ref = crop_image(ref_images[i, :, :], None, subframe)

            tmp_offset, _, _ = phase_cross_correlation(sub_ref,
                                                       sub_in,
                                                       upsample_factor=accuracy)
        offset += tmp_offset

    offset /= float(num_references)

    if resize is not None:
        offset *= resize

        sum_before = np.sum(image_in)

        tmp_image = rescale(image_in,
                            (resize, resize),
                            order=5,
                            mode='reflect',
                            multichannel=False,
                            anti_aliasing=True)

        sum_after = np.sum(tmp_image)

        # Conserve flux because the rescale function normalizes all values to [0:1].
        tmp_image = tmp_image*(sum_before/sum_after)

    else:
        tmp_image = image_in

    return shift_image(tmp_image, offset, interpolation)
예제 #4
0
def _determine_registration_offset(base_image, uncorrected_image):
    """
    
    Finds the translational offset required to align this image with all others in the stack.
    Returns dx, dy adjustments in pixels *but does not change the image!*
    
    :param base_image:   a 2D numpy array that the other image should be aligned to
    :param uncorrected_image:   a 2D numpy array
    :returns:   float, float
    
    """
    # Original bounds:
    left_bounds = (0.1, 0.3)
    right_bounds = (0.7, 0.9)
    # left_bounds = (0.35, 0.45)
    # right_bounds = ( 0.6, 0.7)
    # Get the dimensions of the images that we're aligning
    base_height, base_width = base_image.shape
    uncorrected_height, uncorrected_width = uncorrected_image.shape

    # We take the area that roughly corresponds to the catch channels. This has two benefits: one, it
    # speeds up the registration significantly (as it scales linearly with image size), and two, if
    # a large amount of debris/yeast/bacteria/whatever shows up in the central trench, the registration
    # algorithm goes bonkers if it's considering that portion of the image.
    # Thus we separately find the registration for the left side and right side, and average them.
    left_base_section = base_image[:,
                                   int(base_width *
                                       left_bounds[0]):int(base_width *
                                                           left_bounds[1])]
    left_uncorrected = uncorrected_image[:,
                                         int(uncorrected_width * left_bounds[0]
                                             ):int(uncorrected_width *
                                                   left_bounds[1])]
    right_base_section = base_image[:,
                                    int(base_width *
                                        right_bounds[0]):int(base_width *
                                                             right_bounds[1])]
    right_uncorrected = uncorrected_image[:,
                                          int(uncorrected_width *
                                              right_bounds[0]
                                              ):int(uncorrected_width *
                                                    right_bounds[1])]

    #
    left_dy, left_dx = phase_cross_correlation(left_base_section,
                                               left_uncorrected,
                                               upsample_factor=20)[0]
    right_dy, right_dx = phase_cross_correlation(right_base_section,
                                                 right_uncorrected,
                                                 upsample_factor=20)[0]

    return (left_dy + right_dy) / 2.0, (left_dx + right_dx) / 2.0
예제 #5
0
def find_and_apply_shifts(ref_image,
                          other_images,
                          dapi_index,
                          block_size=500,
                          block_pad=250):
    im1 = ref_image[:, :, dapi_index]
    ImagesAligned = [ref_image.astype(np.float32)]
    for im2 in other_images:
        im2_shift = np.zeros(im2.shape, dtype=np.float32)
        for i in range(0, im1.shape[0], block_size):
            for j in range(0, im1.shape[1], block_size):
                im1_block = im1[max(0, i -
                                    block_pad):i + block_size + block_pad,
                                max(0, j - block_pad):j + block_size +
                                block_pad]
                im2_block = im2[i:i + block_size, j:j + block_size]
                if (im1_block.sum() > 0) and (im2_block.sum() > 0):
                    pad0 = im1_block.shape[0] - im2_block.shape[0]
                    pad1 = im1_block.shape[1] - im2_block.shape[1]
                    pad0 = (int(pad0 / 2), int(pad0 / 2 + pad0 % 2))
                    pad1 = (int(pad1 / 2), int(pad1 / 2 + pad1 % 2))
                    im2_block = np.pad(im2_block, (pad0, pad1, (0, 0)),
                                       'constant').astype(im1_block.dtype)
                    shift, error, diffphase = phase_cross_correlation(
                        im1_block, im2_block[:, :, dapi_index])
                    offset_image = apply_shift_to_stack(im2_block, shift)
                    im2_shift[max(0, i - block_pad):i + block_size + block_pad,
                              max(0, j - block_pad):j + block_size +
                              block_pad] += offset_image
        ImagesAligned.append(im2_shift)
    return ImagesAligned
예제 #6
0
def get_cam_roll_pxsize(imgs, positions):
    '''Finds camera angle and pixel size

    Parameters
    ----------
    imgs : list(ndarray)
        List of images where nozzle has been moved in x-direction
    positions : list(float)
        List of motor positions in millimeters

    Returns
    -------
    cam_roll : float
        Camera angle in radians
    pxsize : float
        Pixel size in millimeters
    '''
    ytot = 0
    xtot = 0
    changetot = 0
    for i in range(len(positions) - 1):
        im1, im2 = imgs[i], imgs[i + 1]
        (dy, dx), _, _ = phase_cross_correlation(im1, im2, upsample_factor=100)
        if dy < 0:
            dy *= -1
            dx *= -1
        ytot += dy
        xtot += dx
        changetot += abs(positions[i + 1] - positions[i])

    cam_roll = -np.arctan(ytot / xtot)
    pxsize = changetot / np.sqrt(ytot**2 + xtot**2)
    return cam_roll, pxsize
예제 #7
0
def get_nozzle_shift(im1, im2, *, cam_roll, pxsize):
    """
    Find the distance the nozzle has shifted between two images.

    Parameters
    ----------
    im1 : ndarray
        On-axis camera image 1.

    im2 : ndarray
        On-axis camera image 2.

    cam_roll : float
        Rotation of camera about z axis in radians.

    pxsize : float
        Size of pixel in mm.

    Returns
    -------
    dy : float
        Distance in y.

    dx : float
        Distance in x.
    """

    # Generalize for both cameras?
    (sy, sx), _, _ = phase_cross_correlation(im1, im2, upsample_factor=100)
    dx = (sx * np.cos(cam_roll) - sy * np.sin(cam_roll)) * pxsize
    dy = (sy * np.cos(cam_roll) + sx * np.sin(cam_roll)) * pxsize
    return dy, dx
예제 #8
0
 def image_registration(self):
     """ Register using cross correlation"""
     tforms = self.fishdata.load_data('tforms',dataset=self.dataset,posname=self.posname,hybe=self.hybe)
     if not isinstance(tforms,type(None)):
         self.tforms = tforms
         self.completed = True
         self.utilities.save_data('Passed',
                                  Dataset=self.dataset,
                                  Position=self.posname,
                                  Hybe=self.hybe,
                                  Channel=self.channel,
                                  Type='flag')
     else:
         if self.verbose:
             self.update_user('Registering Image')
         self.translation_z = 0
         self.residual = 0
         self.nbeads = 0
         if self.hybe==self.parameters['ref_hybe']:
             self.translation_x = 0
             self.translation_y = 0
         else:
             self.ref_image = self.load_image(self.parameters['ref_hybe'],'FarRed')
             self.image = self.load_image(self.hybe,'FarRed')
             shift, error, diffphase = phase_cross_correlation(self.ref_image,
                                                               self.image,
                                                               upsample_factor=10)
             self.translation_x = shift[1]
             self.translation_y = shift[0]
         self.save_tforms()
예제 #9
0
def piecewise_fov_shift(ref_img, tar_img, n_patch=8):
    """ Calculates FOV-shift map between a reference and a target image. Images are split in n_patch X n_patch patches,
    and shift is calculated for each patch separately with phase correlation. The resulting shift map is scaled up and
    missing values interpolated to ref_img size to get an estimated shift value for each pixel.

    Args:
        ref_img (np.array): reference image
        tar_img (np.array): target image to which FOV shift is calculated. Has to be same dimensions as ref_img
        n_patch (int): root number of patches the FOV should be subdivided into for piecewise phase correlation

    Returns:
         np.array: Array containing estimated shifts per pixel (upscaled x_shift_map)
         np.array: Array containing estimated shifts per pixel (upscaled y_shift_map)
    """
    img_dim = ref_img.shape
    patch_size = int(img_dim[0] / n_patch)

    shift_map_x = np.zeros((n_patch, n_patch))
    shift_map_y = np.zeros((n_patch, n_patch))
    for row in range(n_patch):
        for col in range(n_patch):
            curr_ref_patch = ref_img[row * patch_size:row * patch_size + patch_size,
                             col * patch_size:col * patch_size + patch_size]
            curr_tar_patch = tar_img[row * patch_size:row * patch_size + patch_size,
                             col * patch_size:col * patch_size + patch_size]
            patch_shift = phase_cross_correlation(curr_ref_patch, curr_tar_patch, upsample_factor=100,
                                                  return_error=False)
            shift_map_x[row, col] = patch_shift[0]
            shift_map_y[row, col] = patch_shift[1]
    shift_map_x_big = zoom(shift_map_x, patch_size, order=3)
    shift_map_y_big = zoom(shift_map_y, patch_size, order=3)
    return shift_map_x_big, shift_map_y_big
    def find_center_pc(images: Images,
                       initial_guess: Optional[float] = None,
                       tol: float = 0.5) -> float:
        """
        Find rotation axis location by finding the offset between the first
        projection and a mirrored projection 180 degrees apart using
        phase correlation in Fourier space.

        Implements an updated version of Tomopy's `find_center_pc`, source:
        https://github.com/tomopy/tomopy/blob/1ae454caf4da496499be6e6c6d6299e74550cf50/source/tomopy/recon/rotation.py#L374-L418
        The changes make use of the newer scikit-image version and it's registration module, for a faster
        registration by using the `phase_cross_correlation` function. The rest of the changes are to be compatible
        with the data structure used within this package (Images class)
        """
        # if the user provides an initial guess of the COR, take that into account to move the image to it
        initial_guess = 0 if initial_guess is None else initial_guess - images.h_middle
        p1 = ndimage.shift(images.projection(0), [0, -initial_guess],
                           mode='constant',
                           cval=0)
        p2 = np.fliplr(
            ndimage.shift(images.proj180deg.data, [0, -initial_guess],
                          mode='constant',
                          cval=0))
        shift = phase_cross_correlation(p1, p2, upsample_factor=1.0 / tol)
        getLogger(__name__).info(f"Found COR shift {shift}")
        # Compute center of rotation as the center of first image and the
        # registered translation with the second image
        center = (p1.shape[1] + shift[0][1]) / 2
        return center + initial_guess
예제 #11
0
def correct_stage_drift(image1, image2, additional_images=[]):

    # find shift with image registration
    shift_values = phase_cross_correlation(image1, image2, upsample_factor=100)

    shift_y = shift_values[0][0]
    shift_x = shift_values[0][1]

    # using interpolation to shift subpixel precision, image2 is the reference
    image1_shift = shift(image1, shift=(-shift_y, -shift_x), order=5)

    # normalizing and converting to image format
    b = normalizing(croping_after_shift(image1_shift, shift_x, shift_y))
    a = normalizing(croping_after_shift(image2, shift_x, shift_y))
    b_save = Image.fromarray(b * 255)
    a_save = Image.fromarray(a * 255)

    # doing the same with additional images
    additional_images_save = []
    for add_image in additional_images:
        add_image_shift = shift(add_image, shift=(-shift_y, -shift_x), order=5)
        add_image_norm = normalizing(croping_after_shift(add_image_shift, shift_x, shift_y))
        add_image_save = Image.fromarray(add_image_norm * 255)
        additional_images_save.append(add_image_save)

    return b_save, a_save, additional_images_save, (shift_x, shift_y)
예제 #12
0
def _conventional_xc(exp_disc, sim_disc, upsample_factor):
    """Takes two images of disc and finds the shift between them using
    conventional (phase) cross correlation.

    Parameters
    ----------
    exp_disc : np.array()
        A numpy array of the "experimental" disc
    sim_disc : np.array()
        A numpy array of the disc used as a template
    upsample_factor: int (must be even)
        Factor to upsample by, reciprocal of the subpixel resolution
        (eg 10 ==> 1/10th of a pixel)

    Returns
    -------
    shifts
        Pixel shifts required to register the two images

    """

    shifts, error, _ = phase_cross_correlation(exp_disc,
                                               sim_disc,
                                               upsample_factor=upsample_factor)
    shifts = np.flip(
        shifts)  # to comply with hyperspy conventions - see issue#490
    return shifts
예제 #13
0
def get_cam_roll(imgs):
    '''Finds the camera angle

    Parameters
    ----------
    imgs : list(ndarray)
        List of images where nozzle has been moved in x-direction

    Returns
    -------
    cam_roll : float
        Camera angle in radians
    '''
    ytot = 0
    xtot = 0
    for i in range(len(imgs) - 1):
        im1, im2 = imgs[i], imgs[i + 1]
        # Is the order dy, dx correct?
        (dy, dx), _, _ = phase_cross_correlation(im1, im2, upsample_factor=100)
        if dy < 0:
            dy *= -1
            dx *= -1
        ytot += dy
        xtot += dx
    return -np.arctan(ytot / xtot)
예제 #14
0
def get_cam_pitch(imgs):
    """
    Find the camera angle.

    Parameters
    ----------
    imgs : list of ndarray
        List of images where nozzle has been moved in x-direction.

    Returns
    -------
    cam_pitch : float
        Offaxis camera pitch angle in radians.
    """

    ytot = 0
    ztot = 0
    for i in range(len(imgs) - 1):
        im1, im2 = imgs[i], imgs[i + 1]
        (dy, dz), _, _ = phase_cross_correlation(im1, im2, upsample_factor=100)
        if dy < 0:
            dy *= -1
            dz *= -1
        ytot += dy
        ztot += dz
    # why is this one not negative?
    return np.arctan(ytot / ztot)
예제 #15
0
def test_detrecated_masked_register_translation():
    reference_image, moving_image, _ = stereo_motorcycle()
    ref_mask = np.random.choice(
        [True, False], reference_image.shape, p=[3 / 4, 1 / 4])
    with expected_warnings(["Function ``masked_register_translation``"]):
        assert_equal(_deprecated(reference_image, moving_image, ref_mask),
                     phase_cross_correlation(reference_image, moving_image,
                                             reference_mask=ref_mask))
예제 #16
0
 def _compute_transform(self, image1, image2, mask1=None, mask2=None):
     # Masks are ignored by default
     dy, dx = phase_cross_correlation(image1,
                                      image2,
                                      upsample_factor=self._up_factor,
                                      space=self._fft_space,
                                      return_error=False)
     return transform.AffineTransform(translation=(-dx, -dy))
예제 #17
0
def register_frame(frame, mask, reference):

    detected_shift = phase_cross_correlation(reference,
                                             frame,
                                             reference_mask=mask)
    shifted_frame = ndi.shift(frame, detected_shift, mode='reflect')
    shifted_mask = ndi.shift(mask, detected_shift, mode='constant', cval=0)
    return shifted_frame, shifted_mask
예제 #18
0
def cross_correlate_image_pairs(pairs: tuple) -> list:
    """Cross correlate image pairs."""
    translations = []
    for img0, img1 in pairs:
        translation, error, phasediff = phase_cross_correlation(img0, img1, upsample_factor=10)
        print(f'shift {translation} error {error:.4f} phasediff {phasediff:.4f}')
        translations.append(translation)
    return translations
예제 #19
0
def image_registration(ref_image, off_image, img_to_reg=None, upsample_fac=50):
    """ Function to co-register off_image with respect to off_image"""
    shift, error, diffphase = phase_cross_correlation(
        ref_image, off_image, upsample_factor=upsample_fac)
    if img_to_reg is None:
        img_to_reg = off_image
    reg_image = np.real(
        np.fft.ifftn(fourier_shift(np.fft.fftn(img_to_reg), shift)))
    return reg_image
예제 #20
0
def calibrate_mag1_from_image_fn(center_fn, other_fn):
    """Calibrate pixel->stageposition coordinates from a set of images.

    center_fn: `str`
        Reference image at the center of the grid (with the clover in the middle)
    other_fn: `tuple` of `str`
        Set of images to cross correlate to the first reference image

    return:
        instance of Calibration class with conversion methods
    """
    img_cent, h_cent = read_image(center_fn)

    # binsize = h_cent["ImageBinsize"]
    cam_dimensions = h_cent['ImageCameraDimensions']
    bin_x, bin_y = cam_dimensions / np.array(img_cent.shape)
    assert bin_x == bin_y, 'Binsizes do not match {bin_x} != {bin_y}'
    binsize = int(bin_x)

    img_cent, scale = autoscale(img_cent, maxdim=512)

    x_cent, y_cent, _, _, _ = h_cent['StagePosition']

    xy_cent = np.array([x_cent, y_cent])
    print('Center:', center_fn)
    print('Stageposition: x={:.0f} | y={:.0f}'.format(*xy_cent))
    print()

    shifts = []
    stagepos = []

    for i, fn in enumerate(other_fn):
        img, h = read_image(fn)

        img = imgscale(img, scale)

        x_xobs, yobs, _, _, _ = h_cent['StagePosition']
        print('Image:', fn)
        print(f'Stageposition: x={xobs:.0f} | y={yobs:.0f}')

        shift, error, phasediff = phase_cross_correlation(img_cent, img, upsample_factor=10)
        print('Shift:', shift)
        print()

        stagepos.append((xobs, yobs))
        shifts.append(shift)

    # correct for binsize, store as binsize=1
    shifts = np.array(shifts) * binsize / scale
    stagepos = np.array(stagepos) - xy_cent

    c = CalibStage.from_data(shifts, stagepos, reference_position=xy_cent, camera_dimensions=cam_dimensions)
    c.plot()
    c.to_file()

    return c
예제 #21
0
        def _align_image(image_in: np.ndarray) -> np.ndarray:
            offset = np.array([0., 0.])

            for i in range(self.m_num_references):
                if self.m_subframe is None:
                    tmp_offset, _, _ = phase_cross_correlation(
                        ref_images[i, :, :],
                        image_in,
                        upsample_factor=self.m_accuracy)

                else:
                    sub_in = crop_image(image_in, None, self.m_subframe)
                    sub_ref = crop_image(ref_images[i, :, :], None,
                                         self.m_subframe)

                    tmp_offset, _, _ = phase_cross_correlation(
                        sub_ref, sub_in, upsample_factor=self.m_accuracy)
                offset += tmp_offset

            offset /= float(self.m_num_references)

            if self.m_resize is not None:
                offset *= self.m_resize

                sum_before = np.sum(image_in)

                tmp_image = rescale(image=np.asarray(image_in,
                                                     dtype=np.float64),
                                    scale=(self.m_resize, self.m_resize),
                                    order=5,
                                    mode='reflect',
                                    anti_aliasing=True,
                                    multichannel=False)

                sum_after = np.sum(tmp_image)

                # Conserve flux because the rescale function normalizes all values to [0:1].
                tmp_image = tmp_image * (sum_before / sum_after)

            else:
                tmp_image = image_in

            return shift_image(tmp_image, offset, self.m_interpolation)
예제 #22
0
    def align_to(
        self,
        ref_img: 'np.array',
        apply: bool = True,
        verbose: bool = False,
    ) -> list:
        """Align current view by comparing it against the given image using
        cross correlation. The stage is translated so that the object of
        interest (in the reference image) is at the center of the view.

        Parameters
        ----------
        ref_img : np.array
            Reference image that the microscope will be aligned to
        apply : bool
            Toggle to translate the stage to center the image
        verbose : bool
            Be more verbose

        Returns
        -------
        stage_shift : np.array[2]
            The stage shift vector determined from cross correlation
        """
        from skimage.registration import phase_cross_correlation

        current_x, current_y = self.stage.xy

        if verbose:
            print(f'Current stage position: {current_x:.0f} {current_y:.0f}')

        stagematrix = self.get_stagematrix()

        img = self.get_rotated_image()

        pixel_shift, error, phasediff = phase_cross_correlation(
            ref_img, img, upsample_factor=10)

        stage_shift = np.dot(pixel_shift, stagematrix)
        stage_shift[0] = -stage_shift[0]  # match TEM Coordinate system

        print(
            f'Aligning: shifting stage by dx={stage_shift[0]:6.0f} dy={stage_shift[1]:6.0f}'
        )

        new_x = current_x + stage_shift[0]
        new_y = current_y + stage_shift[1]

        if verbose:
            print(f'New stage position: {new_x:.0f} {new_y:.0f}')

        if apply:
            self.stage.set_xy_with_backlash_correction(x=new_x, y=new_y)

        return stage_shift
def calibrate_stage_lowmag_from_image_fn(center_fn, other_fn):
    """Calibrate pixel->stageposition coordinates from a set of images.

    center_fn: `str`
        Reference image at the center of the grid (with the clover in the middle)
    other_fn: `tuple` of `str`
        Set of images to cross correlate to the first reference image

    return:
        instance of Calibration class with conversion methods
    """
    img_cent, h_cent = read_image(center_fn)

    img_cent, scale = autoscale(img_cent, maxdim=512)

    x_cent, y_cent, _, _, _ = h_cent['StagePosition']
    xy_cent = np.array([x_cent, y_cent])
    print('Center:', center_fn)
    print('Stageposition: x={:.0f} | y={:.0f}'.format(*xy_cent))
    print()

    binsize = h_cent['ImageBinsize']

    shifts = []
    stagepos = []

    for fn in other_fn:
        img, h = read_image(fn)

        img = imgscale(img, scale)

        xobs, yobs, _, _, _ = h['StagePosition']
        print('Image:', fn)
        print(f'Stageposition: x={xobs:.0f} | y={yobs:.0f}')
        print()

        shift, error, phasediff = phase_cross_correlation(img_cent,
                                                          img,
                                                          upsample_factor=10)

        stagepos.append((xobs, yobs))
        shifts.append(shift)

    # correct for binsize, store as binsize=1
    shifts = np.array(shifts) * binsize / scale
    stagepos = np.array(stagepos) - xy_cent

    c = CalibStage.from_data(shifts,
                             stagepos,
                             reference_position=xy_cent,
                             header=h_cent)
    c.plot()

    return c
예제 #24
0
def calculate_image_offset(img1, img2, upsample_factor=1):
    ref = utils.whiten(img1, 0)
    test = utils.whiten(img2, 0)
    shift = phase_cross_correlation(
        ref,
        test,
        upsample_factor=upsample_factor,
        normalization=None,
        return_error=False,
    )
    return shift
예제 #25
0
def find_shift(reference_image, other_image, scale=0.25):
    """
    """
    # TODO: Fill out docstring. Also why is there a scale parameter here? Is it to save computation?

    rescaled_reference_image = rescale(reference_image, scale)
    rescaled_other_image = rescale(other_image, scale)
    shift, error, diffphase = phase_cross_correlation(rescaled_reference_image,
                                                      rescaled_other_image)
    scaled_shift = shift / scale

    return scaled_shift
예제 #26
0
 def _value_function_handle(params: Dict[Enum, Parameter]) -> np.ndarray:
     shifts, error, _ = phase_cross_correlation(
         params[AngleSelectParams.REF_IMG].value,
         params[AngleSelectParams.ROT_B_IMG].value,
         upsample_factor=params[AngleSelectParams.UPSAMPLING].value,
     )
     tform = AffineTransform(
         scale=1,
         rotation=np.deg2rad(-params[AngleSelectParams.ANGLE_B].value),
     )
     shifts = tform.params[:2, :2] @ shifts[::-1]
     return np.array([*shifts, error])
def cross_correlation(moving, fixed):    
    if moving.shape[-1] == 3:
        moving_gray = rgb2gray(moving)
        fixed_gray = rgb2gray(fixed)
    elif moving.shape[-1] == 1:
        moving_gray = moving[..., 0]
        fixed_gray = fixed[..., 0]
    else:
        print("Image channel Error!")
    
    shift, error, diffphase = phase_cross_correlation(moving_gray, fixed_gray)
    out = np.roll(moving, -np.array(shift).astype(np.int), axis=(0, 1))
    return out, error
예제 #28
0
 def _value_function_handle(params: Dict[Enum, Parameter]) -> np.ndarray:
     shifts, error, _ = phase_cross_correlation(
         params[LogPolParams.REF_IMG].value,
         params[LogPolParams.RECOVERED_ROT_SCALE_IMG].value,
         upsample_factor=params[LogPolParams.UPSAMPLING].value,
     )
     tform = AffineTransform(
         scale=params[LogPolParams.RECOVERED_SCALE].value[0],
         rotation=np.deg2rad(
             -params[LogPolParams.RECOVERED_ROTATION].value[0]),
     )
     shifts = tform.params[:2, :2] @ shifts[::-1]
     return np.array([*shifts, error])
예제 #29
0
def measure_shift(previous_frame, current_frame, mask=None, f=100):
    # note frames are reversed so the shift measures wind speed
    # in terms of the reference image
    shift_yx = phase_cross_correlation(
        current_frame,
        previous_frame,
        return_error=False,
        reference_mask=mask,
        upsample_factor=f  # will have no effect if mask is not None
    )
    x = shift_yx[1] * PYDM_SPEEDSCALE_X
    y = shift_yx[0] * PYDM_SPEEDSCALE_Y
    r, theta = polar_transform(x=x, y=y)
    return x, y, r, theta
예제 #30
0
def test_masked_registration_vs_phase_cross_correlation():
    """masked_register_translation should give the same results as
    phase_cross_correlation in the case of trivial masks."""
    reference_image = camera()
    shift = (-7, 12)
    shifted = np.real(
        fft.ifft2(fourier_shift(fft.fft2(reference_image), shift)))
    trivial_mask = np.ones_like(reference_image)

    nonmasked_result, *_ = phase_cross_correlation(reference_image, shifted)
    masked_result = masked_register_translation(reference_image,
                                                shifted,
                                                reference_mask=trivial_mask,
                                                overlap_ratio=1 / 10)

    assert_equal(nonmasked_result, masked_result)