.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/basics/demo_physics.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_basics_demo_physics.py: Creating a forward operator. ==================================================================================================== While deepinv offers a large number of forward operators in the physics module, you might want to create your own forward operator for your specific imaging problem. This example walks you through the creation of a custom forward operator. We will create a simple forward operator that converts RGB images to grayscale images by averaging the color channels. We also show you how to exploit the singular value decomposition of the operator to speed up the evaluation of the pseudo-inverse and proximal operators. .. GENERATED FROM PYTHON SOURCE LINES 14-18 .. code-block:: Python import deepinv as dinv import torch .. GENERATED FROM PYTHON SOURCE LINES 19-27 Creating a custom forward operator. ---------------------------------------------------------------------------------------- Defining a new linear operator only requires a forward function and its transpose operation, inheriting the remaining structure of the :class:`deepinv.physics.LinearPhysics` class. Once the operator is defined, we can use any of the functions in the :class:`deepinv.physics.Physics` class and :class:`deepinv.physics.LinearPhysics` class, such as computing the norm of the operator, testing the adjointness, computing the proximal operator, etc. .. GENERATED FROM PYTHON SOURCE LINES 27-53 .. code-block:: Python # define an operator that converts color images into grayscale ones. class Decolorize(dinv.physics.LinearPhysics): r""" Converts RGB images to grayscale. Signals must be tensors with 3 colour (RGB) channels, i.e. [*,3,*,*] The measurements are grayscale images. """ def __init__(self, **kwargs): super().__init__(**kwargs) self.noise_model = dinv.physics.GaussianNoise(sigma=0.1) def A(self, x, theta=None): # theta is an optional parameter that is not used here y = x[:, 0, :, :] * 0.2989 + x[:, 1, :, :] * 0.5870 + x[:, 2, :, :] * 0.1140 return y.unsqueeze(1) def A_adjoint(self, y, theta=None): return torch.cat([y * 0.2989, y * 0.5870, y * 0.1140], dim=1) physics = Decolorize() .. GENERATED FROM PYTHON SOURCE LINES 54-58 Generate toy image -------------------------------------------------------------------- This example uses a toy image with 3 color channels. .. GENERATED FROM PYTHON SOURCE LINES 58-71 .. code-block:: Python x = torch.zeros(1, 3, 96, 128) x[:, 0, :32, :] = 1 x[:, 1, 32:64, :] = 1 x[:, 2, 64:, :] = 1 y = physics(x) xlin = physics.A_dagger(y) # compute the linear pseudo-inverse dinv.utils.plot([x, y, xlin], titles=["image", "meas.", "linear rec."]) .. image-sg:: /auto_examples/basics/images/sphx_glr_demo_physics_001.png :alt: image, meas., linear rec. :srcset: /auto_examples/basics/images/sphx_glr_demo_physics_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 72-78 Verifying our linear operator -------------------------------------------- If the operator is linear, it is recommended to verify that the transpose well-defined using :func:`deepinv.physics.LinearPhysics.adjointness_test`, and that it has a unit norm using :func:`deepinv.physics.LinearPhysics.compute_norm`. .. GENERATED FROM PYTHON SOURCE LINES 78-85 .. code-block:: Python print(f"The linear operator has norm={physics.compute_norm(x):.2f}") if physics.adjointness_test(x) < 1e-5: print("The linear operator has a well defined transpose") .. rst-class:: sphx-glr-script-out .. code-block:: none Power iteration converged at iteration 2, value=0.45 The linear operator has norm=0.45 The linear operator has a well defined transpose .. GENERATED FROM PYTHON SOURCE LINES 86-93 Creating a decomposable forward operator. -------------------------------------------- If the forward operator has a closed form singular value decomposition (SVD), it is recommended to implement the operator using the :class:`deepinv.physics.DecomposablePhysics` method. The operator in this example is decomposable, so we can implement it using :class:`deepinv.physics.DecomposablePhysics`. .. GENERATED FROM PYTHON SOURCE LINES 93-129 .. code-block:: Python class DecolorizeSVD(dinv.physics.DecomposablePhysics): r""" Converts RGB images to grayscale. Signals must be tensors with 3 colour (RGB) channels, i.e. [*,3,*,*] The measurements are grayscale images. """ def __init__(self, **kwargs): super().__init__(mask=0.447, **kwargs) self.noise_model = dinv.physics.GaussianNoise(sigma=0.1) def V_adjoint(self, x): y = x[:, 0, :, :] * 0.6687 + x[:, 1, :, :] * 1.3132 + x[:, 2, :, :] * 0.2550 return y.unsqueeze(1) def V(self, y): return torch.cat([y * 0.6687, y * 1.3132, y * 0.2550], dim=1) physics2 = DecolorizeSVD() y2 = physics2(x) xlin2 = physics.A_dagger(y2) # compute the linear pseudo-inverse dinv.utils.plot([x, y2, xlin2], titles=["image", "meas.", "linear rec."]) print(f"The decomposable operator has norm={physics.compute_norm(x):.2f}") if physics.adjointness_test(x) < 1e-5: print("The decomposable operator has a well defined transpose") .. image-sg:: /auto_examples/basics/images/sphx_glr_demo_physics_002.png :alt: image, meas., linear rec. :srcset: /auto_examples/basics/images/sphx_glr_demo_physics_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Power iteration converged at iteration 2, value=0.45 The decomposable operator has norm=0.45 The decomposable operator has a well defined transpose .. GENERATED FROM PYTHON SOURCE LINES 130-141 Benefits of using a decomposable forward operator. ---------------------------------------------------------------------------------------- If the forward operator has a closed form singular value decomposition (SVD), it is recommended to implement the operator using :class:`deepinv.physics.DecomposablePhysics`. The operator in this example is decomposable, so we can implement it using :class:`deepinv.physics.DecomposablePhysics`. The main benefit of using a decomposable forward operator is that it provides closed form solutions for the proximal operator and the linear pseudo-inverse. Moreover, some algorithms, such as :class:`deepinv.sampling.DDRM` require the forward operator to be decomposable. .. GENERATED FROM PYTHON SOURCE LINES 141-159 .. code-block:: Python import time start = time.time() for i in range(10): xlin = physics.A_dagger(y) xprox = physics.prox_l2(x, y, 0.1) end = time.time() print(f"Elapsed time for LinearPhysics: {end - start:.2f} seconds") start = time.time() for i in range(10): xlin2 = physics2.A_dagger(y) xprox2 = physics2.prox_l2(x, y2, 0.1) end = time.time() print(f"Elapsed time for DecomposablePhysics: {end - start:.2e} seconds") .. rst-class:: sphx-glr-script-out .. code-block:: none Elapsed time for LinearPhysics: 0.01 seconds Elapsed time for DecomposablePhysics: 2.76e-03 seconds .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.147 seconds) .. _sphx_glr_download_auto_examples_basics_demo_physics.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: demo_physics.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: demo_physics.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: demo_physics.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_