# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['fringes']

package_data = \
{'': ['*']}

install_requires = \
['asdf>=2.14.3,<3.0.0',
 'numba>=0.56.4,<0.57.0',
 'opencv-contrib-python>=4.7.0,<5.0.0',
 'pyyaml>=6.0,<7.0',
 'scikit-image>=0.19.3,<0.20.0',
 'scipy>=1.10.0,<2.0.0',
 'si-prefix>=1.2.2,<2.0.0',
 'sympy>=1.11.1,<2.0.0']

setup_kwargs = {
    'name': 'fringes',
    'version': '0.1.4',
    'description': 'Phase shifting algorithms for encoding and decoding sinusoidal fringe patterns.',
    'long_description': '# Fringes\n\nAuthor: Christian Kludt\n\n## Description\nThis package provides the handy `Fringes` class which handles all the required parameters for configuring a fringe pattern\nand provides methods for fringe analysis.\n<!---\nlink to  paper, please cite\n--->\n\n### Features\n<!---\n- Generalized Temporal Phase Unwrappting (GTPU)[[14](#14-kludt-2024)]\n--->\n- Generalized Temporal Phase Unwrappting (GTPU)\n- Uncertainty Propagation\n- Optimal Coding Strategy\n- Deinterlacing\n- Multiplexing\n- Filtering Phase Maps\n- Remapping\n\n### Background\nMany applications, such as fringe projection [[11]](#11-burke-2002) or deflectometry [[1]](#1-burke-2022),\nrequire the ability to encode positional data.\nTo do this, fringe patterns are used to encode the position on the screen / projector (in pixel coordinates)\nat which the camera pixels were looking at during acquisition.\n\n--- FIGURE coding ---\n\n```\nI = A + B * cos(2πvξ/L - 2πft - φ₀)\n  = A + B * cos(kx - wt - φ₀)\n  = A + B * cos(Φ)\n```\n\n- **Encoding**\n  - **Spatial Modulation**\\\nThe x- resp. y-coordinate `ξ` of the screen/projector is normalized into the range `[0, 1)`\nby dividing through the maximum coordinate `L`\nand used to modulate the luminance in a sinusoidal fringe pattern `I`\nwith offset `A`, amplitude `B` and spatial frequency `v`.\n  - **Temporal Modulation**\\\nThe pattern is then shifted `N` times with an equidistant phase shift of `2πf/N` radian each.\nAn additional phase offset `φ₀` may be set, e.g. to let the fringe patterns start with a gray value of zero.\n- **Decoding**\n  - **Temporal Demodulation**\\\nFrom these shifts, the phase map `φ` is determined [[13]](#13-burke-2012). Due to the trigonometric functions used,\nthe global phase `Φ` is wrapped into the interval <code>[0, 2 &pi;]</code> with `v` periods:\n<code>φ &equiv; Φ mod 2&pi;</code>.\n  - **Spatial Demodulation / Phase Unwrapping**\\\nIf only one set with spatial frequency <code>v &le; 1</code> is used,\nno unwrapping is required because one period covers the complete coding range.\nHence, the coordinates `ξ` are computed directly by scaling: <code>ξ = φ / (2&pi;) * L / v</code>.\nThis constitutes the registration, which is a mapping in the same pixel grid as the camera sensor\nand contains the information where each camera pixel, i.e. each camera sightray, was looking at\nduring the fringe pattern acquisition.\nNote that in contrast to binary coding schemes, e.g. Gray code,\nthe coordinates are obtained with sub-pixel precision.\n    - **Temporal Phase Unwrapping (TPU)**\\\nIf multiple sets with different spatial frequencies `v` are used\nand the [unmbiguous measurement range](#quality-metrics) is larger than the coding range <code>UMR &ge; L</code>,\nthe ambiguity of the phase map is resolved by\ngeneralized multi-frequency temporal phase unwrapping (GTPU) [[14]](#14-kludt-2024).\n    - **Spatial Phase Unwrapping (SPU)**\\\nHowever, if only one set with `v > 1` is used, or multiple sets but  `UMR < L`, the ambiguous phase `φ`\nis unwrapped analyzing the neighbouring phase values [[15]](#15-herráez-2002) [[16]](#16-lei-2015).\nThis only yields a relative phase map, therefore absolute positions are unknown.\n\n## Contents\n- [Installation](#installation)\n- [Usage](#usage)\n- [Graphical User Interface](#graphical-user-interface)\n- [Attributes](#attributes)\n- [Methods](#methods)\n- [Optimal Coding Strategy](#optimal-coding-strategy)\n- [Troubleshooting](#troubleshooting)\n- [License](#license)\n- [Project Status](#project-status)\n\n## Installation\nYou can install `fringes` directly from [PyPi](https://pypi.org/) via `pip`:\n\n```\npip install fringes\n```\n\n## Usage\nYou instantiate and deploy the `Fringes` class:\n\n```python\nimport fringes as frng\n\nf = frng.Fringes()      # instanciate class\n```\n\nFor creating the fringe pattern sequence `I`, use the method `encode()`.\nIt will return a [NumPy array](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.html) \nin [videoshape](#video-shape) (frames, width, height, color channels).\n\n```python\nI = f.encode()          # encode fringe patterns\n```\n\nFor analyzing (recorded) fringe patterns, use the method `decode()`.\nIt will return a [namedtuple](https://docs.python.org/3/library/collections.html#collections.namedtuple), \ncontaining the Numpy arrays brightness `A`, modulation `B` and the coordinates `ξ`,\nall in [videoshape](#video-shape).\n\n```python\nA, B, xi = f.decode(I)  # decode fringe patterns\n```\n\nAll parameters are accesible by the respective attributes of the `Fringes` class.\n\n```python\nf.X = 1920              # set width of the fringe patterns\nf.Y = 1080              # set height of the fringe patterns\nf.K = 2                 # set number of sets\nf.N = 4                 # set number of shifts\nf.v = [9, 10]           # set spatial frequencies\nf.T                     # get the number of frames\n```\n\nA glossary of them is obtained by the class attribute `doc`.\n\n```python\nfrng.Fringes.doc        # get glossary\n```\n\nYou can change the [logging level](https://docs.python.org/3/library/logging.html#levels) of a `Fringes` instance.\nChanging it to `\'DEBUG\'` gives you verbose feedback on which parameters are changed\nand how long functions take to execute.\n\n```python\nf.logger.setLevel("DEBUG")\n```\n<!---\n## Graphical User Interface\nDo you need a GUI? `Fringes` has a sister project that is called `Fringes GUI`:\nhttps://pypi.org/project/fringes-gui/\n--->\n## Attributes\nAll parameters are parsed when setting, so usually several input formats are accepted, e.g.\n`bool`, `int`, `float`, `str` for scalars and additionally `list`, `tuple`, `ndarray` for arrays.\n\nNote that parameters might have circular dependencies which are resolved automatically,\nhence dependent parameters might change as well. \nThe attributes in rectangular boxes are readonly, i.e. they are inferred from the others.\nOnly the ones in white boxes will never influence others.\n\n![Parameter Interdependencies](docs/interdependencies.svg)\\\nParameter and their Interdependencies.\n\n### __Coordinate System__\nThe following coordinate systems can be used by setting `grid` to:\n- `\'image\'`: The top left corner pixel of the grid is the origin (0, 0)\nand positive directions are right- resp. downwards.\n- `\'Cartesian\'`: The center of grid is the origin (0, 0) and positive directions are right- resp. upwards.\n- `\'polar\'`: The center of grid is the origin (0, 0) and positive directions are clockwise resp. outwards.\n- `\'log-polar\'`: The center of grid is the origin (0, 0) and positive directions are clockwise resp. outwards.\n\n`D` denotes the number of directions to be encoded.\nIf <code>D &equiv; 1</code>, the parameter `axis` is used to define along which axis of the coordinate system\n(index 0 or 1) the fringes are shifted.\n\n`angle` can be used to tilt the coordinate system. The origin stays the same.\n\n### __Video Shape__\nStandardized `shape` `(T, Y, X, C)` of fringe pattern sequence, with\n- `T`: number of frames\n- `Y`: height\n- `X`: width\n- `C`: number of color channels\n\n`T` depends on the paremeters `H`, `D`, `K`, `N` and the [multiplexing](#multiplexing) methods:\\\nIf all `N` are identical, then `T = H * D * K * N` with `N` as a scalar,\nelse <code>T = H * &sum; N<sub>i</sub></code> with `N` as an array.\\\nIf a [multiplexing](#multiplexing) methods is activated, `T` reduces further.\n\nThe length `L` is the maximum of `X` and `Y`.\n\n`C` depends on the [coloring](#coloring-and-averaging) and [multiplexing](#multiplexing) methods.\n\n`size` is the product of `shape`.\n\n### __Set__\nEach set consists of the following parameters:\n- `N`: number of shifts\n- `l`: wavelength [px]\n- `v`: spatial frequency, i.e. number of periods (per screen length `L`)\n- `f`: temporal frequency, i.e. number of periods to shift over\n\nEach is an array with shape (number of directions `D`, number of sets `K`).\\\nFor example, if <code>N.shape &equiv; (2, 3)</code>, it means that we encode `D = 2` directions with `K = 3` sets each.\n\nChanging `D` or `K` directly, changes the shape of all set parameters.\nWhen setting a set parameter with a new shape (`D\'`, `K\'`),\n`D` and `K` are updated as well as the shape of the other set parameters.\n\nPer direction at least one set with <code>N &ge; 3</code> is necessary\nto solve for the three unknowns brightness `A`, modulation `B` and coordinates `ξ`.\n\n`l` and `v` are related by `l = L / v`.\nWhen `L` changes, `v` is kept constant and only `l` is changed.\n\nUsually `f = 1` and is essentially only changed if [frequency division multiplexing](#multiplexing) `FDM` is activated.\n\n`reverse` is a boolean which reverses the direction of the shifts (by multiplying `f` with `-1`).\n\n`o` denotes the phase offset `φ₀` which can be used to\ne.g. let the fringe patterns start (at the origin) with a gray value of zero.\n\n`UMR` denotes the unambiguous measurement range.\nThe coding is only unique in the interval `[0, UMR)`; after that it repeats itself.\nThe `UMR` is derived from `l` and `v`:\n- If <code>l &isin; &#8469;</code>, <code>UMR = lcm(l<sub>i</sub>)</code> with `lcm` being the least common multiple.\n- Else, if <code>v &isin; &#8469;</code>,\n  <code>UMR = `L`/ gcd(v<sub>i</sub>)</code> with `gcd` being the greatest common divisor.\n- Else, if <code>l &and; v &isin; &#8474;</code>, `lcm` resp. `gdc` are extended to rational numbers.\n- Else, if <code>l &and; v &isin; &#8477; \\ &#8474;</code>, `l` and `v` are approximated by rational numbers\n  with a fixed length of decimal digits.\n\n### __Coloring and Averaging__\nThe fringe pattern sequence `I` can be colorized by setting the hue `h` to any RGB color tuple\nin the interval `[0, 255]`. However, black `(0, 0, 0)` is not allowed. `h` must be in shape `(H, 3)`:\\\n`H` is the number of hues and can be set directly; 3 is the length of the RGB color tuple.\\\nThe hues `h` can also be set by assigning any combination of the following characters as a string:\n- `\'r\'`: red\n- `\'g\'`: green\n- `\'b\'`: blue\n- `\'c\'`: cyan\n- `\'m\'`: magenta\n- `\'y\'`: yellow\n- `\'w\'`: white\n\n`C` is the number of color channels required for either the set of hues `h`\nor [wavelength division multiplexing](#multiplexing).\nFor example, if all hues are monochromatic, i.e. the RGB values are identical for each hue, `C` equals 1, else 3.\n\nRepeating hues will be fused by averaging them before decoding.\\\n`M` is the number of averaged intensity samples and can be set directly.\n\n### __Multiplexing__\nThe following multiplexing methods can be activated by setting them to `True`:\n- `SDM`: Spatial Division Multiplexing [[2]](#2)\\\n  This results in crossed fringe patterns. The amplitude `B` is halved.\\\n  It can only be activated if we have two directions <code>D &equiv; 2</code>.\\\n  The number of frames `T` is reduced by a factor of 2.\n- `WDM`: Wavelength Divison Multiplexing [[3]](#3)\\\n  All shifts `N` must equal 3. Then, the shifts are multiplexed into the color channel,\n  resulting in an RGB fringe pattern.\\\n  The number of frames `T` is reduced by a factor of 3.\n- `FDM`: Frequency Division Multiplexing [[4]](#4), [[5]](#5)\\\n  Here, the directions `D` and the sets `K` are multiplexed.\n  Hence, the amplitude `B` is reduced by a factor of `D * K`.\\\n  It can only be activated if <code>D &or; K > 1</code> i.e. `D * K > 1`.\\\n  This results in crossed fringe patterns if <code>D &equiv; 2</code>.\\\n  Each set per direction receives an individual temporal frequency `f`,\n  which is used in [temporal demodulation](#temporal-demodulation) to distinguish the individual sets.\\\n  A minimal number of shifts <code>N<sub>min</sub> &ge; &LeftCeiling;</sub> 2 * f<sub>max</sub> + 1 &RightCeiling;</code>\n  is required to satisfy the sampling theorem and `N` is updated automatically if necessary.\\\n  If one wants a static pattern, i.e. one that remains congruent when shifted, set `static` to `True`.\n\n`SDM` and `WDM` can be used together [[6]](#6) (reducing `T` by a factor of 2 * 3 = 6), `FDM` with neighter.\n\nBy default, the aforementioned multiplexing methods are deactivated,\nso we then only have `TDM`: Time Divison Multiplexing.\n\n### __Data Type__\n`dtype` denotes the data type of the fringe pattern sequence `I`.\\\nPossible values are:\n- `\'bool\'`\n- `\'uint8\'` (the default)\n- `\'uint16\'`\n- `\'float32\'`\n- `\'float64\'`\n\nThe total number of bytes `nbytes` consumed by the fringe pattern sequence\nas well as its maximum gray value `Imax` are derived directly from it:\\\n`Imax = 1` for `float` and `bool`,\nand <code>Imax = 2<sup>Q</sup> - 1</code> for `unsigned integers` with `Q` bits.\n\n`Imax` in turn limits the offset `A` and the amplitude `B`.\nThe fringe visibility (also called fringe contrast) is `V = A / B` with <code>V &isin; [0, 1]</code>.\n\nThe quantization step size `q` is also derived from `dtype`:\n`q = 1` for `bool` and `Q`-bit `unsigned integers`, \nand for `float` its corresponding [resolution](https://numpy.org/doc/stable/reference/generated/numpy.finfo.html).\n\nThe standard deviation of the quantization noise  is <code>QN = q / &radic; 12</code>.\n\n### Unwrapping\n- `PU` denotes the phase unwrapping method and is eihter `\'none\'`, `\'temporal\'`, `\'spatial\'` or `\'SSB\'`.\nSee [spatial demodulation](#spatial-demodulation--phase-unwrapping--pu-) for more details.\n- `mode` denotes the mode used for [temporal phase unwrapping](#temporal-phase-unwrapping--tpu-).\n  Choose either `\'fast\'` (the default) or `\'precise\'`.\n- `Vmin` denotes the minimal fringe visibility (fringe contrast) required for the measurement to be valid\nand is in the interval `[0, 1]`. During decoding, pixels with less are discarded, which can speed up the computation.\n- `verbose` can be set to `True` to also receive the wrapped phase map `φ`,\nthe fringe orders `k` and the residuals `r` from decoding.\n- `SSB` denotes **Single Sideband Demodulation** [[17]](#17-takeda) and is deployed\nif <code>K &equiv; H &equiv; N &equiv; 1</code>, i.e. <code>T &equiv; 1</code>\nand the [coordinate system](#coordinate-system) is eighter `\'image\'` or `\'Cartesian\'`.\n\n### __Quality Metrics__\n`eta` denotes the coding efficiency `L / UMR`. It makes no sense to choose `UMR` much larger than `L`,\nbecause then a significant part of the coding range is not used.\n\n`u` denotes the minimum possible uncertainty of the measurement in pixels.\nIt is based on the phase noise model from [[7]](#7),\npropagated through [generalized temporal phase unwrapping](#temporal-phase-unwrapping--tpu-) and converted from phase to pixel units.\nIt is influenced by the fringe parameters\n- `M`: number of [averaged](#coloring-and-averaging) intensity samples\n- `N`: number of phase shifts\n- `l`: wavelengths of the fringes\n- `B`: measured amplitude\n\nand the measurement hardware-specific noise sources [[8]](#8), [[9]](#9)\n- `PN`: photon noise of light itself\n- `DN`: dark noise of the used camera\n- `QN`: quantization noise of the light source or camera\n\nThe maximum possible dynamic range of the measurement is `DR = UMR / u`.\nIt describes how many points can be discriminated on the interval `[0, UMR)`.\nIt remains constant if `L` and hence `l` are scaled (the scaling factor cancels out).\n\n## Methods\n- `load(fname)`\\\n  Load a parameter set from the file `fname` to a `Fringes` instance.\n  Supported file formats are `.json`, `.yaml` and `.asdf`.\n- `save(fname)`\\\n  Save the parameter set of the current `Fringes` instance to the file `fname`.\n  If `fname` is not provided, the default is `params.yaml` within the package\'s directory \'fringes\'.\n- `reset()`\\\n  Reset the parameter set of the current `Fringes` instance to the default values.\n- `auto(T)`\\\n  Automatically set the [optimal parameters](#optimal-coding-strategy) based on the argument `T` (number of frames).\n  This also takes into account the minimum resolvable wavelength `lmin` and the length of the fringe patterns `L`.\n- `setMTF(B)`\\\n  Compute the normalized modulation transfer function at spatial frequencies `v`\n  and use the result to set the optimal `lmin`.\n  `B` is the modulation from decoding. For more details, see [Optimal Coding Strategy](#optimal-coding-strategy).\n- `coordinates()`\\\n  Generate the coordinate matrices of the defined [coordinate system](#coordinate-system).\n- `encode(frames)`\\\n  [Encode](#encoding) the fringe pattern sequence `I`.\\\n  The frames <code>I<sub>t</sub></code> can be encoded indiviually\n  by passing the frame indices `frames`, either as an `integer` or a `tuple`.\n  The default is `None` in which case all frames are encoded.\\\n  To receive the frames iteratively (i.e. in a lazy manner), simply iterate over the `Fringes` instance.\n- `decode(I, verbose)`\\\n  [Decode](#decoding) the fringe pattern sequence `I`.\\\n  If either the argument `verbose` or the attribute with the same name is `True`,\n  additional infomation is computed and retuned: phase maps `φ`, residuals `r` and fringe orders `k`.\\\n  If the argument `denoise` is `True`, the unwrapped phase map is smoothened by a bilateral filter\n  which is edge-preserving.\\\n  If the argument `despike` is `True`, single pixel outliers in the unwrapped phase map\n  are replaced by their local neighborhood using a median filter.\n- `remap(registration, modulation)`\\\n  Mapping decoded registered coordinates `ξ` (having sub-pixel accuracy)\n  from camera grid to (integer) positions on the pattern/screen grid\n  with weights from modulation `B`.\n  The default for `modulation` is `None`, in which case all weights are assumed to equal one.\n  The method yields a grid representing the screen (light source)\n  with the pixel values being a relative measure\n  of how much a screen (light source) pixel contributed\n  to the exposure of the camera sensor.\n- `deinterlace(I)`\\\n  Deinterlace a fringe pattern sequence `I` acquired with a line scan camera\n  while each frame has been displayed and captured\n  while the object has been moved by one pixel.\n\nThe next methods are class-methods:\n- `unwrap(phi)`\\\n  [Unwrap](#spatial-phase-unwrapping--spu-) the phase map `phi` i.e. `φ` spacially.\n\nThe next methods are package-methods:\n- `vshape(I)`\\\n  Transforms video data of arbitrary shape and dimensionality into the standardized shape `(T, Y, X, C)`, where\n  `T` is number of frames, `Y` is height, `X` is width, and `C` is number of color channels.\n  Ensures that the array becomes 4-dimensional and that the size of the last dimension,\n  i.e. the number of color channels <code>C &isin; {1; 3; 4}</code>. To do this, leading dimensions may be flattened.\n- `curvature(registration)`\\\n  Returns a curvature map. \n- `relief(curvature)`\\\n  Local height map by local integration via an inverse laplace filter [[19]](#19).\n\n## __Optimal Coding Strategy__\nAs makes sense intuitively, more sets `K` as well as more shifts `N` per set reduce the uncertainty `u` after decoding.\nA minimum of 3 shifts is needed to solve for the 3 unknowns brightness `A`, modulation `B` and coordinates `ξ`.\nAny additional 2 shifts compensate for one harmonic of the recorded fringe pattern.\nTherefore, higher accuracy can be achieved using more shifts `N`, but the time required to capture them \nsets a practical upper limit to the feasible number of shifts.\n\nGenerally, shorter wavelengths `l` (or equivalently more periods `v`) reduce the uncertainty `u`,\nbut the resolution of the camera and the display must resolve the fringe pattern spatially.\nHence, the used hardware imposes a lower bound for the wavelength (or upper bound for the number of periods).\n   \nAlso, small wavelengths might result in a smaller unambiguous measurement range `UMR`.\nIf two or more sets `K` are used and their wavelengths `l` resp. number of periods `v` are relative primes,\nthe unmbiguous measurement range can be increased many times.\nAs a consequence, one can use much smaller wavelenghts `l` (larger number of periods `v`).\nHowever, it must be assured that the unambiguous measurment range is always equal or larger than both,\nthe width `X` and the height `Y`.\nElse, [temporal phase unwrapping](#temporal-phase-unwrapping--tpu-) would yield wrong results and thus instead\n[spatial phase unwrapping](#spatial-phase-unwrapping--spu-) is used.\nBe aware that in the latter case only a relative phase map is obtained,\nwhich lacks the information of where exactly the camera sight rays were looking at during acquisition.\n\nTo simplify finding and setting the optimal parameters, the following methods can be used:\n- `setMTF()`: The optimal `vmax` is determined automativally [[18]](#18-bothe-2008)\nby measuring the **modulation transfer function** `MTF`.\\\n  Therefore, a sequence of exponentially increasing `v` is acquired:\n    1. Set `v` to `\'exponential\'`.\n    2. Encode, acquire and decode the fringe pattern sequence.\n    3. Call the function `setMTF(B)` with the argument `B` from decoding.\n- `v` can be set to `\'auto\'`. This automatically determines the optimal integer set of `v`\n  based on the maximal resolvable spatial frequency `vmax`.\n-  Equivalently, `l` can also be set to `\'auto\'`. This will automatically determine the optimal integer set of `l`\n  based on the minimal resolvable wavelength `lmin = L / vmax`.\n- `T` can be set directly, based on the desired acquisition time.\n  The optimal `K`, `N` and the [multiplexing](#multiplexing) methods will be determined automatically.\n\nAlternatively, simply use the function `auto()`\nto automatically set the optimal `v`, `T` and [multiplexing](#multiplexing) methods.\n\n## Troubleshooting\n<!---\n- __`poetry install` does not work__\n  \n  First, ensure that poetry is installed correctly as descibed onthe [Poetry Website](https://python-poetry.org/docs/).\\\n  Secondly, ensure the correct python version is installed on your system, as specified in the file `pyproject.toml`!\\\n  Thirdly, this can be caused by a proxy which `pip` does not handle correctly.\n  Manually setting the proxy in the Windows settings or even adding a system variable \n`https_proxy = http://YOUR_PROXY:PORT` can resolve this.\n--->\n\n- __Decoding takes a long time__\n  \n  This is probably related to the just-in-time compiler [Numba](https://numba.pydata.org/) \n  used for this computationally expensive function:\n  During the first execution, an initial compilation is executed. \n  This can take several tens of seconds up to single digit minutes, depending on your CPU.\n  However, for any subsequent execution, the compiled code is cached and the code of the function runs much faster, \n  approaching the speeds of code written in C.\n\n\n- __My decoded coordinates show lots of noise__\n\n  Try using more, sets `K` and/or shifts `N` and adjust the used wavelengths `l` resp. number of periods `v`.\\\n  Also, make sure the exposure of your camera is adjusted so that the fringe patterns show up with maximum contrast.\\\n  Try to avoid under- and overexposure during acquisition.\n\n\n- #### My decoded coordinates show systematic offsets\n  First, ensure that the correct frame was captured while acquiring the fringe pattern sequence.\n  If the timings are not set correctly, the sequence may be a frame off.\\\n  Secondly, this might occur if either the camera or the display used have a gamma value very different from 1.\n  Typical screens have a gamma value of 2.2;   therefore compensate by setting the inverse value\n  <code>gamma<sup>-1</sup> = 1 / 2.2 &approx; 0.45</code> to the `gamma` attribute of the `Fringes` instance.\n  Alternatively, change the gamma value of the light source or camera directly.\n  You might also use more shifts `N` to compensate for the dominant harmonics of the gamma-nonlinearities.\n\n## References\n\n#### [11] [Burke 2002]\n[J. Burke, T. Bothe, W. Osten, and C. Hess,\n“Reverse engineering by fringe projection,”\nin Interferometry XI: Applications (W. Osten, ed.), vol. 4778, pp. 312–324, SPIE,\n2002.](https://doi.org/10.1117/12.473547)\n\n#### [1] [Burke 2022] \n[J. Burke, A. Pak, S. Höfer, M. Ziebarth, M. Roschani, J. Beyerer,\n"Deflectometry for specular surfaces: an overview",\narXiv:2204.11592v1 [physics.optics],\n2022.](https://arxiv.org/abs/2204.11592)\n\n#### [2] [Park2008]?\n\n#### [3] [Huang 1999]\n\n#### [4] [Liu 2014] [Liu2010] [Park2008]?\n\n#### [5] [Kludt 2018]\n\n#### [6] [Trumper 2016]\n\n#### [7] [Surrel 1997]\n\n#### [8] [EMVA1288]\n\n#### [9] [Bothe2008]\n\n#### [10] [Fischer]\n\n#### [13] [Burke 2012]\n[J. Burke,\n"Phase Decoding and Reconstruction",\nvol. Optical Methods for Solid Mechanics: A Full-Field Approach, ch. 3, pp. 83–141. Wiley, Weinheim,\n2012.](https://www.wiley.com/en-us/Optical+Methods+for+Solid+Mechanics%3A+A+Full+Field+Approach-p-9783527411115)\n\n#### [14] [Kludt 2024]\n\n#### [15] [Herráez 2002]\n[Miguel Arevallilo Herráaez, David R. Burton, Michael J. Lalor, and Munther A. Gdeisat.\nFast two-dimensional phase-unwrapping algorithm based on sorting by reliability following a noncontinuous path.\nAppl. Opt., 41(35):7437-7444,\nDec 2002.](https://opg.optica.org/ao/abstract.cfm?uri=ao-41-35-7437)\n\n#### [16] [Lei 2015]\n[Hai Lei, Xin yu Chang, Fei Wang, Xiao-Tang Hu, and Xiao-Dong Hu.\nA novel algorithm based on histogram processing of reliability for two-dimensional phase unwrapping.\nOptik - International Journal for Light and Electron Optics, 126(18):1640 - 1644,\n2015.](https://www.sciencedirect.com/science/article/abs/pii/S0030402615003228?via%3Dihub)\n\n#### [17] [Takeda]\n\n#### [18] [Bothe 2008]\n\n#### [19]\nInverse Laplace Filter\n\n## License\nCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public License\n\n## Project Status\nThis package is in an early stage and under active development,\nso features and functionally will be added in the future.\nFeature requests are warmly welcomed!',
    'author': 'Christian Kludt',
    'author_email': 'None',
    'maintainer': 'None',
    'maintainer_email': 'None',
    'url': 'https://github.com/comimag/fringes',
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.10,<3.11',
}


setup(**setup_kwargs)
