Esempio n. 1
0
def skimage_radon_forward_projector(volume, geometry, proj_space, out=None):
    """Calculate forward projection using skimage.

    Parameters
    ----------
    volume : `DiscreteLpElement`
        The volume to project.
    geometry : `Geometry`
        The projection geometry to use.
    proj_space : `DiscreteLp`
        Space in which the projections (sinograms) live.
    out : ``proj_space`` element, optional
        Element to which the result should be written.

    Returns
    -------
    sinogram : ``proj_space`` element
        Result of the forward projection. If ``out`` was given, the returned
        object is a reference to it.
    """
    # Lazy import due to significant import time
    from skimage.transform import radon

    # Check basic requirements. Fully checking should be in wrapper
    assert volume.shape[0] == volume.shape[1]

    theta = np.degrees(geometry.angles)
    skimage_range = skimage_proj_space(geometry, volume.space, proj_space)

    # Rotate volume from (x, y) to (rows, cols), then project
    sino_arr = radon(
        np.rot90(volume.asarray(), 1), theta=theta, circle=False
    )
    sinogram = skimage_range.element(sino_arr.T)

    if out is None:
        out = proj_space.element()

    with writable_array(out) as out_arr:
        point_collocation(
            clamped_interpolation(skimage_range, sinogram),
            proj_space.grid.meshgrid,
            out=out_arr,
        )

    scale = volume.space.cell_sides[0]
    out *= scale

    return out
Esempio n. 2
0
    def _call(self, x, out=None):
        """Apply resampling operator.

        The element ``x`` is resampled using the sampling and interpolation
        operators of the underlying spaces.
        """
        interpolator = per_axis_interpolator(x, self.domain.grid.coord_vectors,
                                             self.interp)

        context = none_context if out is None else writable_array
        with context(out) as out_arr:
            return point_collocation(interpolator,
                                     self.range.meshgrid,
                                     out=out_arr)
Esempio n. 3
0
def test_collocation_interpolation_identity():
    """Check if collocation is left-inverse to interpolation."""
    # Interpolation followed by collocation on the same grid should be
    # the identity
    coord_vecs = [[0.125, 0.375, 0.625, 0.875], [0.25, 0.75]]
    f = np.array([[1, 2], [3, 4], [5, 6], [7, 8]], dtype='float64')
    interpolators = [
        nearest_interpolator(f, coord_vecs),
        linear_interpolator(f, coord_vecs),
        per_axis_interpolator(f, coord_vecs, interp=['linear', 'nearest']),
    ]

    for interpolator in interpolators:
        mg = sparse_meshgrid(*coord_vecs)
        ident_f = point_collocation(interpolator, mg)
        assert all_almost_equal(ident_f, f)
Esempio n. 4
0
def skimage_radon_back_projector(sinogram, geometry, vol_space, out=None):
    """Calculate forward projection using skimage.

    Parameters
    ----------
    sinogram : `DiscreteLpElement`
        Sinogram (projections) to backproject.
    geometry : `Geometry`
        The projection geometry to use.
    vol_space : `DiscreteLp`
        Space in which reconstructed volumes live.
    out : ``vol_space`` element, optional
        An element to which the result should be written.

    Returns
    -------
    volume : ``vol_space`` element
        Result of the back-projection. If ``out`` was given, the returned
        object is a reference to it.
    """
    # Lazy import due to significant import time
    from skimage.transform import iradon

    theta = np.degrees(geometry.angles)
    skimage_range = skimage_proj_space(geometry, vol_space, sinogram.space)

    skimage_sinogram = skimage_range.element()
    with writable_array(skimage_sinogram) as sino_arr:
        point_collocation(
            clamped_interpolation(sinogram.space, sinogram),
            skimage_range.grid.meshgrid,
            out=sino_arr,
        )

    if out is None:
        out = vol_space.element()
    else:
        # Only do asserts here since these are backend functions
        assert out in vol_space

    # Rotate back from (rows, cols) to (x, y), then back-project (no filter)
    backproj = iradon(
        skimage_sinogram.asarray().T,
        theta,
        output_size=vol_space.shape[0],
        filter=None,
        circle=False,
    )
    out[:] = np.rot90(backproj, -1)

    # Empirically determined value, gives correct scaling
    scaling_factor = 4 * geometry.motion_params.length / (2 * np.pi)

    # Correct in case of non-weighted spaces
    proj_volume = np.prod(sinogram.space.partition.extent)
    proj_size = sinogram.space.partition.size
    proj_weighting = proj_volume / proj_size

    scaling_factor *= sinogram.space.weighting.const / proj_weighting
    scaling_factor /= vol_space.weighting.const / vol_space.cell_volume

    # Correctly scale the output
    out *= scaling_factor

    return out