Metadata-Version: 2.1
Name: imgreg
Version: 1.0.2
Summary: Image registration models with extendable interfaces.
Home-page: https://gitlab.com/DigonIO/imgreg
Author: Fabian A. Preiss, Jendrik A. Potyka
Author-email: devops@digon.io
License: GPLv3
Description: # imgreg
        
        [![pkgversion](https://img.shields.io/pypi/v/imgreg)](https://pypi.org/project/imgreg/)
        [![versionsupport](https://img.shields.io/pypi/pyversions/imgreg)](https://pypi.org/project/imgreg/)
        [![pipeline status](https://gitlab.com/DigonIO/imgreg/badges/master/pipeline.svg)](https://gitlab.com/DigonIO/imgreg/-/pipelines)
        [![coverage report](https://gitlab.com/DigonIO/imgreg/badges/master/coverage.svg)](https://gitlab.com/DigonIO/imgreg/-/pipelines)
        [![license](https://img.shields.io/pypi/l/imgreg)](https://gitlab.com/DigonIO/imgreg/-/blob/master/LICENSE)
        [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
        [![docs](https://readthedocs.org/projects/imgreg/badge/?version=latest)](https://imgreg.readthedocs.io/en/latest/)
        [![Downloads](https://pepy.tech/badge/imgreg)](https://pepy.tech/project/imgreg)
        
        An image registration library for python including a simple interface for building new models. Currently two image registration models for linear transformations based on scikit have been implemented as part of a toolchain in the context of particle image velocimetry (PIV). Tested for Python 3.7 to Python 3.9.
        
        - [Installation](#installation)
        - [Examples](#examples)
          * [Recover the rotation and translation between two images](#recover-the-rotation-and-translation-between-two-images)
          * [Batch image processing](#batch-image-processing)
            + [Store recovered values to .csv](#store-recovered-values-to-csv)
            + [Load the recovered values from .csv](#load-the-recovered-values-from-csv)
            + [Save the reconstructed images](#save-the-reconstructed-images)
          * [A word on the models](#a-word-on-the-models)
        - [Tutorials](#tutorials)
        - [Documentation](#documentation)
        - [Testing](#testing)
        - [License](#license)
        
        ## Installation
        
        imgreg is directly available from [pypi](https://pypi.org/project/imgreg/):
        
        ```bash
        pip install imgreg
        ```
        
        alternatively clone the [repository](https://gitlab.com/DigonIO/imgreg), and install with:
        
        ```bash
        git clone https://gitlab.com/DigonIO/imgreg.git
        cd imgreg
        python setup.py install
        ```
        
        ## Examples
        
        The following example give a short introduction into the available models. For further reading the directory [`doc/tutorial`](https://gitlab.com/DigonIO/imgreg/-/tree/master/doc/tutorial) provides a good starting point. The full documentation can be generated using [sphinx](https://www.sphinx-doc.org/en/master/).
        
        ### Recover the rotation and translation between two images
        
        First import the model (here based on the logpolar and fourier transformation) and load the image files into the model:
        
        ```python
        import numpy as np
        import imgreg.data as data
        from imgreg.models.logpolar import LogPolarSolver
        
        ref_img = np.array(data.ref_img())
        mod_img = np.array(data.mod_img())
        lps = LogPolarSolver(ref_img, mod_img)
        ```
        
        The images can be displayed with:
        
        ```python
        lps.display([lps.REF_IMG, lps.MOD_IMG])
        ```
        
        ![reference vs modified image](https://gitlab.com/DigonIO/imgreg/-/raw/master/doc/_assets/ref_mod.png)
        
        To access the recovered rotation angle and lower error bound in degrees use:
        
        ```python
        lps.RECOVERED_ROTATION.value
        # array([-13.06730769,   0.11259774])
        ```
        
        The recovered x,y translation and lower error bound given in number of pixels is accessed with:
        
        ```python
        lps.RECOVERED_TRANSLATION.value
        # array([-17.98318062,  31.037803  ,   0.42407651])
        ```
        
        The recovered scaling factor is available with:
        
        ```python
        lps.RECOVERED_SCALE.value
        # array([1.        , 1.00187429])
        ```
        
        A comparision between the recovered and the reference image can be displayed with:
        
        ```python
        lps.display([lps.RECOVERED_ROT_SCALE_TR_IMG, lps.REF_IMG])
        ```
        
        ![recovered vs reference image](https://gitlab.com/DigonIO/imgreg/-/raw/master/doc/_assets/rec_ref.png)
        
        ### Batch image processing
        
        First import the required modules (here we use less general domain specific `RadonSolver` model, if not suitable for your application, repace with the `LogPolarSolver` as in the previous example):
        
        ```python
        import os
        import pandas as pd
        
        import matplotlib.pyplot as plt
        import numpy as np
        from PIL import Image
        
        from imgreg.models.radon import RadonSolver
        from imgreg.util.helpers import image_save_back_tf, rot_tr_gen, solver_gen
        from imgreg.util.io import DirectoryView
        ```
        
        Define the location to your reference image according to your usecase by replacing `<path/to/reference/image.jpg>`, then replace the location of your source `<src>` and destination `<dest>` paths. Adjust the `file_pattern` and `step` variables to your needs, the latter can be used to skip images for faster computation.
        
        ```python
        image_path_ref = "<path/to/reference/image.jpg>"
        image_path_src = "<src>"
        image_path_dest = "<dest>"
        file_pattern = "*.jpg"
        step = 10
        ```
        
        Create a directory view from which the solver generates its input:
        
        ```python
        d_view = DirectoryView(image_path_src, file_pattern=file_pattern)
        fnames = [file for i, file in enumerate(sorted(d_view.files)) if not i % step]
        ```
        
        Load the reference image:
        
        ```python
        ref_img = np.array(Image.open(image_path_ref))
        ```
        
        Initialize and configure a suitable solver:
        
        ```python
        ras = RadonSolver(ref_img=ref_img)
        ras.UPSAMPLING.value = 20
        ```
        
        Generate an array containing the recovered translation and rotation parameters for the given images:
        
        ```python
        radg = solver_gen(d_view, ras, step)
        rad_rot_tr_arr = np.array(list(rot_tr_gen(radg)))
        ```
        
        Display the relative norm `NormRel_L2` over the image series as an indicator for the goodness of the recovered values:
        
        ```python
        plt.plot(rad_rot_tr_arr[:, -1])
        plt.xlabel("# image")
        plt.ylabel("NormRel_L2")
        plt.show()
        ```
        
        ![plot of the relative difference L2 norm](https://gitlab.com/DigonIO/imgreg/-/raw/master/doc/_assets/NormRel_L2.png)
        
        #### Store recovered values to .csv
        
        ```python
        df_out = pd.DataFrame(
            rad_rot_tr_arr,
            index=fnames,
            columns=[
                "tr_x",
                "tr_y",
                "tr_err",
                "rot",
                "rot_err",
                "NormRel_L2",
            ],
        )
        df_out.to_csv(f"radon-{step}.csv")
        df_out
        ```
        
        |               |       tr_x |      tr_y |   tr_err |        rot |   rot_err |   NormRel_L2 |
        |:--------------|-----------:|----------:|---------:|-----------:|----------:|-------------:|
        | test00001.jpg | -26.4509   |  47.3258  | 0.405569 | -20.5556   |  0.282843 |     0.41641  |
        | test00011.jpg | -26.3339   |  47.1561  | 0.405386 | -20.5556   |  0.282843 |     0.415555 |
        | test00021.jpg | -26.2344   |  47.0332  | 0.405536 | -20.5556   |  0.282843 |     0.415513 |
        | test00031.jpg | -22.8071   |  42.6237  | 0.385188 | -18.4444   |  0.282843 |     0.396469 |
        | test00041.jpg | -18.4961   |  36.5684  | 0.366198 | -16        |  0.282843 |     0.379106 |
        | test00051.jpg | -14.7056   |  30.9144  | 0.343007 | -13.5556   |  0.282843 |     0.35666  |
        | test00061.jpg | -11.768    |  25.8513  | 0.316403 | -11.2469   |  0.282843 |     0.329185 |
        | test00071.jpg |  -8.66827  |  20.3634  | 0.288842 |  -8.80247  |  0.282843 |     0.300223 |
        | test00081.jpg |  -6.02938  |  15.0685  | 0.258316 |  -6.44444  |  0.282843 |     0.267387 |
        | test00091.jpg |  -3.50923  |   9.32793 | 0.220809 |  -4        |  0.282843 |     0.227255 |
        | test00101.jpg |  -1.19596  |   3.51883 | 0.172761 |  -1.55556  |  0.282843 |     0.175223 |
        | test00111.jpg |   0.575633 |  -1.85773 | 0.129057 |   0.753086 |  0.282843 |     0.126313 |
        | test00121.jpg |   2.41049  |  -7.94683 | 0.167134 |   3.19753  |  0.282843 |     0.16156  |
        | test00131.jpg |   3.81275  | -13.2214  | 0.200897 |   5.44444  |  0.282843 |     0.198397 |
        | test00141.jpg |   5.16611  | -19.4011  | 0.234146 |   7.95062  |  0.282843 |     0.240847 |
        | test00151.jpg |   6.11063  | -24.7732  | 0.264576 |  10.1975   |  0.282843 |     0.289057 |
        | test00161.jpg |   6.97132  | -31.2601  | 0.29121  |  12.7531   |  0.282843 |     0.335311 |
        | test00171.jpg |   7.47346  | -36.6325  | 0.317422 |  15        |  0.282843 |     0.387218 |
        | test00181.jpg |   7.68796  | -41.7207  | 0.34348  |  17        |  0.282843 |     0.426283 |
        | test00191.jpg |   7.70654  | -41.831   | 0.345591 |  17        |  0.282843 |     0.42826  |
        | test00201.jpg |   7.69192  | -41.8788  | 0.349477 |  17        |  0.282843 |     0.4287   |
        | test00211.jpg |   7.65427  | -39.2652  | 0.338767 |  15.9506   |  0.282843 |     0.405673 |
        | test00221.jpg |   7.37055  | -33.822   | 0.325869 |  13.7531   |  0.282843 |     0.370918 |
        | test00231.jpg |   7.39534  | -33.931   | 0.327034 |  13.7531   |  0.282843 |     0.372402 |
        | test00241.jpg |   7.38345  | -33.9795  | 0.33014  |  13.7531   |  0.282843 |     0.375312 |
        | test00251.jpg |   7.11119  | -31.5481  | 0.321188 |  12.7531   |  0.282843 |     0.357117 |
        
        #### Load the recovered values from .csv
        
        ```python
        df_in = pd.read_csv(f"radon-{step}.csv", index_col=0, sep=",")
        rad_rot_tr_arr = df_in.to_numpy()
        fnames = df_in.index
        ```
        
        If desired an offset can be applied to a column of the data for plotting:
        
        ```python
        rad_rot_tr_arr[:, 3] -= 15
        plt.plot(rad_rot_tr_arr[:, 3])
        plt.xlabel("# image")
        plt.ylabel("angle")
        plt.show()
        ```
        
        ![plot of the angles with an offset](https://gitlab.com/DigonIO/imgreg/-/raw/master/doc/_assets/angle.png)
        
        #### Save the reconstructed images
        
        Finally the table of reconstructed parameters can be used to save the backtransformed images.
        
        ```python
        image_save_back_tf(rad_rot_tr_arr, fnames, image_path_src, image_path_dest)
        ```
        
        ### A word on the models
        
        The implemented models differ in some of the internal parameters. As the construction of a model also defines the dependency tree of its parameters, we can display a representation of the dependency tree as follows for every model (shown for the RadonSolver):
        
        ```python
        from imgreg.models.radon import RadonSolver
        from imgreg.util.graph import dot_args_box_img_func
        
        ras=RadonSolver()
        ras.dot_graph(dot_args_box_img_func)
        ```
        
        ![A dependency graph representation of the RadonSolver](https://gitlab.com/DigonIO/imgreg/-/raw/master/doc/_assets/graphviz-95712dd0db77a44b8fed74946896cee539b4b9fd.svg)
        
        ## Tutorials
        
        Further interactive examples are available as [jupyter-notebooks](https://jupyter.org/) in [`doc/tutorial`](https://gitlab.com/DigonIO/imgreg/-/tree/master/doc/tutorial).
        
        ## Documentation
        
        The API documentation can either be viewed [online](https://imgreg.readthedocs.io/en/latest/) or be generated using Sphinx with [numpydoc](https://numpydoc.readthedocs.io/en/latest/format.html) formatting. To build, run:
        
        ```bash
        sphinx-build -b html doc/ doc/_build/html
        ```
        
        ## Testing
        
        Testing is done using [pytest](https://pypi.org/project/pytest/). With [pytest-cov](https://pypi.org/project/pytest-cov/) and [coverage](https://pypi.org/project/coverage/) a report for the tests can be generated with:
        
        ```bash
        pytest --cov=imgreg/ tests/
        coverage html
        ```
        
        To test the examples in the documentation run:
        
        ```bash
        pytest --doctest-modules imgreg/
        ```
        
        ## License
        
        This software is published under the [GPLv3 license](https://www.gnu.org/licenses/gpl-3.0.en.html).
Keywords: image registration data analysis science
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Image Processing
Classifier: Topic :: Scientific/Engineering :: Visualization
Classifier: Topic :: Software Development :: Libraries
Classifier: Operating System :: Unix
Classifier: Operating System :: POSIX
Description-Content-Type: text/markdown
