Esempio n. 1
0
def im_backproject(im, rot_matrices):
    """
    Backproject images along rotation
    :param im: An L-by-L-by-n array of images to backproject.
    :param rot_matrices: An 3-by-3-by-n array of rotation matrices corresponding to viewing directions.
    :return: An L-by-L-by-L volumes corresponding to the sum of the backprojected images.
    """
    L, _, n = im.shape
    ensure(L == im.shape[1], "im must be LxLxK")
    ensure(n == rot_matrices.shape[2],
           "No. of rotation matrices must match the number of images")

    pts_rot = rotated_grids(L, rot_matrices)
    pts_rot = m_reshape(pts_rot, (3, -1))

    im_f = centered_fft2(im) / (L**2)
    if L % 2 == 0:
        im_f[0, :, :] = 0
        im_f[:, 0, :] = 0
    im_f = m_flatten(im_f)

    plan = Plan(sz=(L, L, L), fourier_pts=pts_rot)
    vol = np.real(plan.adjoint(im_f)) / L

    return vol
Esempio n. 2
0
    def testTransform2(self):
        if not backend_available('pynfft'):
            raise SkipTest

        vol = np.load(os.path.join(DATA_DIR, 'nfft_volume.npy'))
        fourier_pts = np.array([
            [ 0.88952655922411,  0.35922344760724, -0.17107966400962, -0.70138277562649],
            [ 1.87089316522016,  1.99362869011803,  2.11636421501590,  2.23909973991377],
            [-3.93035749861843, -3.36417300942290, -2.79798852022738, -2.23180403103185]
        ])

        plan = Plan(vol.shape, fourier_pts, backend='pynfft')
        result = plan.transform(vol)

        self.assertTrue(np.allclose(
            result,
            [-0.05646675 + 1.503746j, 1.677600 + 0.6610926j, 0.9124417 - 0.7394574j, -0.9136836 - 0.5491410j]
        ))
Esempio n. 3
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)
Esempio n. 4
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)