コード例 #1
0
ファイル: test_splradon.py プロジェクト: idiap/cbi_toolbox
    def test_dimension(self):
        image_dim = (50, 50, 3)
        image_3d = np.random.default_rng().random(image_dim)
        image_2d = np.copy(image_3d[..., 0])

        spline_3d = spl.radon(image_3d)
        spline_2d = spl.radon(image_2d)

        np.testing.assert_allclose(
            spline_2d, spline_3d[..., 0], rtol=1e-12, atol=1e-12)

        out_3d = spl.iradon(image_3d)
        out_2d = spl.iradon(image_2d)

        np.testing.assert_allclose(
            out_2d, out_3d[..., 0], rtol=1e-12, atol=1e-12)
コード例 #2
0
ファイル: test_splradon.py プロジェクト: idiap/cbi_toolbox
    def test_contiguous(self):
        image_dim = (50, 50, 3)
        image_3d = np.random.default_rng().random(image_dim)

        image_3d = np.transpose(image_3d, (1, 0, 2))
        image_2d = np.copy(image_3d[..., 0])

        spline_3d = spl.radon(image_3d)
        spline_2d = spl.radon(image_2d)

        np.testing.assert_allclose(
            spline_2d, spline_3d[..., 0], rtol=1e-9, atol=1e-12)

        out_3d = spl.iradon(spline_3d)
        out_2d = spl.iradon(spline_2d)

        np.testing.assert_allclose(
            out_2d, out_3d[..., 0], rtol=1e-9, atol=1e-12)
コード例 #3
0
ファイル: test_splradon.py プロジェクト: idiap/cbi_toolbox
    def test_padding(self):
        theta = np.arange(10)
        for size in range(5, 25):
            shape = (size, size)
            image = np.random.default_rng().random(shape)

            for circle in (True, False):
                rd = spl.radon(image, theta, circle=circle,
                               b_spline_deg=(0, 0))
                ird = spl.iradon(rd, theta, circle=circle, b_spline_deg=(0, 0))

                np.testing.assert_array_equal(shape, ird.shape)
コード例 #4
0
ファイル: test_deconv.py プロジェクト: idiap/cbi_toolbox
    def test_deconv(self):
        size = 100
        sample = primitives.boccia(size, radius=(0.5 * size) // 2, n_stripes=4)
        theta = np.arange(90)

        radon = spl.radon(sample, theta=theta, circle=True)

        for psf in self.psfs:
            s_fpsopt = imaging.fps_opt(sample, psf, theta=theta)
            decon = fpsopt.deconvolve_sinogram(s_fpsopt, psf, l=1e-12)
            snr = psnr(radon, decon)

            self.assertGreater(snr, 60)
コード例 #5
0
ファイル: imaging.py プロジェクト: idiap/cbi_toolbox
def fps_opt(obj, psf, pad=False, **kwargs):
    """
    Simulate the FPS-OPT (focal plane scanning) imaging of an object

    Parameters
    ----------
    obj : array [ZXY]
        the object to be imaged
    psf : array [ZXY] or array [XY]
        the PSF of the system, or projected PSF along the Z axis
    pad : bool, optional
        pad the vield of view to see all contributions
        (required if the sample is not contained in the inner cylinder of the object),
        by default False

    **kwargs :
        to be passed to the radon call

    Returns
    -------
    array [TPY]
        the imaged sinogram

    Raises
    ------
    ValueError
        if the PSF is not 2D or 3D
    """

    if psf.ndim == 3:
        psf = psf.sum(0, keepdims=True)
    elif psf.ndim == 2:
        psf = psf[None, ...]
    else:
        raise ValueError("Invalid dimensions for PSF: {}".format(psf.ndim))

    sinogram = spl.radon(obj, circle=(not pad), **kwargs)

    mode = 'full' if pad else 'same'

    image = sig.fftconvolve(sinogram, psf, axes=(1, 2), mode=mode)
    return image
コード例 #6
0
    TEST_SIZE = 64

    s_psf = optics.gaussian_psf(numerical_aperture=0.3,
                                npix_axial=TEST_SIZE + 1,
                                npix_lateral=TEST_SIZE + 1)

    i_psf = inverse_psf_rfft(s_psf, l=1e-15, mode='constant')
    psfft = fft.rfft2(s_psf.sum(0))
    dirac = fft.irfft2(psfft * i_psf, s=s_psf.shape[1:])

    sample = primitives.boccia(TEST_SIZE,
                               radius=(0.8 * TEST_SIZE) // 2,
                               n_stripes=4)
    s_theta = np.arange(90)

    s_radon = spl.radon(sample, theta=s_theta, circle=True)
    s_fpsopt = imaging.fps_opt(sample, s_psf, theta=s_theta)

    s_deconv = deconvolve_sinogram(s_fpsopt, s_psf, l=0)

    viewer = napari.view_image(s_radon)
    viewer.add_image(s_fpsopt)
    viewer.add_image(s_deconv)

    viewer = napari.view_image(fft.fftshift(np.abs(i_psf), 0),
                               name='inverse PSF FFT')
    viewer.add_image(dirac)

    napari.run()
コード例 #7
0
# This file is part of CBI Toolbox.
#
# CBI Toolbox is free software: you can redistribute it and/or modify
# it under the terms of the 3-Clause BSD License.
#
# CBI Toolbox is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# 3-Clause BSD License for more details.
#
# You should have received a copy of the 3-Clause BSD License along
# with CBI Toolbox. If not, see https://opensource.org/licenses/BSD-3-Clause.
#
# SPDX-License-Identifier: BSD-3-Clause

import os
import numpy as np
import cbi_toolbox.splineradon as spl

path = os.environ['OVC_PATH']

ipath = os.path.join(path, 'imaging')

phantom = np.load(os.path.join(path, 'arrays', 'phantom.npy'))

theta = np.linspace(0, 180, 360, endpoint=False)

radon = spl.radon(phantom, theta=theta, circle=True)
np.save(os.path.join(ipath, 'radon.npy'), radon)
print('Saved Radon')
コード例 #8
0
ファイル: splineradon.py プロジェクト: idiap/cbi_toolbox
image = np.zeros((71, 71, 3))
image[2, 2, 0] = 1
image[50, 50, 0] = 1
image[10, 50, 1] = 1
image[60, 20, 1] = 1
image[30, 60, 2] = 1
image[30, 20, 2] = 1
image[35, 35, :] = 1

use_cuda = spl.is_cuda_available()
if use_cuda:
    print('Running with GPU acceleration')
else:
    print('Running on CPU')

sinogram = spl.radon(image, use_cuda=use_cuda)

reconstruct = spl.iradon(sinogram, use_cuda=use_cuda)

reconstruct -= reconstruct.min()
reconstruct /= reconstruct.max()

sinogram[sinogram < 0] = 0
sinogram /= sinogram.max()

plt.figure()
plt.subplot(131)
plt.imshow(image)
plt.subplot(132)
plt.imshow(sinogram)
plt.subplot(133)
コード例 #9
0
ファイル: imaging.py プロジェクト: idiap/cbi_toolbox
def fss_opt(obj, psf, illu, pad=False, **kwargs):
    """
    Simulate the FSS-OPT (focal sheet scanning) imaging of an object

    Parameters
    ----------
    obj : array [ZXY]
        the object to be imaged
    psf : array [ZXY] or array [XY]
        the PSF of the system
    illu : array [ZXY]
        the illumination function of the SPIM
    pad : bool, optional
        pad the vield of view to see all contributions
        if used, illu will be required to be bigger
        (required if the sample is not contained in the inner cylinder of the object),
        by default False

    **kwargs :
        to be passed to the radon call

    Returns
    -------
    array [TPY]
        the imaged sinogram

    Raises
    ------
    ValueError
        if the PSF dimensions do not fit the illumination
        if the illumination function has an incorrect shape
    """

    if pad:
        # TODO use bigger SPIM illumination function to fit padded sinogram
        raise NotImplementedError()

    if psf.shape[0] % 2 != illu.shape[0] % 2:
        raise ValueError(
            'In order to correctly center the illumination on the PSF,'
            ' please profide a PSF with the same Z axis parity'
            'as the illumination Z axis')

    if not (psf.shape[1] % 2 and psf.shape[2] % 2):
        raise ValueError(
            'In order to correctly center the PSF on the pixels,'
            ' please provide a PSF with odd parity on X and Y axis')

    crop = (psf.shape[0] - illu.shape[0]) // 2
    if crop:
        psf = psf[crop:-crop, ...]
    psf = np.flip(psf)

    sinogram = spl.radon(obj, circle=(not pad), **kwargs)

    psf_xw = psf.shape[1]
    psf_yw = psf.shape[2]
    pad_x = psf_xw // 2
    pad_y = psf_yw // 2

    illu = np.pad(illu, ((0, ), (pad_x, ), (pad_y, )))

    image = np.zeros((sinogram.shape[0], sinogram.shape[1] + psf_xw - 1,
                      sinogram.shape[2] + psf_yw - 1),
                     dtype=sinogram.dtype)

    for x in range(sinogram.shape[1]):
        for y in range(sinogram.shape[2]):
            local = np.sum(illu[:, x:x + psf_xw, y:y + psf_yw] * psf, 0)
            pixel = sinogram[:, x, y]
            spread = pixel[:, None, None] * local[None, ...]

            image[:, x:x + psf_xw, y:y + psf_xw] += spread

    if not pad:
        image = image[:, pad_x:-pad_x, pad_y:-pad_y]

    return image