Commit 1f650c8e authored by Daniel Scheffler's avatar Daniel Scheffler
Browse files

Provided additional options for adjusting sensitivity of outlier detection algorithms.

arosics.COREG_LOCAL / bin/coreg.cmd:
- added options 'min_reliability', 'rs_max_outlier', 'rs_tolerance'

arosics.TiePointGrid.TiePointGrid:
- __init__(): added 'outlDetect_settings'

updated __version__ and __versionalias__
parent c9404339
Pipeline #286 passed with stages
in 44 seconds
......@@ -22,13 +22,6 @@ except ImportError:
from shapely.geometry import Point, Polygon
from skimage.exposure import rescale_intensity
try:
import geoarray
except ImportError:
raise ImportError("Since 2017/03/31 CoReg_Sat depends on the package 'geoarray'. "
"You need an invitation to the respective GitLab repository from Daniel Scheffler. "
"Then follow the install instructions there.")
# internal modules
from .DeShifter import DESHIFTER, _dict_rspAlg_rsp_Int
from . import geometry as GEO
......
......@@ -30,11 +30,12 @@ class COREG_LOCAL(object):
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,
tieP_filter_level=3, align_grids=True, match_gsd=False, out_gsd=None, target_xyGrid=None,
resamp_alg_deshift='cubic', resamp_alg_calc='cubic', footprint_poly_ref=None, footprint_poly_tgt=None,
data_corners_ref=None, data_corners_tgt=None, 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):
tieP_filter_level=3, min_reliability=60, rs_max_outlier=10, rs_tolerance=2.5, align_grids=True,
match_gsd=False, out_gsd=None, target_xyGrid=None, resamp_alg_deshift='cubic', resamp_alg_calc='cubic',
footprint_poly_ref=None, footprint_poly_tgt=None, data_corners_ref=None, data_corners_tgt=None,
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
......@@ -72,6 +73,13 @@ class COREG_LOCAL(object):
correction does not increase image similarity within matching window
(measured by mean structural similarity index)
- Level 3: RANSAC outlier detection
:param min_reliability(float): Tie point filtering: minimum reliability threshold, below which tie points are
marked as false-positives (default: 60%)
- accepts values between 0% (no reliability) and 100 % (perfect reliability)
HINT: decrease this value in case of poor signal-to-noise ratio of your input data
:param rs_max_outlier(float): RANSAC tie point filtering: proportion of expected outliers (default: 10%)
:param rs_tolerance(float): RANSAC tie point filtering: percentage tolerance for max_outlier_percentage
(default: 2.5%)
:param out_gsd (float): output pixel size in units of the reference coordinate system (default = pixel
size of the input array), given values are overridden by match_gsd=True
:param align_grids (bool): True: align the input coordinate grid to the reference (does not affect the
......@@ -149,6 +157,9 @@ class COREG_LOCAL(object):
self.max_shift = max_shift
self.max_iter = max_iter
self.tieP_filter_level = tieP_filter_level
self.min_reliability = min_reliability
self.rs_max_outlier = rs_max_outlier
self.rs_tolerance = rs_tolerance
self.align_grids = align_grids
self.match_gsd = match_gsd
self.out_gsd = out_gsd
......@@ -271,6 +282,10 @@ class COREG_LOCAL(object):
outFillVal = self.outFillVal,
resamp_alg_calc = self.rspAlg_calc,
tieP_filter_level = self.tieP_filter_level,
outlDetect_settings = dict(
min_reliability = self.min_reliability,
rs_max_outlier = self.rs_max_outlier,
rs_tolerance = self.rs_tolerance),
dir_out = self.projectDir,
CPUs = self.CPUs,
progress = self.progress,
......
......@@ -284,7 +284,7 @@ class DESHIFTER(object):
# warnings.warn('This method has not been tested in its current state!')
# # FIX ME nicht multiprocessing-fähig, weil immer kompletter array gewarpt wird und sich ergebnisse gegenseitig überschreiben
# # create tempfile
# fd, path_tmp = tempfile.mkstemp(prefix='CoReg_Sat', suffix=self.outFmt, dir=self.tempDir)
# fd, path_tmp = tempfile.mkstemp(prefix='AROSICS', suffix=self.outFmt, dir=self.tempDir)
# os.close(fd)
#
# t_extent = " -te %s %s %s %s" %self._get_out_extent()
......
......@@ -39,7 +39,7 @@ class Tie_Point_Grid(object):
"""See help(Tie_Point_Grid) for documentation!"""
def __init__(self, COREG_obj, grid_res, max_points=None, outFillVal=-9999, resamp_alg_calc='cubic',
tieP_filter_level=2, dir_out=None, CPUs=None, progress=True, v=False, q=False):
tieP_filter_level=3, outlDetect_settings=None, dir_out=None, CPUs=None, progress=True, v=False, q=False):
"""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
......@@ -59,7 +59,7 @@ class Tie_Point_Grid(object):
(valid algorithms: nearest, bilinear, cubic, cubic_spline, lanczos, average, mode,
max, min, med, q1, q3)
default: cubic (highly recommended)
:param tieP_filter_level(int): filter tie points used for shift correction in different levels (default: 2).
:param tieP_filter_level(int): filter tie points used for shift correction in different levels (default: 3).
NOTE: lower levels are also included if a higher level is chosen
- Level 0: no tie point filtering
- Level 1: Reliablity filtering - filter all tie points out that have a low
......@@ -68,6 +68,10 @@ class Tie_Point_Grid(object):
correction does not increase image similarity within matching window
(measured by mean structural similarity index)
- Level 3: RANSAC outlier detection
:param outlDetect_settings a dictionary with the settings to be passed to
arosics.TiePointGrid.Tie_Point_Refiner. Available keys: min_reliability,
rs_max_outlier, rs_tolerance, rs_max_iter, rs_exclude_previous_outliers,
rs_timeout, q. See documentation there.
:param dir_out(str): output directory to be used for all outputs if nothing else is given
to the individual methods
:param CPUs(int): number of CPUs to use during calculation of tie points grid
......@@ -85,6 +89,7 @@ class Tie_Point_Grid(object):
self.outFillVal = outFillVal
self.rspAlg_calc = resamp_alg_calc
self.tieP_filter_level = tieP_filter_level
self.outlDetect_settings = outlDetect_settings if outlDetect_settings else dict(q=q)
self.dir_out = dir_out
self.CPUs = CPUs
self.v = v
......@@ -341,7 +346,7 @@ class Tie_Point_Grid(object):
if self.tieP_filter_level>0:
if not self.q:
print('Performing validity checks...')
TPR = Tie_Point_Refiner(GDF[GDF.ABS_SHIFT != self.outFillVal], q=self.q)
TPR = Tie_Point_Refiner(GDF[GDF.ABS_SHIFT != self.outFillVal], **self.outlDetect_settings)
GDF_filt, new_columns = TPR.run_filtering(level=self.tieP_filter_level)
GDF = GDF.merge(GDF_filt[ ['POINT_ID']+new_columns], on='POINT_ID', how="outer")
GDF = GDF.fillna(int(self.outFillVal))
......@@ -790,10 +795,10 @@ class Tie_Point_Refiner(object):
self.ransac_model_robust = None
def run_filtering(self, level=2):
def run_filtering(self, level=3):
"""Filter tie points used for shift correction.
:param level: tie point filter level (default: 2).
:param level: tie point filter level (default: 3).
NOTE: lower levels are also included if a higher level is chosen
- Level 0: no tie point filtering
- Level 1: Reliablity filtering - filter all tie points out that have a low
......
......@@ -4,8 +4,8 @@
__author__ = """Daniel Scheffler"""
__email__ = 'daniel.scheffler@gfz-potsdam.de'
__version__ = '0.1.1'
__versionalias__ = '2017-06-28_01'
__version__ = '0.2.0'
__versionalias__ = '2017-06-30_01'
from .CoReg import COREG
......
......@@ -23,12 +23,12 @@ except ImportError:
from osgeo import ogr
# internal modules
sys.path.append(os.path.abspath(os.path.dirname(__file__))) # append CoReg_Sat root directory
sys.path.append(os.path.abspath(os.path.dirname(__file__))) # append AROSICS root directory
sys.path.append(os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..')))
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../geoarray')))
import geoarray
from CoReg_Sat import COREG, COREG_LOCAL, __version__
from arosics import COREG, COREG_LOCAL, __version__
import py_tools_ds
......@@ -80,6 +80,9 @@ def run_local_coreg(args):
max_iter = args.max_iter,
max_shift = args.max_shift,
tieP_filter_level = args.tieP_filter_level,
min_reliability = args.min_reliability,
rs_max_outlier = args.rs_max_outlier,
rs_tolerance = args.rs_tolerance,
#align_grids = args.align_grids,
#match_gsd = args.match_gsd,
#out_gsd = args.out_gsd,
......@@ -107,7 +110,7 @@ if __name__ == '__main__':
from socket import gethostname
from datetime import datetime as dt
from getpass import getuser
from components.io import wfa
from arosics.io import wfa
wfa('/misc/hy5/scheffler/tmp/crlf', '%s\t%s\t%s\t%s\n' % (dt.now(), getuser(), gethostname(), ' '.join(sys.argv)))
parser = argparse.ArgumentParser(
......@@ -155,7 +158,7 @@ if __name__ == '__main__':
'calculated at a specific (adjustable) image position. Correction performs a global shifting in '
'X- or Y direction.',
help="detect and correct global X/Y shifts (sub argument parser) - "
"use '>>> python /path/to/CoReg_Sat/coreg_cmd.py global -h' for documentation and usage hints")
"use '>>> python /path/to/arosics/bin/coreg_cmd.py global -h' for documentation and usage hints")
gloArg = parse_coreg_global.add_argument
gloArg('path_ref', type=str, help='source path of reference image (any GDAL compatible image format is supported)')
......@@ -262,7 +265,7 @@ if __name__ == '__main__':
'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.',
help="detect and correct local shifts (sub argument parser)"
"use '>>> python /path/to/CoReg_Sat/coreg_cmd.py local -h' for documentation and usage hints")
"use '>>> python /path/to/arosics/bin/coreg_cmd.py local -h' for documentation and usage hints")
locArg = parse_coreg_local.add_argument
locArg('path_ref', type=str, help='source path of reference image (any GDAL compatible image format is supported)')
......@@ -297,13 +300,24 @@ if __name__ == '__main__':
locArg('-max_shift', nargs='?', type=int,
help="maximum shift distance in reference image pixel units (default: 5 px)", default=5)
locArg('-tieP_filter_level', nargs='?', type=int,
locArg('-tieP_filter_level', nargs='?', type=int, default=3, choices=[0, 1, 2, 3],
help="filter tie points used for shift correction in different levels (default: 3). NOTE: lower levels are "
"also included if a higher level is chosen. Level 0: no tie point filtering; Level 1: Reliablity "
"filtering - filter all tie points out that have a low reliability according to internal tests; "
"Level 2: SSIM filtering - filters all tie points out where shift correction does not increase image "
"similarity within matching window (measured by mean structural similarity index) "
"Level 3: RANSAC outlier detection", default=3, choices=[0, 1, 2, 3])
"Level 3: RANSAC outlier detection")
locArg('-min_reliability', nargs='?', type=float, default=60,
help="Tie point filtering: minimum reliability threshold, below which tie points are marked as "
"false-positives (default: 60 percent) - accepts values between 0 (no reliability) and 100 (perfect "
"reliability) HINT: decrease this value in case of poor signal-to-noise ratio of your input data")
locArg('-rs_max_outlier', nargs='?', type=float, default=10,
help="RANSAC tie point filtering: proportion of expected outliers (default: 10 percent)")
locArg('-rs_tolerance', nargs='?', type=float, default=2.5,
help="RANSAC tie point filtering: percentage tolerance for max_outlier_percentage (default: 2.5 percent)")
# TODO implement footprint_poly_ref, footprint_poly_tgt
......@@ -362,17 +376,17 @@ if __name__ == '__main__':
parsed_args = parser.parse_args()
print('==================================================================\n'
'# CoReg_Sat v%s #'%__version__+'\n'
'# SUBPIXEL COREGISTRATION FOR SATELLITE IMAGERY #\n'
'# - algorithm proposed by Foroosh et al. 2002 #\n'
'# - python implementation by Daniel Scheffler #\n'
'==================================================================\n')
print('======================================================================\n'
'# AROSICS v%s #'%__version__+'\n'
'# An Automated and Robust Open-Source Image Co-Registration Software #'
'# for Multi-Sensor Satellite Data #\n'
'# - python implementation by Daniel Scheffler #\n'
'======================================================================\n')
t0 = time.time()
parsed_args.func(parsed_args)
print('\ntotal processing time: %.2fs' %(time.time()-t0))
else:
warnings.warn("The script 'coreg_cmd.py' provides a command line argument parser for CoReg_Sat and is not to be "
"used as a normal Python module.")
\ No newline at end of file
warnings.warn("The script 'coreg_cmd.py' provides a command line argument parser for AROSICS and is not to be "
"used as a normal Python module.")
cmocean
git+https://gitext.gfz-potsdam.de/danschef/geoarray.git
git+https://gitext.gfz-potsdam.de/danschef/py_tools_ds.git
cmocean
numpy
gdal
shapely
......
......@@ -24,7 +24,7 @@ test_requirements = ['coverage']
setup(
name='arosics',
version='0.1.1',
version='0.2.0',
description="An Automated and Robust Open-Source Image Co-Registration Software for Multi-Sensor Satellite Data",
long_description=readme + '\n\n' + history,
author="Daniel Scheffler",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment