def test_fftn(self): x = random((30, 20, 10)) + 1j*random((30, 20, 10)) assert_array_almost_equal( fft.fft(fft.fft(fft.fft(x, axis=2), axis=1), axis=0), fft.fftn(x)) assert_array_almost_equal(fft.fftn(x) / np.sqrt(30 * 20 * 10), fft.fftn(x, norm="ortho"))
def _prepare(self, data): """Calculate filter and data FFT in preparation for filtering. """ dshape = np.array(data.shape) dshape += (dshape % 2 == 0) # all filter dimensions must be uneven oshape = np.array(data.shape) * 2 - 1 float_dtype = _supported_float_type(data.dtype) data = data.astype(float_dtype, copy=False) if self._cache is None or np.any(self._cache.shape != oshape): coords = np.mgrid[[slice(0, float(n)) for n in dshape]] # this steps over two sets of coordinates, # not over the coordinates individually for k, coord in enumerate(coords): coord -= (dshape[k] - 1) / 2. coords = coords.reshape(2, -1).T # coordinate pairs (r,c) coords = coords.astype(float_dtype, copy=False) f = self.impulse_response(coords[:, 0], coords[:, 1], **self.filter_params).reshape(dshape) f = _pad(f, oshape) F = fft.fftn(f) self._cache = F else: F = self._cache data = _pad(data, oshape) G = fft.fftn(data) return F, G
def test_fftn(self): x = random((30, 20, 10)) + 1j * random((30, 20, 10)) expect = fft.fft(fft.fft(fft.fft(x, axis=2), axis=1), axis=0) assert_array_almost_equal(expect, fft.fftn(x)) assert_array_almost_equal(expect, fft.fftn(x, norm="backward")) assert_array_almost_equal(expect / np.sqrt(30 * 20 * 10), fft.fftn(x, norm="ortho")) assert_array_almost_equal(expect / (30 * 20 * 10), fft.fftn(x, norm="forward"))
def spacecharge_meshes(rho_mesh, deltas, gamma=1, offset=(0,0,0), components=['Ex', 'Ey', 'Ez']): """ Computes several components at once using an explicit FFT convolution. This is the preferred routine. """ # FFT Configuration fft = lambda x: sp_fft.fftn(x, overwrite_x=True) ifft = lambda x: sp_fft.ifftn(x, overwrite_x=True) # Make double sized array nx, ny, nz = rho_mesh.shape crho = np.zeros( (2*nx, 2*ny, 2*nz)) crho[0:nx,0:ny,0:nz] = rho_mesh[0:nx,0:ny,0:nz] # FFT crho = fft(crho) # Factor to convert to V/m factor = 1/(4*np.pi*scipy.constants.epsilon_0) field = {'deltas':deltas} for component in components: # Green gunction green_mesh = igf_mesh3(rho_mesh.shape, deltas, gamma=gamma, offset=offset, component=component) # Convolution of double-sized arrays field_mesh = ifft(crho*fft(green_mesh)) # The result is in a shifted location in the output array field[component] = factor*np.real(field_mesh[nx-1:2*nx-1,ny-1:2*ny-1,nx-1:2*nz-1]) return field
def fft(x, direction='C2C', inverse=False): """ Interface with torch FFT routines for 2D signals. Example ------- x = torch.randn(128, 32, 32, 2) x_fft = fft(x, inverse=True) Parameters ---------- input : tensor complex input for the FFT direction : string 'C2R' for complex to real, 'C2C' for complex to complex inverse : bool True for computing the inverse FFT. NB : if direction is equal to 'C2R', then an error is raised. """ if direction == 'C2R': if not inverse: raise RuntimeError( 'C2R mode can only be done with an inverse FFT.') if direction == 'C2R': output = np.real(ifftn(x, axes=(-3, -2, -1))) elif direction == 'C2C': if inverse: output = ifftn(x, axes=(-3, -2, -1)) else: output = fftn(x, axes=(-3, -2, -1)) return output
def convolution_square_root(PSI, pre_expansion=0, post_contraction=0, positive_real_branch_cut=np.pi, negative_real_branch_cut=0.0): # Input PSI and output Z are BoxFunction convolution kernels # Z is the convolution kernel for the square root of the operator that does convolution with PSI initial_width = PSI.width s = pre_expansion PSI = PSI.restrict_to_new_box(PSI.min - s * PSI.width, PSI.max + s * PSI.width) # expand PSI box by zero PSI_shifted_array = np.roll(PSI.array, -PSI.zeropoint_index, axis=np.arange(PSI.ndim)) fft_PSI = fft.fftn(PSI_shifted_array) sqrt_fft_PSI = np.zeros(fft_PSI.shape, dtype=complex) sqrt_fft_PSI[fft_PSI.real >= 0] = square_root(fft_PSI[fft_PSI.real >= 0], positive_real_branch_cut) sqrt_fft_PSI[fft_PSI.real < 0] = square_root(fft_PSI[fft_PSI.real < 0], negative_real_branch_cut) Z_shifted_array = fft.ifftn(sqrt_fft_PSI) Z_array = np.roll(Z_shifted_array, PSI.zeropoint_index, axis=np.arange(PSI.ndim)) / np.sqrt(PSI.dV) Z = BoxFunction(PSI.min, PSI.max, Z_array) t = post_contraction Z = Z.restrict_to_new_box(Z.min + t * initial_width, Z.max - t * initial_width) # contract Z box return Z
def _elser_particle_old(resolution): """This is the original function from Veit Elser without the tunable feature size.""" x_coordinates = _numpy.arange(resolution + 2) - (resolution + 2) / 2.0 + 0.5 y_coordinates = _numpy.arange(resolution + 2) - (resolution + 2) / 2.0 + 0.5 z_coordinates = _numpy.arange(resolution + 2) - (resolution + 2) / 2.0 + 0.5 radius = _numpy.sqrt(x_coordinates[_numpy.newaxis, _numpy.newaxis, :]**2 + y_coordinates[_numpy.newaxis, :, _numpy.newaxis]**2 + z_coordinates[:, _numpy.newaxis, _numpy.newaxis]**2) particle_mask = radius > resolution / 2. lp_mask = _fft.fftshift(radius > resolution / 4.) particle = _numpy.random.random( (resolution + 2, resolution + 2, resolution + 2)) for _ in range(4): particle[particle_mask] = 0.0 particle_ft = _fft.fftn(particle) particle_ft[lp_mask] = 0.0 particle[:, :] = abs(_fft.ifftn(particle)) particle_average = _numpy.average(particle.flatten()) particle[particle > 0.5 * particle_average] = 1.0 particle[particle <= 0.5 * particle_average] = 0.0 particle[particle_mask] = 0.0 return particle
def ufftn(inarray, dim=None): """N-dimensional unitary Fourier transform. Parameters ---------- inarray : ndarray The array to transform. dim : int, optional The last axis along which to compute the transform. All axes by default. Returns ------- outarray : ndarray (same shape than inarray) The unitary N-D Fourier transform of ``inarray``. Examples -------- >>> input = np.ones((3, 3, 3)) >>> output = ufftn(input) >>> np.allclose(np.sum(input) / np.sqrt(input.size), output[0, 0, 0]) True >>> output.shape (3, 3, 3) """ if dim is None: dim = inarray.ndim outarray = fft.fftn(inarray, axes=range(-dim, 0), norm='ortho') return outarray
def fft_wfc_R2G(wfc, igwx, mill, omega): tmp = FFT.fftn(wfc) / np.sqrt(omega) wfcg = np.zeros((igwx,), dtype=complex) for ig in range(igwx): wfgc[tmp] = tmp[mill[0,ig],mill[1,ig],mill[2,ig]] return wfcg
def test_4d_input_pixel(): phantom = img_as_float(binary_blobs(length=32, n_dim=4)) reference_image = fft.fftn(phantom) shift = (-2., 1., 5., -3) shifted_image = fourier_shift(reference_image, shift) result, error, diffphase = phase_cross_correlation(reference_image, shifted_image, space="fourier") assert_allclose(result, -np.array(shift), atol=0.05)
def test_rfftn(self): x = random((30, 20, 10)) expect = fft.fftn(x)[:, :, :6] assert_array_almost_equal(expect, fft.rfftn(x)) assert_array_almost_equal(expect, fft.rfftn(x, norm="backward")) assert_array_almost_equal(expect / np.sqrt(30 * 20 * 10), fft.rfftn(x, norm="ortho")) assert_array_almost_equal(expect / (30 * 20 * 10), fft.rfftn(x, norm="forward"))
def test_correlation(normalization): reference_image = fft.fftn(camera()) shift = (-7, 12) shifted_image = fourier_shift(reference_image, shift) # pixel precision result, _, _ = phase_cross_correlation(reference_image, shifted_image, space="fourier", normalization=normalization) assert_allclose(result[:2], -np.array(shift))
def k_space_sampling(x, ss, idx): ''' x:signal, of total lenght equal prod(ss). ss: signal shape idx: indexes to take the k-space measurements ''' x = x.reshape(ss) X = fftn(x, s=ss) X = X.reshape((-1, 1)) return X[idx]
def test_correlation_invalid_normalization(normalization): reference_image = fft.fftn(camera()) shift = (-7, 12) shifted_image = fourier_shift(reference_image, shift) # pixel precision with pytest.raises(ValueError): phase_cross_correlation(reference_image, shifted_image, space="fourier", normalization=normalization)
def test_size_one_dimension_input(): # take a strip of the input image reference_image = fft.fftn(camera()[:, 15]).reshape((-1, 1)) subpixel_shift = (-2.4, 4) shifted_image = fourier_shift(reference_image, subpixel_shift) # subpixel precision result, error, diffphase = phase_cross_correlation(reference_image, shifted_image, upsample_factor=20, space="fourier") assert_allclose(result[:2], -np.array((-2.4, 0)), atol=0.05)
def test_subpixel_precision(normalization): reference_image = fft.fftn(camera()) subpixel_shift = (-2.4, 1.32) shifted_image = fourier_shift(reference_image, subpixel_shift) # subpixel precision result, _, _ = phase_cross_correlation(reference_image, shifted_image, upsample_factor=100, space="fourier", normalization=normalization) assert_allclose(result[:2], -np.array(subpixel_shift), atol=0.05)
def test_real_input(dtype): reference_image = camera().astype(dtype, copy=False) subpixel_shift = (-2.4, 1.32) shifted_image = fourier_shift(fft.fftn(reference_image), subpixel_shift) shifted_image = fft.ifftn(shifted_image).real.astype(dtype, copy=False) # subpixel precision result, error, diffphase = phase_cross_correlation(reference_image, shifted_image, upsample_factor=100) assert result.dtype == _supported_float_type(dtype) assert_allclose(result[:2], -np.array(subpixel_shift), atol=0.05)
def elser_particle_nd(array_shape, feature_size, mask=None, return_blured=True): """Return a binary contrast particle of arbitrary dimensionality and shape. Feature size is given in pixels. If no mask is provided the paritlce will be spherical.""" radius = tools.radial_distance(array_shape) if mask is None: particle_size = min(array_shape) - 2 mask = radius < particle_size / 2. elif mask.shape != array_shape: raise ValueError("array_shape and mask.shape are different " f"({array_shape} != {mask.shape})") coordinates = [ _numpy.arange(this_shape) - this_shape / 2 + 0.5 for this_shape in array_shape ] scaling = float(feature_size)**2 / float(len(coordinates[0]))**2 component_exp = [ _numpy.exp(-this_coordinate**2 * scaling) for this_coordinate in coordinates ] lp_kernel = _numpy.ones(array_shape) for index, this_exp in enumerate(component_exp): this_slice = [_numpy.newaxis] * len(array_shape) this_slice[index] = slice(None) this_slice = tuple(this_slice) lp_kernel *= this_exp[this_slice] lp_kernel = _fft.fftshift(lp_kernel) particle = _numpy.random.random(array_shape) for _ in range(4): particle_average = _numpy.median(particle[mask]) particle[particle > particle_average] = 1. particle[particle <= particle_average] = 0. particle[~mask] = 0. particle_ft = _fft.fftn(particle) particle_ft *= lp_kernel particle[:] = abs(_fft.ifftn(particle_ft)) if not return_blured: particle_average = _numpy.median(particle[mask]) particle[particle > particle_average] = 1. particle[particle <= particle_average] = 0. return particle
def random_channel(n, rand, fpower=2.0): freq = fftn(rand.rand(n, n)) fx = fftfreq(n)[:, None] fy = fftfreq(n)[None, :] # combine as l2 norm of freq f = (fx**2 + fy**2)**0.5 i = f > 0 freq[i] /= f[i]**fpower freq[0, 0] = 0.0 data = np.real(ifftn(freq)) data -= data.min() data /= data.max() return data
def fftconvolve3(rho, *greens): """ Efficiently perform a 3D convolution of a charge density rho and multiple Green functions. Parameters ---------- rho : np.array (3D) Charge mesh *greens : np.arrays (3D) Charge meshes for the Green functions, which should be twice the size of rho Returns ------- fields : tuple of np.arrays with the same shape as rho. """ # FFT Configuration fft = lambda x: sp_fft.fftn(x, overwrite_x=True) ifft = lambda x: sp_fft.ifftn(x, overwrite_x=True) # Place rho in double-sized array. Should match the shape of green nx, ny, nz = rho.shape crho = np.zeros((2 * nx, 2 * ny, 2 * nz)) crho[0:nx, 0:ny, 0:nz] = rho[0:nx, 0:ny, 0:nz] # FFT crho = fft(crho) results = [] for green in greens: assert crho.shape == green.shape, f'Green array shape {green.shape} should be twice rho shape {rho.shape}' result = ifft(crho * fft(green)) # Extract the result result = np.real(result[nx - 1:2 * nx - 1, ny - 1:2 * ny - 1, nz - 1:2 * nz - 1]) results.append(result) return tuple(results)
def test_3d_input(): phantom = img_as_float(binary_blobs(length=32, n_dim=3)) reference_image = fft.fftn(phantom) shift = (-2., 1., 5.) shifted_image = fourier_shift(reference_image, shift) result, error, diffphase = phase_cross_correlation(reference_image, shifted_image, space="fourier") assert_allclose(result, -np.array(shift), atol=0.05) # subpixel precision now available for 3-D data subpixel_shift = (-2.3, 1.7, 5.4) shifted_image = fourier_shift(reference_image, subpixel_shift) result, error, diffphase = phase_cross_correlation(reference_image, shifted_image, upsample_factor=100, space="fourier") assert_allclose(result, -np.array(subpixel_shift), atol=0.05)
def fourier(self, field_Re, field_Im=None): if field_Im: FT = np.squeeze(self.cg[field_Re][:, :, :].d + 1j * self.cg[field_Im][:, :, :].d) else: FT = np.squeeze(self.cg[field_Re][:, :, :].d) # use fftn to do an N-dimensional FFT on an N-dimensional numpy array FT = fft.fftn(FT) # we're shifting the sampling frequencies next, so we have to shift the FFT values FT = fft.fftshift(FT) # get the absolute value of the fft FT_mag = np.abs(FT) # get the phase of the fft FT_phi = np.angle(FT) if self.Nx > 1: # find the sampling frequencies in X & shift them kx = fft.fftfreq(self.Nx, self.dx) kx = fft.fftshift(kx) else: kx = None if self.Ny > 1: # find the sampling frequencies in Y & shift them ky = fft.fftfreq(self.Ny, self.dy) ky = fft.fftshift(ky) else: ky = None if self.Nz > 1: # find the sampling frequencies in Z & shift them kz = fft.fftfreq(self.Nz, self.dz) kz = fft.fftshift(kz) else: kz = None return FourierData(self.ds.current_time, kx, ky, kz, FT_mag, FT_phi)
def gaussian_blur_nonperiodic(array, sigma): """Only 1d at this point""" small_size = len(array) pad_size = int(sigma * 10) large_size = small_size + 2 * pad_size large_array = _numpy.zeros(large_size) large_array[pad_size:(small_size + pad_size)] = array large_array[:pad_size] = array[0] large_array[(small_size + pad_size):] = array[-1] x_array = _numpy.arange(-large_size // 2, large_size // 2) kernel_ft = _numpy.exp(-2. * sigma**2 * _numpy.pi**2 * (x_array / large_size)**2) kernel_ft = ((large_size / _numpy.sqrt(2. * _numpy.pi) / sigma) * _fft.fftshift(kernel_ft)) image_ft = _fft.fftn(large_array) image_ft *= kernel_ft blured_large_array = _fft.ifftn(image_ft) return blured_large_array[pad_size:-pad_size]
def scale_image_3d(image, factor): """Scales up the image by the scaling factor. Input: image factor""" size_x = image.shape[0] size_y = image.shape[1] size_z = image.shape[2] center_x = size_x // 2 center_y = size_y // 2 center_z = size_z // 2 window_x = int(size_x // factor) window_y = int(size_y // factor) window_z = int(size_z // factor) image_ft = _fft.fftn( image[center_x - window_x // 2:center_x + window_x // 2, center_y - window_y // 2:center_y + window_y // 2, center_z - window_z // 2:center_z + window_z // 2], [size_x, size_y, size_z]) image_scaled = abs( _fft.ifftn(_fft.fftshift(image_ft), [size_x, size_y, size_z])) return image_scaled
def elser_particle(array_size, particle_size, feature_size, return_blured=True): """Return a binary contrast particle. 'particle_size' and 'feature_size' should both be given in pixels.""" if particle_size > array_size - 2: raise ValueError("Particle size must be <= array_size is " f"({particle_size} > {array_size}-2)") x_coordinates = _numpy.arange(array_size) - array_size / 2. + 0.5 y_coordinates = _numpy.arange(array_size) - array_size / 2. + 0.5 z_coordinates = _numpy.arange(array_size) - array_size / 2. + 0.5 radius = _numpy.sqrt(x_coordinates[_numpy.newaxis, _numpy.newaxis, :]**2 + y_coordinates[_numpy.newaxis, :, _numpy.newaxis]**2 + z_coordinates[:, _numpy.newaxis, _numpy.newaxis]**2) particle_mask = radius > particle_size / 2. kernel_scaling = float(feature_size)**2 / float(array_size)**2 lp_kernel = _fft.fftshift(_numpy.exp(-radius**2 * kernel_scaling)) particle = _numpy.random.random((array_size, ) * 3) for _ in range(4): # binary constrast particle_average = _numpy.median(particle[~particle_mask]) particle[particle > particle_average] = 1. particle[particle <= particle_average] = 0. particle[particle_mask] = 0. # smoothen particle_ft = _fft.fftn(particle) particle_ft *= lp_kernel particle[:, :] = abs(_fft.ifftn(particle_ft)) if not return_blured: particle_average = _numpy.median(particle[~particle_mask]) particle[particle > particle_average] = 1. particle[particle <= particle_average] = 0. return particle
def transformation_3d(group): # return pywt.dwtn(group, 'bior1.5') return fftn(group)
def test_rfftn(self): x = random((30, 20, 10)) assert_array_almost_equal(fft.fftn(x)[:, :, :6], fft.rfftn(x)) assert_array_almost_equal(fft.rfftn(x) / np.sqrt(30 * 20 * 10), fft.rfftn(x, norm="ortho"))
def _fft(image): """shifted fft 2D """ return fftshift(fftn(fftshift(image)))
def phase_cross_correlation(reference_image, moving_image, *, upsample_factor=1, space="real", return_error=True, reference_mask=None, moving_mask=None, overlap_ratio=0.3): """Efficient subpixel image translation registration by cross-correlation. This code gives the same precision as the FFT upsampled cross-correlation in a fraction of the computation time and with reduced memory requirements. It obtains an initial estimate of the cross-correlation peak by an FFT and then refines the shift estimation by upsampling the DFT only in a small neighborhood of that estimate by means of a matrix-multiply DFT. Parameters ---------- reference_image : array Reference image. moving_image : array Image to register. Must be same dimensionality as ``reference_image``. upsample_factor : int, optional Upsampling factor. Images will be registered to within ``1 / upsample_factor`` of a pixel. For example ``upsample_factor == 20`` means the images will be registered within 1/20th of a pixel. Default is 1 (no upsampling). Not used if any of ``reference_mask`` or ``moving_mask`` is not None. space : string, one of "real" or "fourier", optional Defines how the algorithm interprets input data. "real" means data will be FFT'd to compute the correlation, while "fourier" data will bypass FFT of input data. Case insensitive. Not used if any of ``reference_mask`` or ``moving_mask`` is not None. return_error : bool, optional Returns error and phase difference if on, otherwise only shifts are returned. Has noeffect if any of ``reference_mask`` or ``moving_mask`` is not None. In this case only shifts is returned. reference_mask : ndarray Boolean mask for ``reference_image``. The mask should evaluate to ``True`` (or 1) on valid pixels. ``reference_mask`` should have the same shape as ``reference_image``. moving_mask : ndarray or None, optional Boolean mask for ``moving_image``. The mask should evaluate to ``True`` (or 1) on valid pixels. ``moving_mask`` should have the same shape as ``moving_image``. If ``None``, ``reference_mask`` will be used. overlap_ratio : float, optional Minimum allowed overlap ratio between images. The correlation for translations corresponding with an overlap ratio lower than this threshold will be ignored. A lower `overlap_ratio` leads to smaller maximum translation, while a higher `overlap_ratio` leads to greater robustness against spurious matches due to small overlap between masked images. Used only if one of ``reference_mask`` or ``moving_mask`` is None. Returns ------- shifts : ndarray Shift vector (in pixels) required to register ``moving_image`` with ``reference_image``. Axis ordering is consistent with numpy (e.g. Z, Y, X) error : float Translation invariant normalized RMS error between ``reference_image`` and ``moving_image``. phasediff : float Global phase difference between the two images (should be zero if images are non-negative). References ---------- .. [1] Manuel Guizar-Sicairos, Samuel T. Thurman, and James R. Fienup, "Efficient subpixel image registration algorithms," Optics Letters 33, 156-158 (2008). :DOI:`10.1364/OL.33.000156` .. [2] James R. Fienup, "Invariant error metrics for image reconstruction" Optics Letters 36, 8352-8357 (1997). :DOI:`10.1364/AO.36.008352` .. [3] Dirk Padfield. Masked Object Registration in the Fourier Domain. IEEE Transactions on Image Processing, vol. 21(5), pp. 2706-2718 (2012). :DOI:`10.1109/TIP.2011.2181402` .. [4] D. Padfield. "Masked FFT registration". In Proc. Computer Vision and Pattern Recognition, pp. 2918-2925 (2010). :DOI:`10.1109/CVPR.2010.5540032` """ if (reference_mask is not None) or (moving_mask is not None): return _masked_phase_cross_correlation(reference_image, moving_image, reference_mask, moving_mask, overlap_ratio) # images must be the same shape if reference_image.shape != moving_image.shape: raise ValueError("images must be same shape") # assume complex data is already in Fourier space if space.lower() == 'fourier': src_freq = reference_image target_freq = moving_image # real data needs to be fft'd. elif space.lower() == 'real': src_freq = fftn(reference_image) target_freq = fftn(moving_image) else: raise ValueError('space argument must be "real" of "fourier"') # Whole-pixel shift - Compute cross-correlation by an IFFT shape = src_freq.shape image_product = src_freq * target_freq.conj() cross_correlation = ifftn(image_product) # Locate maximum maxima = np.unravel_index(np.argmax(np.abs(cross_correlation)), cross_correlation.shape) midpoints = np.array([np.fix(axis_size / 2) for axis_size in shape]) float_dtype = image_product.real.dtype shifts = np.stack(maxima).astype(float_dtype, copy=False) shifts[shifts > midpoints] -= np.array(shape)[shifts > midpoints] if upsample_factor == 1: if return_error: src_amp = np.sum(np.real(src_freq * src_freq.conj())) src_amp /= src_freq.size target_amp = np.sum(np.real(target_freq * target_freq.conj())) target_amp /= target_freq.size CCmax = cross_correlation[maxima] # If upsampling > 1, then refine estimate with matrix multiply DFT else: # Initial shift estimate in upsampled grid upsample_factor = np.array(upsample_factor, dtype=float_dtype) shifts = np.round(shifts * upsample_factor) / upsample_factor upsampled_region_size = np.ceil(upsample_factor * 1.5) # Center of output array at dftshift + 1 dftshift = np.fix(upsampled_region_size / 2.0) # Matrix multiply DFT around the current shift estimate sample_region_offset = dftshift - shifts*upsample_factor cross_correlation = _upsampled_dft(image_product.conj(), upsampled_region_size, upsample_factor, sample_region_offset).conj() # Locate maximum and map back to original pixel grid maxima = np.unravel_index(np.argmax(np.abs(cross_correlation)), cross_correlation.shape) CCmax = cross_correlation[maxima] maxima = np.stack(maxima).astype(float_dtype, copy=False) maxima -= dftshift shifts += maxima / upsample_factor if return_error: src_amp = np.sum(np.real(src_freq * src_freq.conj())) target_amp = np.sum(np.real(target_freq * target_freq.conj())) # If its only one row or column the shift along that dimension has no # effect. We set to zero. for dim in range(src_freq.ndim): if shape[dim] == 1: shifts[dim] = 0 if return_error: # Redirect user to masked_phase_cross_correlation if NaNs are observed if np.isnan(CCmax) or np.isnan(src_amp) or np.isnan(target_amp): raise ValueError( "NaN values found, please remove NaNs from your " "input data or use the `reference_mask`/`moving_mask` " "keywords, eg: " "phase_cross_correlation(reference_image, moving_image, " "reference_mask=~np.isnan(reference_image), " "moving_mask=~np.isnan(moving_image))") return shifts, _compute_error(CCmax, src_amp, target_amp),\ _compute_phasediff(CCmax) else: return shifts
def _fft_centered(x): return fftmodule.fftshift(fftmodule.fftn(fftmodule.fftshift(x)))