Example #1
0
    def downsample(self, ds_res):
        """
        Downsample Image to a specific resolution. This method returns a new Image.
        :param ds_res: int - new resolution, should be <= the current resolution of this Image
        :return: The downsampled Image object.
        """
        grid = grid_2d(self.res)
        grid_ds = grid_2d(ds_res)

        im_ds = np.zeros((ds_res, ds_res, self.n_images)).astype(self.dtype)

        # x, y values corresponding to 'grid'. This is what scipy interpolator needs to function.
        res_by_2 = self.res / 2
        x = y = np.ceil(np.arange(-res_by_2, res_by_2)) / res_by_2

        mask = (np.abs(grid['x']) < ds_res / self.res) & (np.abs(grid['y']) <
                                                          ds_res / self.res)
        im = np.real(
            centered_ifft2(centered_fft2(self.data) * np.expand_dims(mask, 2)))

        for s in range(im_ds.shape[-1]):
            interpolator = RegularGridInterpolator((x, y),
                                                   im[:, :, s],
                                                   bounds_error=False,
                                                   fill_value=0)
            im_ds[:, :,
                  s] = interpolator(np.dstack([grid_ds['x'], grid_ds['y']]))

        return Image(im_ds)
Example #2
0
def im_downsample(im, L_ds):
    """
    Blur and downsample image
    :param im: Set of images to be downsampled in the form of an array L-by-L-by-K, where K is the number of images.
    :param L_ds: The desired resolution of the downsampled images. Must be smaller than L.
    :return: An array of the form L_ds-by-L_ds-by-K consisting of the blurred and downsampled images.
    """
    N = im.shape[0]
    grid = grid_2d(N)
    grid_ds = grid_2d(L_ds)

    im_ds = np.zeros((L_ds, L_ds, im.shape[2])).astype(im.dtype)

    # x, y values corresponding to 'grid'. This is what scipy interpolator needs to function.
    x = y = np.ceil(np.arange(-N/2, N/2)) / (N/2)

    mask = (np.abs(grid['x']) < L_ds/N) & (np.abs(grid['y']) < L_ds/N)
    im = np.real(centered_ifft2(centered_fft2(im) * np.expand_dims(mask, 2)))

    for s in range(im_ds.shape[-1]):
        interpolator = RegularGridInterpolator(
            (x, y),
            im[:, :, s],
            bounds_error=False,
            fill_value=0
        )
        im_ds[:, :, s] = interpolator(np.dstack([grid_ds['x'], grid_ds['y']]))

    return im_ds
Example #3
0
def im_filter(im, filt, *args, **kwargs):
    # TODO: Move inside appropriate object
    L = im.shape[0]
    im, sz_roll = unroll_dim(im, 3)
    filter_vals = filt.evaluate_grid(L, *args, **kwargs)
    im_f = centered_fft2(im)
    if im_f.ndim > filter_vals.ndim:
        im_f = np.expand_dims(filter_vals, 2) * im_f
    else:
        im_f = filter_vals * im_f
    im = centered_ifft2(im_f)
    im = np.real(im)
    im = roll_dim(im, sz_roll)

    return im
Example #4
0
    def filter(self, filter):
        """
        Apply a `Filter` object to the Image. This method returns a new Image.
        :param filter: An object of type `Filter`.
        :return: A new filtered `Image` object.
        """
        filter_values = filter.evaluate_grid(self.res)

        im_f = centered_fft2(self.data)
        if im_f.ndim > filter_values.ndim:
            im_f = np.expand_dims(filter_values, 2) * im_f
        else:
            im_f = filter_values * im_f
        im = centered_ifft2(im_f)
        im = np.real(im)

        return Image(im)
Example #5
0
def vol_project(vol, rot_matrices):
    L = vol.shape[0]
    n = rot_matrices.shape[-1]
    pts_rot = rotated_grids(L, rot_matrices)

    # TODO: rotated_grids might as well give us correctly shaped array in the first place
    pts_rot = m_reshape(pts_rot, (3, L**2 * n))

    im_f = 1. / L * Plan(vol.shape, pts_rot).transform(vol)
    im_f = m_reshape(im_f, (L, L, -1))

    if L % 2 == 0:
        im_f[0, :, :] = 0
        im_f[:, 0, :] = 0

    im = centered_ifft2(im_f)

    return np.real(im)
Example #6
0
def downsample(insamples, szout):
    """
    Blur and downsample 1D to 3D objects such as, curves, images or volumes
    :param insamples: Set of objects to be downsampled in the form of an array, the last dimension
                    is the number of objects.
    :param szout: The desired resolution of for output objects.
    :return: An array consists of the blurred and downsampled objects.
    """

    ensure(
        insamples.ndim - 1 == szout.ndim,
        'The number of downsampling dimensions is not the same as that of objects.'
    )

    L_in = insamples.shape[0]
    L_out = szout.shape[0]
    ndata = insamples.shape(-1)
    outdims = szout
    outdims.push_back(ndata)
    outsamples = np.zeros((outdims)).astype(insamples.dtype)

    if insamples.ndim == 2:
        # one dimension object
        grid_in = grid_1d(L_in)
        grid_out = grid_1d(L_out)
        # x values corresponding to 'grid'. This is what scipy interpolator needs to function.
        x = np.ceil(np.arange(-L_in / 2, L_in / 2)) / (L_in / 2)
        mask = (np.abs(grid_in['x']) < L_out / L_in)
        insamples_fft = np.real(
            centered_ifft1(centered_fft1(insamples) * np.expand_dims(mask, 1)))
        for idata in range(ndata):
            interpolator = RegularGridInterpolator((x, ),
                                                   insamples_fft[:, idata],
                                                   bounds_error=False,
                                                   fill_value=0)
            outsamples[:, :, idata] = interpolator(np.dstack([grid_out['x']]))

    elif insamples.ndim == 3:
        grid_in = grid_2d(L_in)
        grid_out = grid_2d(L_out)
        # x, y values corresponding to 'grid'. This is what scipy interpolator needs to function.
        x = y = np.ceil(np.arange(-L_in / 2, L_in / 2)) / (L_in / 2)
        mask = (np.abs(grid_in['x']) < L_out / L_in) & (np.abs(grid_in['y']) <
                                                        L_out / L_in)
        insamples_fft = np.real(
            centered_ifft2(centered_fft2(insamples) * np.expand_dims(mask, 2)))
        for idata in range(ndata):
            interpolator = RegularGridInterpolator((x, y),
                                                   insamples_fft[:, :, idata],
                                                   bounds_error=False,
                                                   fill_value=0)
            outsamples[:, :, idata] = interpolator(
                np.dstack([grid_out['x'], grid_out['y']]))

    elif insamples.ndim == 4:
        grid_in = grid_3d(L_in)
        grid_out = grid_3d(L_out)
        # x, y, z values corresponding to 'grid'. This is what scipy interpolator needs to function.
        x = y = z = np.ceil(np.arange(-L_in / 2, L_in / 2)) / (L_in / 2)
        mask = (np.abs(grid_in['x']) < L_out / L_in) & (np.abs(
            grid_in['y']) < L_out / L_in) & (np.abs(grid_in['z']) <
                                             L_out / L_in)
        insamples_fft = np.real(
            centered_ifft3(centered_fft3(insamples) * np.expand_dims(mask, 3)))
        for idata in range(ndata):
            interpolator = RegularGridInterpolator((x, y, z),
                                                   insamples_fft[:, :, :,
                                                                 idata],
                                                   bounds_error=False,
                                                   fill_value=0)
            outsamples[:, :, :, idata] = interpolator(
                np.dstack([grid_out['x'], grid_out['y'], grid_out['z']]))

    return outsamples
Example #7
0
def vol2img(volume, rots, L=None, dtype=None):
    """
    Generate 2D images from the input volume and rotation angles

    The function handles odd and even-sized arrays correctly. The center of
    an odd array is taken to be at (n+1)/2, and an even array is n/2+1.
    :param volume: A 3D volume objects.
    :param rots: A n-by-3-by-3 array of rotation angles.
    :param L: The output size of 2D images.
    :return: An array consists of 2D images.
    """

    if L is None:
        L = np.size(volume, 0)
    if dtype is None:
        dtype = volume.dtype

    lv = np.size(volume, 0)
    if L > lv + 1:
        # For compatibility with gen_projections, allow one pixel aliasing.
        # More precisely, it should be N>nv, however, by using nv+1 the
        # results match those of gen_projections.
        if np.mod(L - lv, 2) == 1:
            raise RuntimeError(
                'Upsampling from odd to even sizes or vice versa is '
                'currently not supported')
        dL = np.floor((L - lv) / 2)
        fv = centered_fft3(volume)
        padded_volume = np.zeros((L, L, L), dtype=dtype)
        padded_volume[dL + 1:dL + lv + 1, dL + 1:dL + lv + 1,
                      dL + 1:dL + lv + 1] = fv
        volume = centered_ifft3(padded_volume)
        ensure(
            np.norm(np.imag(volume[:])) / np.norm(volume[:]) < 1.0e-5,
            "The image part of volume is related large (>1.0e-5).")
        #  The new volume size
        lv = L

    grid2d = grid_2d(lv, shifted=True, normalized=False)

    num_pts = lv**2
    num_rots = rots.shape[0]
    pts = np.pi * np.vstack([
        grid2d['x'].flatten('F'), grid2d['y'].flatten('F'),
        np.zeros(num_pts)
    ])

    pts_rot = np.zeros((3, num_pts, num_rots))

    for i in range(num_rots):
        pts_rot[:, :, i] = rots[i, :, :].T @ pts

    pts_rot = m_reshape(pts_rot, (3, lv**2 * num_rots))

    pts_rot = -2 * pts_rot / lv

    im_f = Plan(volume.shape, -pts_rot).transform(volume)

    im_f = m_reshape(im_f, (lv, lv, -1))

    if lv % 2 == 0:
        pts_rot = m_reshape(pts_rot, (3, lv, lv, num_rots))
        im_f = im_f * np.exp(1j * np.sum(pts_rot, 0) / 2)
        im_f = im_f * np.expand_dims(
            np.exp(2 * np.pi * 1j * (grid2d['x'] + grid2d['y'] - 1) /
                   (2 * lv)), 2)

    im = centered_ifft2(im_f)
    if lv % 2 == 0:
        im = im * m_reshape(
            np.exp(2 * np.pi * 1j * (grid2d['x'] + grid2d['y']) / (2 * lv)),
            (lv, lv, 1))

    return np.real(im)