.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/registration/plot_lddmm_1_normalization.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_registration_plot_lddmm_1_normalization.py: LDDMM with normalized kernel ============================ This notebook illustrates the interest of normalizing the cometric in the LDDMM model. We consider the registration of two spheres that differ by a translation first, and then a more complex registration task with a translation and a deformation. Without normalization, the carpooling artifact occurs: the sphere is contracted, then translated and finally expanded. in this situation, event if the morphed shape matches the target, the intermediate shapes are not meaningful and the extrapolation is not reliable. Normalizing the kernel adds regularization to the morphing, leanding to prevention of the carpooling artifact and improvement of the extrapolation to some extent. Options for normalization are: * "rows": normalize the rows of the kernel * "columns": normalize the columns of the kernel * "both": normalize both the rows and the columns of the kernel (for quare kernels, algorithm 5.7 in https://www.jeanfeydy.com/geometric_data_analysis.pdf) Further explanation can be found in the p177 and onwards of https://www.jeanfeydy.com/geometric_data_analysis.pdf. .. GENERATED FROM PYTHON SOURCE LINES 26-36 .. code-block:: Python from time import time import pyvista as pv import torch import skshapes as sks # sphinx_gallery_thumbnail_number = 9 .. GENERATED FROM PYTHON SOURCE LINES 37-38 Load data .. GENERATED FROM PYTHON SOURCE LINES 38-68 .. code-block:: Python plot_kwargs = { "smooth_shading": True, "pbr": True, "metallic": 0.7, "roughness": 0.6, } cpos = [ (1.6256104086078755, -9.701422233882411, 1.3012755902068773), (1.191160019984921, 0.01901107976782581, -0.0052552929581526076), (0.006053690112347382, 0.13347614338229413, 0.9910335372649167), ] source = sks.Sphere() target = sks.Sphere() decimation = sks.Decimation(n_points=200) source = decimation.fit_transform(source) target = decimation.transform(target) target.points = target.points + torch.tensor([2, 0.0, 0.0]) plotter = pv.Plotter() plotter.add_mesh(source.to_pyvista(), color="teal", opacity=0.8, **plot_kwargs) plotter.add_mesh(target.to_pyvista(), color="red", opacity=0.8, **plot_kwargs) plotter.camera_position = cpos plotter.show() .. tab-set:: .. tab-item:: Static Scene .. image-sg:: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_001.png :alt: plot lddmm 1 normalization :srcset: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_001.png :class: sphx-glr-single-img .. tab-item:: Interactive Scene .. offlineviewer:: /home/runner/work/scikit-shapes/scikit-shapes/doc/source/auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_001.vtksz .. GENERATED FROM PYTHON SOURCE LINES 69-71 LDDM without normalization -------------------------- .. GENERATED FROM PYTHON SOURCE LINES 71-105 .. code-block:: Python model = sks.ExtrinsicDeformation( n_steps=4, kernel="gaussian", scale=0.3, ) loss = sks.L2Loss() task = sks.Registration( model=model, loss=loss, optimizer=sks.LBFGS(), n_iter=3, regularization_weight=1e-1, verbose=True, ) start = time() task.fit(source=source, target=target) print("Elapsed time: ", time() - start) path = task.path_ plotter = pv.Plotter() plotter.add_mesh(source.to_pyvista(), color="teal", opacity=0.2, **plot_kwargs) plotter.add_mesh(target.to_pyvista(), color="red", opacity=0.2, **plot_kwargs) for i in range(len(path)): plotter.add_mesh( path[i].to_pyvista(), color="tan", opacity=0.8, **plot_kwargs ) plotter.camera_position = cpos plotter.show() .. tab-set:: .. tab-item:: Static Scene .. image-sg:: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_002.png :alt: plot lddmm 1 normalization :srcset: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_002.png :class: sphx-glr-single-img .. tab-item:: Interactive Scene .. offlineviewer:: /home/runner/work/scikit-shapes/scikit-shapes/doc/source/auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_002.vtksz .. rst-class:: sphx-glr-script-out .. code-block:: none Initial loss : 8.04e+02 = 8.04e+02 + 0.1 * 0.00e+00 (fidelity + regularization_weight * regularization) Loss after 1 iteration(s) : 1.84e+00 = 1.42e+00 + 0.1 * 4.16e+00 (fidelity + regularization_weight * regularization) Loss after 2 iteration(s) : 5.25e-01 = 1.21e-01 + 0.1 * 4.04e+00 (fidelity + regularization_weight * regularization) Loss after 3 iteration(s) : 4.40e-01 = 3.99e-02 + 0.1 * 4.00e+00 (fidelity + regularization_weight * regularization) Elapsed time: 69.92670607566833 .. GENERATED FROM PYTHON SOURCE LINES 106-107 Extrapolation .. GENERATED FROM PYTHON SOURCE LINES 107-142 .. code-block:: Python back = model.morph( shape=source, parameter=task.parameter_, final_time=-1.0, return_path=True, ).path model.n_steps = 8 forward = model.morph( shape=source, parameter=task.parameter_, final_time=2.0, return_path=True, ).path path = back[::-1] + forward[1:] plotter = pv.Plotter() plotter.open_gif("lddmm_no_normalization.gif", fps=4) for i in range(len(path)): plotter.clear_actors() plotter.add_mesh( source.to_pyvista(), color="teal", opacity=0.2, **plot_kwargs ) plotter.add_mesh( target.to_pyvista(), color="red", opacity=0.2, **plot_kwargs ) plotter.add_mesh( path[i].to_pyvista(), color="tan", opacity=0.8, **plot_kwargs ) plotter.camera_position = cpos plotter.write_frame() plotter.close() .. image-sg:: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_003.gif :alt: plot lddmm 1 normalization :srcset: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_003.gif :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 143-145 Normalizing the rows of the kernel ---------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 145-177 .. code-block:: Python model_norm = sks.ExtrinsicDeformation( n_steps=4, kernel="gaussian", scale=0.3, normalization="rows", ) task_norm = sks.Registration( model=model_norm, loss=loss, optimizer=sks.LBFGS(), n_iter=1, regularization_weight=0.0, verbose=True, ) start = time() task_norm.fit(source=source, target=target) print("Elapsed time: ", time() - start) path = task_norm.path_ plotter = pv.Plotter() plotter.add_mesh(source.to_pyvista(), color="teal", opacity=0.2, **plot_kwargs) plotter.add_mesh(target.to_pyvista(), color="red", opacity=0.2, **plot_kwargs) for i in range(len(path)): plotter.add_mesh( path[i].to_pyvista(), color="tan", opacity=0.8, **plot_kwargs ) plotter.camera_position = cpos plotter.show() .. tab-set:: .. tab-item:: Static Scene .. image-sg:: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_004.png :alt: plot lddmm 1 normalization :srcset: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_004.png :class: sphx-glr-single-img .. tab-item:: Interactive Scene .. offlineviewer:: /home/runner/work/scikit-shapes/scikit-shapes/doc/source/auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_004.vtksz .. rst-class:: sphx-glr-script-out .. code-block:: none Initial loss : 8.04e+02 = 8.04e+02 + 0 (fidelity + regularization_weight * regularization) Loss after 1 iteration(s) : 1.67e-03 = 1.67e-03 + 0 (fidelity + regularization_weight * regularization) Elapsed time: 41.609856843948364 .. GENERATED FROM PYTHON SOURCE LINES 178-179 Extrapolation .. GENERATED FROM PYTHON SOURCE LINES 179-214 .. code-block:: Python back = model_norm.morph( shape=source, parameter=task_norm.parameter_, final_time=-1.0, return_path=True, ).path model_norm.n_steps = 8 forward = model_norm.morph( shape=source, parameter=task_norm.parameter_, final_time=2.0, return_path=True, ).path path = back[::-1] + forward[1:] plotter = pv.Plotter() plotter.open_gif("lddmm_normalization.gif", fps=4) for i in range(len(path)): plotter.clear_actors() plotter.add_mesh( source.to_pyvista(), color="teal", opacity=0.2, **plot_kwargs ) plotter.add_mesh( target.to_pyvista(), color="red", opacity=0.2, **plot_kwargs ) plotter.add_mesh( path[i].to_pyvista(), color="tan", opacity=0.8, **plot_kwargs ) plotter.camera_position = cpos plotter.write_frame() plotter.close() .. image-sg:: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_005.gif :alt: plot lddmm 1 normalization :srcset: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_005.gif :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 215-217 Normalizing both rows and columns of the kernel ----------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 217-249 .. code-block:: Python model_norm = sks.ExtrinsicDeformation( n_steps=4, kernel="gaussian", scale=0.3, normalization="both", ) task_norm = sks.Registration( model=model_norm, loss=loss, optimizer=sks.LBFGS(), n_iter=1, regularization_weight=0.0, verbose=True, ) start = time() task_norm.fit(source=source, target=target) elapsed_time = time() - start path = task_norm.path_ plotter = pv.Plotter() plotter.add_mesh(source.to_pyvista(), color="teal", opacity=0.2, **plot_kwargs) plotter.add_mesh(target.to_pyvista(), color="red", opacity=0.2, **plot_kwargs) for i in range(len(path)): plotter.add_mesh( path[i].to_pyvista(), color="tan", opacity=0.8, **plot_kwargs ) plotter.camera_position = cpos plotter.show() .. tab-set:: .. tab-item:: Static Scene .. image-sg:: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_006.png :alt: plot lddmm 1 normalization :srcset: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_006.png :class: sphx-glr-single-img .. tab-item:: Interactive Scene .. offlineviewer:: /home/runner/work/scikit-shapes/scikit-shapes/doc/source/auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_006.vtksz .. rst-class:: sphx-glr-script-out .. code-block:: none Initial loss : 8.04e+02 = 8.04e+02 + 0 (fidelity + regularization_weight * regularization) Loss after 1 iteration(s) : 4.98e-06 = 4.98e-06 + 0 (fidelity + regularization_weight * regularization) .. GENERATED FROM PYTHON SOURCE LINES 250-251 Extrapolation .. GENERATED FROM PYTHON SOURCE LINES 251-286 .. code-block:: Python back = model_norm.morph( shape=source, parameter=task_norm.parameter_, final_time=-1.0, return_path=True, ).path model_norm.n_steps = 8 forward = model_norm.morph( shape=source, parameter=task_norm.parameter_, final_time=2.0, return_path=True, ).path path = back[::-1] + forward[1:] plotter = pv.Plotter() plotter.open_gif("lddmm_normalization.gif", fps=4) for i in range(len(path)): plotter.clear_actors() plotter.add_mesh( source.to_pyvista(), color="teal", opacity=0.2, **plot_kwargs ) plotter.add_mesh( target.to_pyvista(), color="red", opacity=0.2, **plot_kwargs ) plotter.add_mesh( path[i].to_pyvista(), color="tan", opacity=0.8, **plot_kwargs ) plotter.camera_position = cpos plotter.write_frame() plotter.close() .. image-sg:: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_007.gif :alt: plot lddmm 1 normalization :srcset: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_007.gif :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 287-289 Example with a more complex shape --------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 289-324 .. code-block:: Python n_steps = 3 plot_kwargs = { "smooth_shading": True, "pbr": True, "metallic": 0.7, "roughness": 0.6, } cpos = [ (3.6401575998373183, -1.183408993703478, 1.0915912440258628), (0.7463583722710609, 0.762569822371006, 0.48035204596817493), (-0.1745415166347431, 0.04933887578777028, 0.9834129012306287), ] # 5 - 8 source = sks.PolyData("../test_data/cactus/cactus3.ply") target = sks.PolyData("../test_data/cactus/cactus11.ply") target.points += torch.Tensor([0.5, 0.5, 0]) decimation = sks.Decimation(n_points=500) source = decimation.fit_transform(source) target = decimation.transform(target) model = sks.ExtrinsicDeformation( n_steps=n_steps, kernel="gaussian", scale=0.1, normalization="both", ) loss = sks.L2Loss() .. GENERATED FROM PYTHON SOURCE LINES 325-327 Interpolation ------------- .. GENERATED FROM PYTHON SOURCE LINES 327-353 .. code-block:: Python task = sks.Registration( model=model, loss=loss, optimizer=sks.LBFGS(), n_iter=1, verbose=True, regularization_weight=0.001, ) start = time() task.fit(source=source, target=target) print("Elapsed time: ", time() - start) path = task.path_ plotter = pv.Plotter() for frame in path: plotter.add_mesh( frame.to_pyvista(), color="tan", opacity=0.3, **plot_kwargs ) plotter.add_mesh(source.to_pyvista(), color="teal", opacity=0.5, **plot_kwargs) plotter.add_mesh(target.to_pyvista(), color="red", opacity=0.5, **plot_kwargs) plotter.camera_position = cpos plotter.show() .. tab-set:: .. tab-item:: Static Scene .. image-sg:: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_008.png :alt: plot lddmm 1 normalization :srcset: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_008.png :class: sphx-glr-single-img .. tab-item:: Interactive Scene .. offlineviewer:: /home/runner/work/scikit-shapes/scikit-shapes/doc/source/auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_008.vtksz .. rst-class:: sphx-glr-script-out .. code-block:: none Initial loss : 2.50e+02 = 2.50e+02 + 0.001 * 0.00e+00 (fidelity + regularization_weight * regularization) Loss after 1 iteration(s) : 1.35e-01 = 9.99e-03 + 0.001 * 1.25e+02 (fidelity + regularization_weight * regularization) Elapsed time: 15.22480583190918 .. GENERATED FROM PYTHON SOURCE LINES 354-356 Extrapolation ------------- .. GENERATED FROM PYTHON SOURCE LINES 356-388 .. code-block:: Python back = model.morph( shape=source, parameter=task.parameter_, return_path=True, return_regularization=True, final_time=-1.0, ).path model.n_steps = 2 * n_steps forward = model.morph( shape=source, parameter=task.parameter_, return_path=True, return_regularization=True, final_time=2.0, ).path path = back[::-1] + forward[1:] plotter = pv.Plotter() for frame in path: plotter.add_mesh( frame.to_pyvista(), color="tan", opacity=0.3, **plot_kwargs ) plotter.add_mesh(source.to_pyvista(), color="teal", opacity=0.5, **plot_kwargs) plotter.add_mesh(target.to_pyvista(), color="red", opacity=0.5, **plot_kwargs) plotter.camera_position = cpos plotter.show() print(plotter.camera_position) .. tab-set:: .. tab-item:: Static Scene .. image-sg:: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_009.png :alt: plot lddmm 1 normalization :srcset: /auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_009.png :class: sphx-glr-single-img .. tab-item:: Interactive Scene .. offlineviewer:: /home/runner/work/scikit-shapes/scikit-shapes/doc/source/auto_examples/registration/images/sphx_glr_plot_lddmm_1_normalization_009.vtksz .. rst-class:: sphx-glr-script-out .. code-block:: none [(3.6401575998373183, -1.183408993703478, 1.0915912440258628), (0.7463583722710609, 0.762569822371006, 0.48035204596817493), (-0.17454151663474313, 0.049338875787770284, 0.9834129012306289)] .. rst-class:: sphx-glr-timing **Total running time of the script:** (3 minutes 27.775 seconds) .. _sphx_glr_download_auto_examples_registration_plot_lddmm_1_normalization.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_lddmm_1_normalization.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_lddmm_1_normalization.py ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_