def upsample_image(image, upsample_factor=1, output_size=None, nthreads=1, use_numpy_fft=False, xshift=0, yshift=0): """ Use dftups to upsample an image (but takes an image and returns an image with all reals) """ fftn, ifftn = fast_ffts.get_ffts(nthreads=nthreads, use_numpy_fft=use_numpy_fft) imfft = ifftn(image) if output_size is None: s1 = image.shape[0] * upsample_factor s2 = image.shape[1] * upsample_factor elif hasattr(output_size, '__len__'): s1 = output_size[0] s2 = output_size[1] else: s1 = output_size s2 = output_size ups = dftups(imfft, s1, s2, upsample_factor, roff=yshift, coff=xshift) return np.abs(ups)
def spshift(data, deltax, deltay, phase=0, nthreads=1, use_numpy_fft=False, return_abs=True): """ FFT-based sub-pixel image shift http://www.mathworks.com/matlabcentral/fileexchange/18401-efficient-subpixel-image-registration-by-cross-correlation/content/html/efficient_subpixel_registration.html Will turn NaNs into zeros """ fftn, ifftn = fast_ffts.get_ffts(nthreads=nthreads, use_numpy_fft=use_numpy_fft) if np.any(np.isnan(data)): data = np.nan_to_num(data) ny, nx = data.shape Nx = np.fft.ifftshift(np.linspace(-np.fix(nx / 2), np.ceil(nx / 2) - 1, nx)) Ny = np.fft.ifftshift(np.linspace(-np.fix(ny / 2), np.ceil(ny / 2) - 1, ny)) Nx, Ny = np.meshgrid(Nx, Ny) gg = ifftn( fftn(data) * np.exp(1j * 2 * np.pi * (-deltax * Nx / nx - deltay * Ny / ny)) * np.exp(-1j * phase)) if return_abs: return np.abs(gg) else: return gg
def shift2d(data, deltax, deltay, phase=0, nthreads=1, use_numpy_fft=False, return_abs=False, return_real=True): """ 2D version: obsolete - use ND version instead (though it's probably easier to parse the source of this one) FFT-based sub-pixel image shift. Will turn NaNs into zeros Shift Theorem: .. math:: FT[f(t-t_0)](x) = e^{-2 \pi i x t_0} F(x) Parameters ---------- data : np.ndarray 2D image phase : float Phase, in radians """ fftn, ifftn = fast_ffts.get_ffts(nthreads=nthreads, use_numpy_fft=use_numpy_fft) if np.any(np.isnan(data)): data = np.nan_to_num(data) ny, nx = data.shape xfreq = deltax * np.fft.fftfreq(nx)[np.newaxis, :] yfreq = deltay * np.fft.fftfreq(ny)[:, np.newaxis] freq_grid = xfreq + yfreq kernel = np.exp(-1j * 2 * np.pi * freq_grid - 1j * phase) result = ifftn(fftn(data) * kernel) if return_real: return np.real(result) elif return_abs: return np.abs(result) else: return result
def fourier_interp2d(data, outinds, nthreads=1, use_numpy_fft=False, return_real=True): """ Use the fourier scaling theorem to interpolate (or extrapolate, without raising any exceptions) data. Parameters ---------- data : ndarray The data values of the array to interpolate outinds : ndarray The coordinate axis values along which the data should be interpolated CAN BE: ndim x [n,m,...] like np.indices OR (less memory intensive, more processor intensive): ([n],[m],...) """ # load fft fftn,ifftn = fast_ffts.get_ffts(nthreads=nthreads, use_numpy_fft=use_numpy_fft) if hasattr(outinds,'ndim') and outinds.ndim not in (data.ndim+1,data.ndim): raise ValueError("Must specify an array of output indices with # of dimensions = input # of dims + 1") elif len(outinds) != data.ndim: raise ValueError("outind array must have an axis for each dimension") imfft = ifftn(data) freqY = np.fft.fftfreq(data.shape[0]) if hasattr(outinds,'ndim') and outinds.ndim == 3: # if outinds = np.indices(shape), we extract just lines along each index indsY = freqY[np.newaxis,:]*outinds[0,:,0][:,np.newaxis] else: indsY = freqY[np.newaxis,:]*np.array(outinds[0])[:,np.newaxis] kerny=np.exp((-1j*2*np.pi)*indsY) freqX = np.fft.fftfreq(data.shape[1]) if hasattr(outinds,'ndim') and outinds.ndim == 3: # if outinds = np.indices(shape), we extract just lines along each index indsX = freqX[:,np.newaxis]*outinds[1,0,:][np.newaxis,:] else: indsX = freqX[:,np.newaxis]*np.array(outinds[1])[np.newaxis,:] kernx=np.exp((-1j*2*np.pi)*indsX) result = np.dot(np.dot(kerny, imfft), kernx) if return_real: return result.real else: return result
def upsample_image(image, upsample_factor=1, output_size=None, nthreads=1, use_numpy_fft=False, xshift=0, yshift=0): """ Use dftups to upsample an image (but takes an image and returns an image with all reals) """ fftn, ifftn = fast_ffts.get_ffts(nthreads=nthreads, use_numpy_fft=use_numpy_fft) imfft = ifftn(image) if output_size is None: s1 = image.shape[0] * upsample_factor s2 = image.shape[1] * upsample_factor elif hasattr(output_size, "__len__"): s1 = output_size[0] s2 = output_size[1] else: s1 = output_size s2 = output_size ups = dftups(imfft, s1, s2, upsample_factor, roff=yshift, coff=xshift) return np.abs(ups)
def shift1d(data, deltax, phase=0, nthreads=1, use_numpy_fft=False, return_abs=False, return_real=True): """ FFT-based sub-pixel image shift http://www.mathworks.com/matlabcentral/fileexchange/18401-efficient-subpixel-image-registration-by-cross-correlation/content/html/efficient_subpixel_registration.html Will turn NaNs into zeros """ fftn,ifftn = fast_ffts.get_ffts(nthreads=nthreads, use_numpy_fft=use_numpy_fft) if np.any(np.isnan(data)): data = np.nan_to_num(data) nx = data.size Nx = np.fft.ifftshift(np.linspace(-np.fix(nx/2),np.ceil(nx/2)-1,nx)) gg = ifftn( fftn(data)* np.exp(1j*2*np.pi*(-deltax*Nx/nx)) * np.exp(-1j*phase) ) if return_real: return np.real(gg) elif return_abs: return np.abs(gg) else: return gg
def shiftnd(data, offset, phase=0, nthreads=1, use_numpy_fft=False, return_abs=False, return_real=True): """ FFT-based sub-pixel image shift. Will turn NaNs into zeros Shift Theorem: .. math:: FT[f(t-t_0)](x) = e^{-2 \pi i x t_0} F(x) Parameters ---------- data : np.ndarray Data to shift offset : (int,)*ndim Offsets in each direction. Must be iterable. phase : float Phase, in radians Other Parameters ---------------- use_numpy_fft : bool Force use numpy's fft over fftw? (only matters if you have fftw installed) nthreads : bool Number of threads to use for fft (only matters if you have fftw installed) return_real : bool Return the real component of the shifted array return_abs : bool Return the absolute value of the shifted array Returns ------- The input array shifted by offsets """ fftn, ifftn = fast_ffts.get_ffts(nthreads=nthreads, use_numpy_fft=use_numpy_fft) if np.any(np.isnan(data)): data = np.nan_to_num(data) freq_grid = np.sum([ off * np.fft.fftfreq(nx)[[np.newaxis] * dim + [slice(None)] + [np.newaxis] * (data.ndim - dim - 1)] for dim, (off, nx) in enumerate(zip(offset, data.shape)) ], axis=0) kernel = np.exp(-1j * 2 * np.pi * freq_grid - 1j * phase) result = ifftn(fftn(data) * kernel) if return_real: return np.real(result) elif return_abs: return np.abs(result) else: return result
pl.title('Ny') deltax, deltay = 1.5, -1.5 # 22.5,30.3 kernel = np.exp(1j * 2 * np.pi * (-deltax * Nx / nx - deltay * Ny / ny)) pl.figure() pl.subplot(131) pl.imshow(kernel.real) pl.title("kernel.real") pl.colorbar() pl.subplot(132) pl.imshow(kernel.imag) pl.title("kernel.imag") pl.colorbar() pl.subplot(133) pl.imshow(np.abs(kernel)) pl.title("abs(kernel)") pl.colorbar() fftn, ifftn = fast_ffts.get_ffts(nthreads=4, use_numpy_fft=False) phase = 0 gg = ifftn(fftn(data) * kernel * np.exp(-1j * phase)) pl.figure() pl.subplot(121) pl.imshow(gg.real) pl.title("gg.real") pl.subplot(122) pl.imshow(gg.imag) pl.title("gg.imag")
# return np.roll(np.roll(out,+1,axis=0),+1,axis=1) return out if __name__ == "__main__" and False: # breakdown of the dft upsampling method from numpy.fft import ifftshift from numpy import pi, newaxis, floor from pylab import * xx, yy = np.meshgrid(np.linspace(-5, 5, 100), np.linspace(-5, 5, 100)) # a Gaussian image data = np.exp(-(xx ** 2 + yy ** 2) / (0.5 ** 2 * 2.0)) fftn, ifftn = fast_ffts.get_ffts(nthreads=4, use_numpy_fft=False) print "input max pixel: ", np.unravel_index(data.argmax(), data.shape) inp = ifftn(data) nr, nc = np.shape(inp) noc, nor = nc, nr # these are the output sizes # upsample_factor usfac = 20.0 for usfac in [1, 2, 5, 10, 20, 30, 40]: # the "virtual image" will have size im.shape[0]*usfac,im.shape[1]*usfac # To "zoom in" on the center of the image, we need an offset that identifies # the lower-left corner of the new image vshape = inp.shape[0] * usfac, inp.shape[1] * usfac roff = -(vshape[0] - usfac - nor) / 2.0 - 1 coff = -(vshape[1] - usfac - noc) / 2.0 - 1
def shiftnd(data, offset, phase=0, nthreads=1, use_numpy_fft=False, return_abs=False, return_real=True): """ FFT-based sub-pixel image shift. Will turn NaNs into zeros Shift Theorem: .. math:: FT[f(t-t_0)](x) = e^{-2 \pi i x t_0} F(x) Parameters ---------- data : np.ndarray Data to shift offset : (int,)*ndim Offsets in each direction. Must be iterable. phase : float Phase, in radians Other Parameters ---------------- use_numpy_fft : bool Force use numpy's fft over fftw? (only matters if you have fftw installed) nthreads : bool Number of threads to use for fft (only matters if you have fftw installed) return_real : bool Return the real component of the shifted array return_abs : bool Return the absolute value of the shifted array Returns ------- The input array shifted by offsets """ fftn, ifftn = fast_ffts.get_ffts(nthreads=nthreads, use_numpy_fft=use_numpy_fft) if np.any(np.isnan(data)): data = np.nan_to_num(data) freq_grid = np.sum( [ off * np.fft.fftfreq(nx)[[np.newaxis] * dim + [slice(None)] + [np.newaxis] * (data.ndim - dim - 1)] for dim, (off, nx) in enumerate(zip(offset, data.shape)) ], axis=0, ) kernel = np.exp(-1j * 2 * np.pi * freq_grid - 1j * phase) result = ifftn(fftn(data) * kernel) if return_real: return np.real(result) elif return_abs: return np.abs(result) else: return result
def fourier_interp1d(data, out_x, data_x=None, nthreads=1, use_numpy_fft=False, return_real=True): """ Use the fourier scaling theorem to interpolate (or extrapolate, without raising any exceptions) data. Parameters ---------- data : ndarray The Y-values of the array to interpolate out_x : ndarray The X-values along which the data should be interpolated data_x : ndarray | None The X-values corresponding to the data values. If an ndarray, must have the same shape as data. If not specified, will be set to np.arange(data.size) Other Parameters ---------------- nthreads : int Number of threads for parallelized FFTs (if available) use_numpy_fft : bool Use the numpy version of the FFT before any others? (Default is to use fftw3) Returns ------- The real component of the interpolated 1D array, or the full complex array if return_real is False Raises ------ ValueError if output indices are the wrong shape or the data X array is the wrong shape """ # load fft fftn,ifftn = fast_ffts.get_ffts(nthreads=nthreads, use_numpy_fft=use_numpy_fft) # specify fourier frequencies freq = np.fft.fftfreq(data.size)[:,np.newaxis] # reshape outinds if out_x.ndim != 1: raise ValueError("Must specify a 1-d array of output indices") if data_x is not None: if data_x.shape != data.shape: raise ValueError("Incorrect shape for data_x") # interpolate output indices onto linear grid outinds = np.interp(out_x, data_x, np.arange(data.size))[np.newaxis,:] else: outinds = out_x[np.newaxis,:] # create the fourier kernel kern=np.exp((-1j*2*np.pi)*freq*outinds) # the result is the dot product (sum along one axis) of the inverse fft of # the function and the kernel result = np.dot(ifftn(data),kern) if return_real: return result.real else: return result
def fourier_interpnd(data, outinds, nthreads=1, use_numpy_fft=False, return_real=True): """ Use the fourier scaling theorem to interpolate (or extrapolate, without raising any exceptions) data. * DOES NOT WORK FOR ANY BUT 2 DIMENSIONS * Parameters ---------- data : ndarray The data values of the array to interpolate outinds : ndarray The coordinate axis values along which the data should be interpolated CAN BE: ndim x [n,m,...] like np.indices OR (less memory intensive, more processor intensive): ([n],[m],...) """ # load fft fftn,ifftn = fast_ffts.get_ffts(nthreads=nthreads, use_numpy_fft=use_numpy_fft) if hasattr(outinds,'ndim') and outinds.ndim not in (data.ndim+1,data.ndim): raise ValueError("Must specify an array of output indices with # of dimensions = input # of dims + 1") elif len(outinds) != data.ndim: raise ValueError("outind array must have an axis for each dimension") imfft = ifftn(data) result = imfft for dim,dimsize in enumerate(data.shape): # specify fourier frequencies freq = np.fft.fftfreq(dimsize) # have to cleverly specify frequency dimensions for the dot # frequency is the axis that will get summed over freqdims = [None]*(dim) + [slice(None)] + [None]*(data.ndim-1-dim) inddims = [None]*(data.ndim-1-dim) + [slice(None)] + [None]*(dim) # create the fourier kernel if hasattr(outinds,'ndim') and outinds.ndim == data.ndim+1: # if outinds = np.indices(shape), we extract just lines along each index outslice = [dim] + [0]*dim + [slice(None)] + [0]*(data.ndim-1-dim) inds = freq[freqdims]*outinds[outslice][inddims] # un-pythonic? elif hasattr(outinds[dim],'ndim') and outinds[dim].ndim == 1: else: inds = freq[freqdims]*np.array(outinds[dim])[inddims] kern=np.exp((-1j*2*np.pi)*inds) # the result is the dot product (sum along one axis) of the inverse fft of # the function and the kernel # first time: dim = 0 ndim-1-dim = 1 # second time: dim = 1 ndim-1-dim = 0 result = np.dot(result.swapaxes(dim,-1),kern.swapaxes(data.ndim-1-dim,-1)).swapaxes(dim,-1) if return_real: return result.real else: return result