Exemplo n.º 1
0
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)
Exemplo n.º 2
0
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
Exemplo n.º 3
0
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
Exemplo n.º 4
0
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
Exemplo n.º 5
0
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
Exemplo n.º 6
0
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)
Exemplo n.º 7
0
Arquivo: shift.py Projeto: Fade89/agpy
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
Exemplo n.º 8
0
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
Exemplo n.º 9
0
    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")
Exemplo n.º 10
0
    # 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
Exemplo n.º 11
0
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
Exemplo n.º 12
0
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
Exemplo n.º 13
0
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