Commit 5eaf6904 authored by Daniel Scheffler's avatar Daniel Scheffler
Browse files

Merge branch 'enhancement/improve_docs' into 'master'

Enhancement/improve docs

See merge request !4
parents b82c97a2 0290c863
Pipeline #4360 failed with stages
in 4 minutes and 57 seconds
......@@ -54,6 +54,9 @@ coverage.xml
# Sphinx documentation
docs/_build/
docs/arosics.rst
docs/arosics.*.rst
docs/modules.rst
# PyBuilder
target/
......
......@@ -25,6 +25,9 @@ test_arosics:
- export PYTHONPATH=$PYTHONPATH:/root # /root <- directory needed later
- pip install "py_tools_ds>=0.14.12" # FIXME remove as soon as docker runner has been updated
- make nosetests
# create the docs
- pip install sphinx_rtd_theme # Read-the-docs theme for SPHINX documentation
- pip install sphinx-autodoc-typehints
- make docs
artifacts:
paths:
......@@ -103,6 +106,7 @@ pages: # this job must be called 'pages' to advise GitLab to upload content to
expire_in: 30 days
only:
- master
- enhancement/improve_docs
deploy_pypi:
......
......@@ -54,43 +54,62 @@ If you are proposing a feature:
* Remember that this is a volunteer-driven project, and that contributions
are welcome :)
You may also join our chat here: |Gitter|
.. |Gitter| image:: https://badges.gitter.im/Join%20Chat.svg
:target: https://gitter.im/arosics/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link
:alt: https://gitter.im/arosics/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link
Get Started!
------------
Ready to contribute? Here's how to set up `arosics` for local development.
1. Fork the `arosics` repo on GitHub.
2. Clone your fork locally::
#. Fork the `arosics` repo on GitHub.
#. Clone your fork locally:
.. code-block:: bash
$ git clone https://gitext.gfz-potsdam.de/danschef/arosics.git
$ git clone https://gitext.gfz-potsdam.de/danschef/arosics.git
3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development::
#. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed,
this is how you set up your fork for local development:
$ mkvirtualenv arosics
$ cd arosics/
$ python setup.py develop
.. code-block:: bash
4. Create a branch for local development::
$ mkvirtualenv arosics
$ cd arosics/
$ python setup.py develop
$ git checkout -b name-of-your-bugfix-or-feature
#. Create a branch for local development:
.. code-block:: bash
$ git checkout -b name-of-your-bugfix-or-feature
Now you can make your changes locally.
5. When you're done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox::
#. When you're done making changes, check that your changes pass flake8 and the tests,
including testing other Python versions with tox:
$ flake8 arosics tests
$ python setup.py test or py.test
$ tox
.. code-block:: bash
$ flake8 arosics tests
$ python -m unittest discover
$ tox
To get flake8 and tox, just pip install them into your virtualenv.
6. Commit your changes and push your branch to GitHub::
#. Commit your changes and push your branch to GitHub:
.. code-block:: bash
$ git add .
$ git commit -m "Your detailed description of your changes."
$ git push origin name-of-your-bugfix-or-feature
$ git add .
$ git commit -m "Your detailed description of your changes."
$ git push origin name-of-your-bugfix-or-feature
7. Submit a pull request through the GitHub website.
#. Submit a pull request through the GitHub website.
Pull Request Guidelines
-----------------------
......@@ -108,7 +127,9 @@ Before you submit a pull request, check that it meets these guidelines:
Tips
----
To run a subset of tests::
To run a subset of tests:
.. code-block:: bash
$ python -m unittest tests.test_arosics
# e.g., to test if the COREG class can be properly initialized:
$ python -m unittest tests.test_COREG.COREG_GLOBAL_init
......@@ -2,32 +2,6 @@
History
=======
0.1.0 (2017-06-15)
------------------
* Package creation.
0.2.1 (2017-07-03)
------------------
* First release on PyPI.
0.4.0 (2017-07-07)
------------------
New features:
* added a logo
* added auto-deploy to PyPI
* added test cases for local co-registration
Fixes and improvements:
* fixed warping issues in case only very few tie points could be identified
0.5.0 (2017-09-19)
------------------
......@@ -74,3 +48,32 @@ Fixes and improvements:
* Fixed pickling error when running COREG_LOCAL in multiprocessing under a Windows environment.
* Replaced all occurrences of "quality grid" with "tie point grid". Updated version info.
0.4.0 (2017-07-07)
------------------
New features:
* added a logo
* added auto-deploy to PyPI
* added test cases for local co-registration
Fixes and improvements:
* fixed warping issues in case only very few tie points could be identified
0.2.1 (2017-07-03)
------------------
* First release on PyPI.
0.1.0 (2017-06-15)
------------------
* Package creation.
......@@ -80,7 +80,7 @@ nosetests: clean-test ## Runs nosetests with coverage, xUnit and nose-html-outpu
docs: ## generate Sphinx HTML documentation, including API docs
rm -f docs/arosics.rst
rm -f docs/modules.rst
sphinx-apidoc -o docs/ arosics
sphinx-apidoc arosics -o docs/ --private --doc-project 'Python API reference'
$(MAKE) -C docs clean
$(MAKE) -C docs html
$(BROWSER) docs/_build/html/index.html
......
This diff is collapsed.
.. figure:: http://danschef.gitext.gfz-potsdam.de/arosics/images/arosics_logo.png
:target: https://gitext.gfz-potsdam.de/danschef/arosics
An Automated and Robust Open-Source Image Co-Registration Software for Multi-Sensor Satellite Data
**An Automated and Robust Open-Source Image Co-Registration Software for Multi-Sensor Satellite Data**
* Free software: GNU General Public License v3
* Documentation: http://danschef.gitext.gfz-potsdam.de/arosics/doc/
* **Documentation:** http://danschef.gitext.gfz-potsdam.de/arosics/doc/
* The (open-access) **paper** corresponding to this software repository can be found here:
`Scheffler et al. 2017 <http://www.mdpi.com/2072-4292/9/7/676>`__
(cite as: Scheffler D, Hollstein A, Diedrich H, Segl K, Hostert P. AROSICS: An Automated and Robust Open-Source
Image Co-Registration Software for Multi-Sensor Satellite Data. Remote Sensing. 2017; 9(7):676).
* Submit feedback by filing an issue `here <https://gitext.gfz-potsdam.de/danschef/arosics/issues>`__
or join our chat here: |Gitter|
.. |Gitter| image:: https://badges.gitter.im/Join%20Chat.svg
:target: https://gitter.im/arosics/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link
:alt: https://gitter.im/arosics/Lobby?utm_source=share-link&utm_medium=link&utm_campaign=share-link
Status
------
......@@ -36,59 +45,61 @@ Status
See also the latest coverage_ report and the nosetests_ HTML report.
Feature overview
----------------
Features
--------
* Detection and correction of local or global geometric displacements between two input images.
AROSICS is a python package to perform **automatic subpixel co-registration** of two satellite image datasets
based on an image matching approach working in the frequency domain, combined with a multistage workflow for
effective detection of false-positives.
Installation
------------
It detects and corrects **local as well as global misregistrations** between two input images in the subpixel scale,
that are often present in satellite imagery. The algorithm is robust against the typical difficulties of
multi-sensoral/multi-temporal images. Clouds are automatically handled by the implemented outlier detection algorithms.
The user may provide user-defined masks to exclude certain image areas from tie point creation. The image overlap area
is automatically detected. AROSICS supports a wide range of input data formats and can be used from the command
line (without any Python experience) or as a normal Python package.
AROSICS depends on some open source packages which are usually installed without problems by the automatic install
routine. However, for some projects, we strongly recommend resolving the dependency before the automatic installer
is run. This approach avoids problems with conflicting versions of the same software.
Using conda_, the recommended approach is:
.. code-block:: console
Global co-registration - fast but only for static X/Y-shifts
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# create virtual environment for arosics, this is optional
conda create --name arosics python=3
source activate arosics
conda install -c conda-forge numpy gdal scikit-image matplotlib pyproj rasterio shapely geopandas cmocean
Only a global X/Y translation is computed within a small subset of the input images (window position is adjustable).
This allows very fast co-registration but only corrects for translational (global) X/Y shifts.
The calculated subpixel-shifts are (by default) applied to the geocoding information of the output image.
No spatial resampling is done automatically as long as both input images have the same projection. However, AROSICS
also allows to align the output image to the reference image coordinate grid if needed.
# optional libraries:
conda install -c conda-forge basemap pykrige
conda install -c conda-forge pyfftw # Linux and MacOS
conda install -c jesserobertson pyfftw # Windows
Here is an example of a Landsat-8 / Sentinel-2 image pair before and after co-registration using AROSICS:
.. image:: docs/images/animation_testcase1_zoom_L8_S2_global_coreg_before_after_900x456.gif
To install AROSICS, use the pip installer:
.. code-block:: console
Local co-registration - for spatially variable shifts but a bit slower
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pip install arosics
A dense grid of tie points is automatically computed, whereas tie points are subsequently validated using a
multistage workflow. Only those tie points not marked as false-positives are used to compute the parameters of an
affine transformation. Warping of the target image is done using an appropriate resampling technique
(cubic by default).
Here is an example of the computed shift vectors after filtering false-positives
(mainly due to clouds in the target image):
Or clone the repository via GIT and update the PATH environment variable:
.. image:: docs/images/shift_vectors_testcase1__900x824.gif
.. code-block:: console
cd /your/installation/folder
git clone https://gitext.gfz-potsdam.de/danschef/arosics.git
git clone https://gitext.gfz-potsdam.de/danschef/geoarray.git
git clone https://gitext.gfz-potsdam.de/danschef/py_tools_ds.git
PATH=$PATH:/path/to/your/installation/folder/arosics:/path/to/your/installation/folder/geoarray:/path/to/your/installation/folder/py_tools_ds
For further details check out the `documentation <http://danschef.gitext.gfz-potsdam.de/arosics/doc/>`__!
Credits
-------
AROSICS was developed within the context of the GeoMultiSens project funded by the German Federal Ministry
of Education and Research (project grant code: 01 IS 14 010 A-C).
AROSICS was developed by Daniel Scheffler (German Research Centre of Geosciences) within the context of the
`GeoMultiSens <http://www.geomultisens.de/>`__ project funded by the German Federal Ministry of Education and Research
(project grant code: 01 IS 14 010 A-C).
This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template.
The test data represent modified Copernicus Sentinel data (2016).
The test data represent modified Copernicus Sentinel-2 data (ESA 2016). The input data for the figures in the
documentation have been provided by NASA (Landsat-8) and ESA (Sentinel-2).
.. _Cookiecutter: https://github.com/audreyr/cookiecutter
.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage
......
......@@ -133,7 +133,13 @@ class GeoArray_CoReg(GeoArray):
class COREG(object):
"""See help(COREG) for documentation!"""
"""The COREG class detects and corrects global X/Y shifts between a target and refernce image.
Geometric shifts are calculated at a specific (adjustable) image position. Correction performs a global shifting
in X- or Y direction.
See help(COREG) for documentation!
"""
def __init__(self, im_ref, im_tgt, path_out=None, fmt_out='ENVI', out_crea_options=None, r_b4match=1, s_b4match=1,
wp=(None, None), ws=(256, 256), max_iter=5, max_shift=5, align_grids=False, match_gsd=False,
......@@ -142,9 +148,7 @@ class COREG(object):
nodata=(None, None), calc_corners=True, binary_ws=True, mask_baddata_ref=None, mask_baddata_tgt=None,
CPUs=None, force_quadratic_win=True, progress=True, v=False, path_verbose_out=None, q=False,
ignore_errors=False):
"""Detects and corrects global X/Y shifts between a target and refernce image. Geometric shifts are calculated
at a specific (adjustable) image position. Correction performs a global shifting in X- or Y direction.
"""Get an instance of the COREG class.
:param im_ref(str, GeoArray): source path (any GDAL compatible image format is supported) or GeoArray instance
of reference image
......@@ -222,7 +226,6 @@ class COREG(object):
In case of error COREG.success == False and COREG.x_shift_px/COREG.y_shift_px
is None
"""
self.params = dict([x for x in locals().items() if x[0] != "self"])
# assertions
......@@ -333,15 +336,15 @@ class COREG(object):
self._coreg_info = None # private attribute to be filled by self.coreg_info property
def _handle_error(self, error, warn=False, warnMsg=None):
"""Appends the given error to self.tracked_errors, sets self.success to False and raises the error in case
self.ignore_errors = True.
"""Append the given error to self.tracked_errors.
This sets self.success to False and raises the error in case self.ignore_errors = True.
:param error: instance of an error
:param warn: whether to give a warning in case error would be ignored otherwise
:param warnMsg: a custom message for the warning
:return:
"""
warn = warn or warnMsg is not None or self.v
self.tracked_errors.append(error)
......@@ -458,9 +461,7 @@ class COREG(object):
'Overlap area covers only %s pixels. At least 16*16 pixels are needed.' % px_covered
def equalize_pixGrids(self):
"""
Equalize image grids and projections of reference and target image (align target to reference).
"""
"""Equalize image grids and projections of reference and target image (align target to reference)."""
if not (prj_equal(self.ref.prj, self.shift.prj) and self.ref.xygrid_specs == self.shift.xygrid_specs):
if not self.q:
print("Equalizing pixel grids and projections of reference and target image...")
......@@ -480,8 +481,10 @@ class COREG(object):
self.ref.band4match = 0 # after resampling there is only one band in the GeoArray
def show_image_footprints(self):
"""This method is intended to be called from Jupyter Notebook and shows a web map containing the calculated
footprints of the input images as well as the corresponding overlap area."""
"""Show a web map containing the calculated footprints and overlap area of the input images.
NOTE: This method is intended to be called from Jupyter Notebook.
"""
# TODO different colors for polygons
assert self.overlap_poly, 'Please calculate the overlap polygon first.'
......@@ -578,6 +581,7 @@ class COREG(object):
else:
# TODO add titles
# TODO handle after_correction=None here
self.matchWin.show(figsize=figsize)
if after_correction:
self._get_deshifted_otherWin().show(figsize=figsize, pmin=pmin, pmax=pmax)
......@@ -585,14 +589,14 @@ class COREG(object):
self.otherWin.show(figsize=figsize, pmin=pmin, pmax=pmax)
def show_cross_power_spectrum(self, interactive=False):
"""
Shows a 3D surface of the cross power spectrum resulting from phase correlating the reference and target
image within the matching window.
"""Show a 3D surface of the cross power spectrum.
NOTE: The cross power spectrum is the result from phase correlating the reference and target
image within the matching window.
:param interactive: whether to return an interactice 3D surface plot based on 'plotly' library
:return:
"""
if interactive:
# create plotly 3D surface
......@@ -620,9 +624,9 @@ class COREG(object):
PLT.subplot_3dsurface(scps.astype(np.float32))
def _get_opt_winpos_winsize(self):
"""
Calculates optimal window position and size in reference image units according to DGM, cloud_mask and
trueCornerLonLat.
"""Calculate optimal window position and size in reference image units.
NOTE: The returned values are computed according to DGM, cloud_mask and trueCornerLonLat.
"""
# dummy algorithm: get center position of overlap instead of searching ideal window position in whole overlap
# TODO automatischer Algorithmus zur Bestimmung der optimalen Window Position
......@@ -674,9 +678,11 @@ class COREG(object):
self.win_size_XY = (int(self.win_size_XY[0]), int(self.win_size_XY[1])) if self.win_size_XY else (512, 512)
def _get_clip_window_properties(self):
"""Calculate all properties of the matching window and the other window. These windows are used to read the
corresponding image positions in the reference and the target image.
hint: Even if X- and Y-dimension of the target window is equal, the output window can be NOT quadratic!
"""Calculate all properties of the matching window and the other window.
These windows are used to read the corresponding image positions in the reference and the target image.
NOTE: Even if X- and Y-dimension of the target window is equal, the output window can be NON-quadratic!
"""
# FIXME image sizes like 10000*256 are still possible
......@@ -775,10 +781,11 @@ class COREG(object):
# write_shp('/misc/hy5/scheffler/Temp/otherMapPoly.shp', otherBox.mapPoly,otherBox.prj)
def _get_image_windows_to_match(self):
"""Reads the matching window and the other window using subset read, and resamples the other window to the
resolution and the pixel grid of the matching window. The result consists of two images with the same
dimensions and exactly the same corner coordinates."""
"""Read the matching window and the other window as subsets.
Th other window is resampled to the resolution and the pixel grid of the matching window.
The result consists of two images with the same dimensions and exactly the same corner coordinates.
"""
match_fullGeoArr = self.ref if self.grid2use == 'ref' else self.shift
other_fullGeoArr = self.shift if self.grid2use == 'ref' else self.ref
......@@ -853,13 +860,13 @@ class COREG(object):
@staticmethod
def _shrink_winsize_to_binarySize(win_shape_YX, target_size=None):
# type: (tuple, tuple) -> Union[Tuple[int, int], None]
"""Shrinks a given window size to the closest binary window size (a power of 2) -
separately for X- and Y-dimension.
"""Shrink a given window size to the closest binary window size (a power of 2).
NOTE: X- and Y-dimension are handled separately.
:param win_shape_YX: <tuple> source window shape as pixel units (rows,colums)
:param target_size: <tuple> source window shape as pixel units (rows,colums)
"""
binarySizes = [2 ** i for i in range(3, 14)] # [8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192]
possibSizes_X = [i for i in binarySizes if i <= win_shape_YX[1]]
possibSizes_Y = [i for i in binarySizes if i <= win_shape_YX[0]]
......@@ -872,14 +879,13 @@ class COREG(object):
return None
def _calc_shifted_cross_power_spectrum(self, im0=None, im1=None, precision=np.complex64):
"""Calculates shifted cross power spectrum for quantifying x/y-shifts.
"""Calculate the shifted cross power spectrum for quantifying X/Y-shifts.
:param im0: reference image
:param im1: subject image to shift
:param precision: to be quantified as a datatype
:return: 2D-numpy-array of the shifted cross power spectrum
"""
im0 = im0 if im0 is not None else self.matchWin[:] if self.matchWin.imID == 'ref' else self.otherWin[:]
im1 = im1 if im1 is not None else self.otherWin[:] if self.otherWin.imID == 'shift' else self.matchWin[:]
......@@ -968,7 +974,7 @@ class COREG(object):
@staticmethod
def _get_peakpos(scps):
"""Returns the row/column position of the peak within the given cross power spectrum.
"""Return the row/column position of the peak within the given cross power spectrum.
:param scps: <np.ndarray> shifted cross power spectrum
:return: <np.ndarray> [row, column]
......@@ -1051,12 +1057,11 @@ class COREG(object):
return x_intshift, y_intshift
def _calc_shift_reliability(self, scps):
"""Calculates a confidence percentage that can be used as an assessment for reliability of the calculated shifts.
"""Calculate a confidence percentage to be used as an assessment for reliability of the calculated shifts.
:param scps: <np.ndarray> shifted cross power spectrum
:return:
"""
# calculate mean power at peak
peakR, peakC = self._get_peakpos(scps)
power_at_peak = np.mean(scps[peakR - 1:peakR + 2, peakC - 1:peakC + 2])
......@@ -1113,17 +1118,17 @@ class COREG(object):
return x_intshift + x_subshift, y_intshift + y_subshift
def _get_deshifted_otherWin(self):
"""Returns a de-shifted version of self.otherWin as a GeoArray instance.The output dimensions and geographic
bounds are equal to those of self.matchWin and geometric shifts are corrected according to the previously
computed X/Y shifts within the matching window. This allows direct application of algorithms e.g. measuring
image similarity.
"""Return a de-shifted version of self.otherWin as a GeoArray instance.
The output dimensions and geographic bounds are equal to those of self.matchWin and geometric shifts are
corrected according to the previously computed X/Y shifts within the matching window. This allows direct
application of algorithms e.g. measuring image similarity.
The image subset that is resampled in this function is always the same that has been resampled during
computation of geometric shifts (usually the image with the higher geometric resolution).
:returns: GeoArray instance of de-shifted self.otherWin
"""
# shift vectors have been calculated to fit target image onto reference image
# -> so the shift vectors have to be inverted if shifts are applied to reference image
coreg_info = self._get_inverted_coreg_info() if self.otherWin.imID == 'ref' else self.coreg_info
......@@ -1140,13 +1145,11 @@ class COREG(object):
return ds_results['GeoArray_shifted']
def _validate_ssim_improvement(self, v=False):
"""Computes mean structural similarity index between reference and target image before and after correction
of geometric shifts..
"""Compute mean structural similarity index between reference and target image before and after co-regsitration.
:param v: <bool> verbose mode: shows images of the matchWin, otherWin and shifted version of otherWin
:return: <tuple> SSIM before an after shift correction
"""
assert self.success is not None, \
'Calculate geometric shifts first before trying to measure image similarity improvement!'
assert self.success in [True, None], \
......@@ -1220,8 +1223,7 @@ class COREG(object):
@property
def ssim_improved(self):
"""Returns True if image similarity within the matching window has been improved by correcting the previously
computed geometric shifts."""
"""Return True if image similarity within the matching window has been improved by co-registration."""
if self.success is True:
if self._ssim_improved is None:
ssim_orig, ssim_deshifted = self._validate_ssim_improvement()
......@@ -1234,12 +1236,10 @@ class COREG(object):
def calculate_spatial_shifts(self):
# type: (COREG) -> str
"""Compute the global X/Y shift between reference and the target image within the matching window.
:return: 'success' or 'fail'
"""
if self.success is False:
return 'fail'
......@@ -1373,9 +1373,7 @@ class COREG(object):
@property
def coreg_info(self):
"""A dictionary containing all the information needed to correct the detected global X/Y shift of the target
image."""
"""Return a dictionary containing everything to correct the detected global X/Y shift of the target image."""
if self._coreg_info:
return self._coreg_info
else:
......@@ -1395,9 +1393,10 @@ class COREG(object):
return self._coreg_info
def _get_inverted_coreg_info(self):
"""Returns an inverted dictionary of coreg_info that can be passed to DESHIFTER in order to fit the REFERENCE
image onto the TARGET image."""
"""Return an inverted dictionary of coreg_info.
This dictionary can be passed to DESHIFTER in order to fit the REFERENCE image onto the TARGET image.
"""
inv_coreg_info = copy(self.coreg_info)
inv_coreg_info['corrected_shifts_px']['x'] *= -1
inv_coreg_info['corrected_shifts_px']['y'] *= -1
......@@ -1418,12 +1417,10 @@ class COREG(object):
def correct_shifts(self):
# type: (COREG) -> dict
"""Correct the already calculated X/Y shift of the target image.
:return: COREG.deshift_results (dictionary)
"""
DS = DESHIFTER(self.shift, self.coreg_info,
path_out=self.path_out,
fmt_out=self.fmt_out,
......
......@@ -51,7 +51,15 @@ __author__ = 'Daniel Scheffler'
class COREG_LOCAL(object):
"""See help(COREG_LOCAL) for documentation!"""
"""
COREG_LOCAL applies the algorithm to detect spatial shifts to the whole overlap area of the input images.
Spatial shifts are calculated for each point in grid of which the parameters can be adjusted using keyword
arguments. Shift correction performs a polynomial transformation using the calculated shifts of each point in the
grid as GCPs. Thus this class can be used to correct for locally varying geometric distortions of the target image.
See help(COREG_LOCAL) for documentation.
"""
def __init__(self, im_ref, im_tgt, grid_res, max_points=None, window_size=(256, 256), path_out=None, fmt_out='ENVI',
out_crea_options=None, projectDir=None, r_b4match=1, s_b4match=1, max_iter=5, max_shift=5,
......@@ -61,11 +69,7 @@ class COREG_LOCAL(object):
outFillVal=-9999, nodata=(None, None), calc_corners=True, binary_ws=True, force_quadratic_win=True,
mask_baddata_ref=None, mask_baddata_tgt=None, CPUs=None, progress=True, v=False, q=False,
ignore_errors=True):
"""Applies the algorithm to detect spatial shifts to the whole overlap area of the input images. Spatial shifts
are calculated for each point in grid of which the parameters can be adjusted using keyword arguments. Shift
correction performs a polynomial transformation using the calculated shifts of each point in the grid as GCPs.
Thus this class can be used to correct for locally varying geometric distortions of the target image.
"""Get an instance of COREG_LOCAL.
:param im_ref(str, GeoArray): source path of reference image (any GDAL compatible image format is supported)
:param im_tgt(str, GeoArray): source path of image to be shifted (any GDAL compatible image format is
......@@ -167,7 +171,6 @@ class COREG_LOCAL(object):
:param q(bool): quiet mode (default: False)