def estimate_shift2D(self, reference='current', correlation_threshold=None, chunk_size=30, roi=None, normalize_corr=False, sobel=True, medfilter=True, hanning=True, plot=False, dtype='float', show_progressbar=None, sub_pixel_factor=1): """Estimate the shifts in a image using phase correlation This method can only estimate the shift by comparing bidimensional features that should not change position between frames. To decrease the memory usage, the time of computation and the accuracy of the results it is convenient to select a region of interest by setting the roi keyword. Parameters ---------- reference : {'current', 'cascade' ,'stat'} If 'current' (default) the image at the current coordinates is taken as reference. If 'cascade' each image is aligned with the previous one. If 'stat' the translation of every image with all the rest is estimated and by performing statistical analysis on the result the translation is estimated. correlation_threshold : {None, 'auto', float} This parameter is only relevant when reference='stat'. If float, the shift estimations with a maximum correlation value lower than the given value are not used to compute the estimated shifts. If 'auto' the threshold is calculated automatically as the minimum maximum correlation value of the automatically selected reference image. chunk_size : {None, int} If int and reference='stat' the number of images used as reference are limited to the given value. roi : tuple of ints or floats (left, right, top, bottom) Define the region of interest. If int(float) the position is given axis index(value). Note that ROIs can be used in place of a tuple. sobel : bool apply a sobel filter for edge enhancement medfilter : bool apply a median filter for noise reduction hanning : bool Apply a 2d hanning filter plot : bool or 'reuse' If True plots the images after applying the filters and the phase correlation. If 'reuse', it will also plot the images, but it will only use one figure, and continuously update the images in that figure as it progresses through the stack. dtype : str or dtype Typecode or data-type in which the calculations must be performed. %s sub_pixel_factor : float Estimate shifts with a sub-pixel accuracy of 1/sub_pixel_factor parts of a pixel. Default is 1, i.e. no sub-pixel accuracy. Returns ------- shifts : list of array List of estimated shifts Notes ----- The statistical analysis approach to the translation estimation when using reference='stat' roughly follows [*]_ . If you use it please cite their article. References ---------- .. [*] Schaffer, Bernhard, Werner Grogger, and Gerald Kothleitner. “Automated Spatial Drift Correction for EFTEM Image Series.” Ultramicroscopy 102, no. 1 (December 2004): 27–36. """ if show_progressbar is None: show_progressbar = preferences.General.show_progressbar self._check_signal_dimension_equals_two() if roi is not None: # Get the indices of the roi yaxis = self.axes_manager.signal_axes[1] xaxis = self.axes_manager.signal_axes[0] roi = tuple([xaxis._get_index(i) for i in roi[2:]] + [yaxis._get_index(i) for i in roi[:2]]) ref = None if reference == 'cascade' else \ self.__call__().copy() shifts = [] nrows = None images_number = self.axes_manager._max_index + 1 if plot == 'reuse': # Reuse figure for plots plot = plt.figure() if reference == 'stat': nrows = images_number if chunk_size is None else \ min(images_number, chunk_size) pcarray = ma.zeros(( nrows, self.axes_manager._max_index + 1, ), dtype=np.dtype([('max_value', np.float), ('shift', np.int32, (2, ))])) nshift, max_value = estimate_image_shift( self(), self(), roi=roi, sobel=sobel, medfilter=medfilter, hanning=hanning, normalize_corr=normalize_corr, plot=plot, dtype=dtype, sub_pixel_factor=sub_pixel_factor) np.fill_diagonal(pcarray['max_value'], max_value) pbar_max = nrows * images_number else: pbar_max = images_number # Main iteration loop. Fills the rows of pcarray when reference # is stat with progressbar(total=pbar_max, disable=not show_progressbar, leave=True) as pbar: for i1, im in enumerate(self._iterate_signal()): if reference in ['current', 'cascade']: if ref is None: ref = im.copy() shift = np.array([0, 0]) nshift, max_val = estimate_image_shift( ref, im, roi=roi, sobel=sobel, medfilter=medfilter, hanning=hanning, plot=plot, normalize_corr=normalize_corr, dtype=dtype, sub_pixel_factor=sub_pixel_factor) if reference == 'cascade': shift += nshift ref = im.copy() else: shift = nshift shifts.append(shift.copy()) pbar.update(1) elif reference == 'stat': if i1 == nrows: break # Iterate to fill the columns of pcarray for i2, im2 in enumerate(self._iterate_signal()): if i2 > i1: nshift, max_value = estimate_image_shift( im, im2, roi=roi, sobel=sobel, medfilter=medfilter, hanning=hanning, normalize_corr=normalize_corr, plot=plot, dtype=dtype, sub_pixel_factor=sub_pixel_factor) pcarray[i1, i2] = max_value, nshift del im2 pbar.update(1) del im if reference == 'stat': # Select the reference image as the one that has the # higher max_value in the row sqpcarr = pcarray[:, :nrows] sqpcarr['max_value'][:] = symmetrize(sqpcarr['max_value']) sqpcarr['shift'][:] = antisymmetrize(sqpcarr['shift']) ref_index = np.argmax(pcarray['max_value'].min(1)) self.ref_index = ref_index shifts = (pcarray['shift'] + pcarray['shift'][ref_index, :nrows][:, np.newaxis]) if correlation_threshold is not None: if correlation_threshold == 'auto': correlation_threshold = \ (pcarray['max_value'].min(0)).max() _logger.info("Correlation threshold = %1.2f", correlation_threshold) shifts[ pcarray['max_value'] < correlation_threshold] = ma.masked shifts.mask[ref_index, :] = False shifts = shifts.mean(0) else: shifts = np.array(shifts) del ref return shifts
def estimate_shift2D(self, reference='current', correlation_threshold=None, chunk_size=30, roi=None, normalize_corr=False, sobel=True, medfilter=True, hanning=True, plot=False, dtype='float', show_progressbar=None): """Estimate the shifts in a image using phase correlation This method can only estimate the shift by comparing bidimensional features that should not change position between frames. To decrease the memory usage, the time of computation and the accuracy of the results it is convenient to select a region of interest by setting the roi keyword. Parameters ---------- reference : {'current', 'cascade' ,'stat'} If 'current' (default) the image at the current coordinates is taken as reference. If 'cascade' each image is aligned with the previous one. If 'stat' the translation of every image with all the rest is estimated and by performing statistical analysis on the result the translation is estimated. correlation_threshold : {None, 'auto', float} This parameter is only relevant when `reference` is 'stat'. If float, the shift estimations with a maximum correlation value lower than the given value are not used to compute the estimated shifts. If 'auto' the threshold is calculated automatically as the minimum maximum correlation value of the automatically selected reference image. chunk_size: {None, int} If int and `reference`=='stat' the number of images used as reference are limited to the given value. roi : tuple of ints or floats (left, right, top bottom) Define the region of interest. If int(float) the position is given axis index(value). sobel : bool apply a sobel filter for edge enhancement medfilter : bool apply a median filter for noise reduction hanning : bool Apply a 2d hanning filter plot : bool If True plots the images after applying the filters and the phase correlation dtype : str or dtype Typecode or data-type in which the calculations must be performed. show_progressbar : None or bool If True, display a progress bar. If None the default is set in `preferences`. Returns ------- list of applied shifts Notes ----- The statistical analysis approach to the translation estimation when using `reference`='stat' roughly follows [1]_ . If you use it please cite their article. References ---------- .. [1] Schaffer, Bernhard, Werner Grogger, and Gerald Kothleitner. “Automated Spatial Drift Correction for EFTEM Signal2D Series.” Ultramicroscopy 102, no. 1 (December 2004): 27–36. """ if show_progressbar is None: show_progressbar = preferences.General.show_progressbar self._check_signal_dimension_equals_two() if roi is not None: # Get the indices of the roi yaxis = self.axes_manager.signal_axes[1] xaxis = self.axes_manager.signal_axes[0] roi = tuple([xaxis._get_index(i) for i in roi[2:]] + [yaxis._get_index(i) for i in roi[:2]]) ref = None if reference == 'cascade' else \ self.__call__().copy() shifts = [] nrows = None images_number = self.axes_manager._max_index + 1 if reference == 'stat': nrows = images_number if chunk_size is None else \ min(images_number, chunk_size) pcarray = ma.zeros((nrows, self.axes_manager._max_index + 1, ), dtype=np.dtype([('max_value', np.float), ('shift', np.int32, (2,))])) nshift, max_value = estimate_image_shift( self(), self(), roi=roi, sobel=sobel, medfilter=medfilter, hanning=hanning, normalize_corr=normalize_corr, plot=plot, dtype=dtype) np.fill_diagonal(pcarray['max_value'], max_value) pbar_max = nrows * images_number else: pbar_max = images_number # Main iteration loop. Fills the rows of pcarray when reference # is stat with progressbar(total=pbar_max, disable=not show_progressbar, leave=True) as pbar: for i1, im in enumerate(self._iterate_signal()): if reference in ['current', 'cascade']: if ref is None: ref = im.copy() shift = np.array([0, 0]) nshift, max_val = estimate_image_shift( ref, im, roi=roi, sobel=sobel, medfilter=medfilter, hanning=hanning, plot=plot, normalize_corr=normalize_corr, dtype=dtype) if reference == 'cascade': shift += nshift ref = im.copy() else: shift = nshift shifts.append(shift.copy()) pbar.update(1) elif reference == 'stat': if i1 == nrows: break # Iterate to fill the columns of pcarray for i2, im2 in enumerate( self._iterate_signal()): if i2 > i1: nshift, max_value = estimate_image_shift( im, im2, roi=roi, sobel=sobel, medfilter=medfilter, hanning=hanning, normalize_corr=normalize_corr, plot=plot, dtype=dtype) pcarray[i1, i2] = max_value, nshift del im2 pbar.update(1) del im if reference == 'stat': # Select the reference image as the one that has the # higher max_value in the row sqpcarr = pcarray[:, :nrows] sqpcarr['max_value'][:] = symmetrize(sqpcarr['max_value']) sqpcarr['shift'][:] = antisymmetrize(sqpcarr['shift']) ref_index = np.argmax(pcarray['max_value'].min(1)) self.ref_index = ref_index shifts = (pcarray['shift'] + pcarray['shift'][ref_index, :nrows][:, np.newaxis]) if correlation_threshold is not None: if correlation_threshold == 'auto': correlation_threshold = \ (pcarray['max_value'].min(0)).max() _logger.info("Correlation threshold = %1.2f", correlation_threshold) shifts[pcarray['max_value'] < correlation_threshold] = ma.masked shifts.mask[ref_index, :] = False shifts = shifts.mean(0) else: shifts = np.array(shifts) del ref return shifts