def test_radon2d_adjointness(self):
        # Set image size.
        m, n = 39, 23

        # Define angles.
        angles = np.linspace(0, np.pi, 180, False)

        # Create operators.
        K, Kadj, ndet = radon.radon2d(m, n, angles)

        # Apply to dummy image.
        f = K(np.ones((m, n)))
        np.testing.assert_allclose(f.shape[0], angles.size)

        # Apply to dummy data.
        f = Kadj(np.ones_like(f))
        np.testing.assert_allclose(f.shape, (m, n))

        # Create random matrix.
        x = np.random.rand(m, n)
        p, q = K(x).shape

        # Create second random matrix.
        y = np.random.rand(p, q)

        # Check adjointness up to certain relative tolerance.
        np.testing.assert_allclose(np.dot(K(x).flatten(), y.flatten()),
                                   np.dot(x.flatten(),
                                          Kadj(y).flatten()), 1e-3)
    def test_radon2d_plot(self):

        img = Image.open('data/phantom.png').convert('L')
        img = np.array(img)

        # Set image size.
        m, n = img.shape

        # Define angles.
        angles = np.linspace(0, np.pi, 180, False)

        # Create operators.
        K, Kadj, ndet = radon.radon2d(m, n, angles)

        # Plot original image.
        plt.imshow(img, cmap='gray')
        plt.colorbar()
        plt.show()

        # Apply to dummy image.
        f = K(img)

        # Plot data.
        plt.imshow(f, cmap='gray')
        plt.colorbar()
        plt.show()

        # Apply to dummy data.
        f = Kadj(f)

        # Plot result of backprojection.
        plt.imshow(f, cmap='gray')
        plt.colorbar()
        plt.show()
    def test_radon2d_operators_cuda(self):
        # Define image size.
        image_size = (31, 23)

        # Define angles.
        nangles = 180
        angles = np.linspace(0, np.pi, nangles, False)

        # Check if GPU is available.
        cuda = torch.cuda.is_available()
        device = torch.device('cuda') if cuda else 'cpu'

        # Create operators.
        R, Radj, ndet = radon.radon2d(*image_size, angles, cuda)
        data_size = (nangles, ndet)

        # Create instances for use with torch.
        K = radon.RadonTransform(R, Radj, data_size)
        Kadj = radon.BackProjection(R, Radj, image_size)

        # Create random matrix.
        x = torch.randn(1, 1, *image_size).to(device)

        # Create second random matrix.
        y = torch.randn(1, 1, *data_size).to(device)

        # Check adjointness up to certain relative tolerance.
        ip1 = torch.dot(K(x).flatten(), y.flatten())
        ip2 = torch.dot(x.flatten(), Kadj(y).flatten())
        torch.allclose(ip1, ip2)
    def test_LinearOperator_radon_gradcheck(self):
        # Set image size.
        image_size = (5, 4)

        # Define angles.
        nangles = 180
        angles = np.linspace(0, np.pi, nangles, False)

        # Create operators.
        R, Radj, ndet = radon.radon2d(*image_size, angles)
        data_size = (nangles, ndet)

        # Create instances for use with torch.
        K = radon.RadonTransform(R, Radj, data_size)
        Kadj = radon.BackProjection(R, Radj, image_size)

        # Apply to dummy input.
        x = torch.randn((1, 1, *image_size),
                        requires_grad=True,
                        dtype=torch.double)
        f = K(x)

        # Check for simple loss.
        loss = f.sum()
        loss.backward()
        torch.allclose(x.grad, Kadj(x.new_ones(1, 1, *data_size)))

        def op_fun(x):
            out = LinearOperator.apply(x, K, Kadj)
            return out.sum()

        # Check for anomalies.
        with tag.detect_anomaly():
            x = torch.randn(1,
                            1,
                            *image_size,
                            requires_grad=True,
                            dtype=torch.double)
            out = op_fun(x)
            out.backward()

        # Check numerical gradient up to certain tolerance.
        # Due to inaccuracy of adjoint this check fails.
        x = torch.randn(1,
                        1,
                        *image_size,
                        requires_grad=True,
                        dtype=torch.double)
        tag.gradcheck(lambda t: K(t), x)
    def test_radon2d(self):
        # Set image size.
        m, n = 39, 23

        # Define angles.
        angles = np.linspace(0, np.pi, 180, False)

        # Create operators.
        K, Kadj, ndet = radon.radon2d(m, n, angles)

        # Apply to dummy image.
        f = K(np.ones((m, n)))
        np.testing.assert_allclose(f.shape[0], angles.size)

        # Apply to dummy data.
        f = Kadj(np.ones_like(f))
        np.testing.assert_allclose(f.shape, (m, n))
    def test_LinearOperator_radon_cuda(self):
        # Set image size.
        image_size = 5, 4

        # Define angles.
        nangles = 180
        angles = np.linspace(0, np.pi, nangles, False)

        # Check if GPU is available.
        cuda = torch.cuda.is_available()
        device = torch.device('cuda' if cuda else 'cpu')

        # Create operators.
        R, Radj, ndet = radon.radon2d(*image_size, angles, cuda)
        data_size = (nangles, ndet)

        # Create instances for use with torch.
        K = radon.RadonTransform(R, Radj, data_size)
        Kadj = radon.BackProjection(R, Radj, image_size)

        # Apply to dummy input.
        x = torch.randn((1, 1, *image_size),
                        requires_grad=True,
                        dtype=torch.double,
                        device=device)
        f = K(x)

        # Check for simple loss.
        loss = f.sum()
        loss.backward()
        torch.allclose(x.grad, Kadj(x.new_ones(1, 1, *data_size)))

        def op_fun(x):
            out = LinearOperator.apply(x, K, Kadj)
            return out.sum()

        # Check for anomalies.
        with tag.detect_anomaly():
            x = torch.randn(1,
                            1,
                            *image_size,
                            requires_grad=True,
                            dtype=torch.double,
                            device=device)
            out = op_fun(x)
            out.backward()
def setup_reconstruction_problem(image_size: tuple):
    """Set up reconstruction problem using Radon transform."""
    # Define angles.
    nangles = 180
    angles = np.linspace(0, np.pi, nangles, False)

    # Define Radon transform and adjoint.
    R, Radj, ndet = radon.radon2d(*image_size, angles)
    data_size = (nangles, ndet)

    # Create instances for use with torch.
    K = radon.RadonTransform(R, Radj, data_size)
    Kadj = radon.BackProjection(R, Radj, image_size)

    # Create data fidelity and its gradient.
    G, gradG = functionals.OpSqNormDataTerm(K, Kadj)

    return K, Kadj, G, gradG, data_size
Ejemplo n.º 8
0
def setup_reconstruction_problem(f: np.array, sigma: float):
    """Set up reconstruction problem using Radon transform."""
    m, n = f.shape

    # Define angles.
    nangles = 180
    angles = np.linspace(0, np.pi, nangles, False)

    # Define Radon transform and adjoint.
    K, Kadj, ndet = radon.radon2d(m, n, angles)

    # Generate data and add noise.
    y = K(f)

    # Add noise.
    ydelta = y + sigma**2 * y.var() * y.max() * np.random.randn(*y.shape)

    # Define data fidelity and its gradient.
    G, gradG = functionals.OpSqNormDataTerm(K, Kadj, ydelta)

    return ydelta, G, gradG
def landweber():
    """Compute a solution by Landweber iteration."""
    # Load phantom image.
    f = np.asarray(Image.open('data/phantom.png').convert('L'),
                   dtype=np.double)
    f = f / np.max(f)
    m, n = f.shape

    # Define angles.
    angles = np.linspace(0, np.pi, 180, False)

    # Define Radon transform and adjoint.
    K, Kadj, ndet = radon.radon2d(m, n, angles)

    # Generate data and add noise.
    y = K(f)
    ydelta = y + 5 * np.random.randn(*y.shape)

    # Show image.
    plt.figure()
    plt.imshow(ydelta, cmap='gray')
    plt.colorbar()
    plt.show()

    # Initialise solution.
    x = np.zeros_like(f)

    # Define stepsize parameter.
    omega = 2e-5

    # Run Landweber iteration.
    nliter = 30
    for i in range(nliter):

        x = x - omega * Kadj(K(x) - ydelta)

        plt.figure()
        plt.imshow(x, cmap='gray')
        plt.colorbar()
        plt.show()