Commit 6504101e authored by Daniel Scheffler's avatar Daniel Scheffler
Browse files

added multiple keywords to COREG, COREG_LOCAL and Geo_Quality_Grid

components.CoReg.COREG:
- implemented new keyword 'target_xyGrid'
- added out format assertion

components.CoReg_local.COREG_LOCAL:
- implemented new keywords 'out_gsd', 'align_grids', 'match_gsd', 'target_xyGrid', 'resamp_alg_deshift', 'resamp_alg_calc'
- modified output format assertion

components.DeShifter.DESHIFTER:
- edited docstring

components.Geom_Quality_Grid.Geom_Quality_Grid:
- implemented new keyword 'resamp_alg_calc'
- CoRegPoints_table: edited print output
- to_GCPList(): edited print output
parent 66cb7b38
......@@ -117,10 +117,10 @@ class COREG(object):
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=(512, 512), max_iter=5, max_shift=5, align_grids=False, match_gsd=False,
out_gsd=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, nodata=(None,None),
calc_corners=True, multiproc=True, binary_ws=True, force_quadratic_win=True, progress=True, v=False,
path_verbose_out=None, q=False, ignore_errors=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,
nodata=(None,None), calc_corners=True, multiproc=True, binary_ws=True, 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.
......@@ -147,6 +147,8 @@ class COREG(object):
:param match_gsd(bool): match the output pixel size to pixel size of the reference image (default: 0)
:param out_gsd(tuple): xgsd ygsd: set the output pixel size in map units
(default: original pixel size of the image to be shifted)
:param target_xyGrid(list): a list with a target x-grid and a target y-grid like [[15,45], [15,45]]
This overrides 'out_gsd', 'align_grids' and 'match_gsd'.
:param resamp_alg_deshift(str) the resampling algorithm to be used for shift correction (if neccessary)
valid algorithms: nearest, bilinear, cubic, cubic_spline, lanczos, average, mode,
max, min, med, q1, q3
......@@ -185,6 +187,8 @@ class COREG(object):
self.params = dict([x for x in locals().items() if x[0] != "self"])
# assertions
assert fmt_out, "'%s' is not a valid GDAL driver code." %fmt_out
if match_gsd and out_gsd: warnings.warn("'-out_gsd' is ignored because '-match_gsd' is set.\n")
if out_gsd: assert isinstance(out_gsd, list) and len(out_gsd) == 2, 'out_gsd must be a list with two values.'
if data_corners_ref and not isinstance(data_corners_ref[0], list): # group if not [[x,y],[x,y]..] but [x,y,x,y,]
......@@ -195,10 +199,10 @@ class COREG(object):
"Got %s with length %s." %(type(nodata),len(nodata))
for rspAlg in [resamp_alg_deshift, resamp_alg_calc]:
assert rspAlg in _dict_rspAlg_rsp_Int.keys(), "'%s' is not a supported resampling algorithm." % rspAlg
if resamp_alg_calc=='average':
if resamp_alg_calc=='average' and (v or not q):
warnings.warn("The resampling algorithm 'average' causes sinus-shaped patterns in fft images that will "
"affect the precision of the calculated spatial shifts! It is highly recommended to"
"choose another resampling algorithm")
"affect the precision of the calculated spatial shifts! It is highly recommended to "
"choose another resampling algorithm.")
self.path_out = path_out # updated by self.set_outpathes
self.fmt_out = fmt_out
......@@ -210,6 +214,7 @@ class COREG(object):
self.align_grids = align_grids
self.match_gsd = match_gsd
self.out_gsd = out_gsd
self.target_xyGrid = target_xyGrid
self.rspAlg_DS = resamp_alg_deshift
self.rspAlg_calc = resamp_alg_calc
self.calc_corners = calc_corners
......@@ -975,6 +980,7 @@ class COREG(object):
resamp_alg = self.rspAlg_DS,
align_grids = self.align_grids,
match_gsd = self.match_gsd,
target_xyGrid = self.target_xyGrid,
nodata = self.shift.nodata,
CPUs = None if self.mp else 1,
progress = self.progress,
......
......@@ -26,9 +26,10 @@ class COREG_LOCAL(object):
def __init__(self, im_ref, im_tgt, grid_res, 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,
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, CPUs=None, progress=True,
v=False, q=False, ignore_errors=False):
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,
CPUs=None, progress=True, v=False, q=False, ignore_errors=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
......@@ -52,6 +53,24 @@ class COREG_LOCAL(object):
:param s_b4match(int): band of shift image to be used for matching (starts with 1; default: 1)
:param max_iter(int): maximum number of iterations for matching (default: 5)
:param max_shift(int): maximum shift distance in reference image pixel units (default: 5 px)
: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
output pixel size as long as input and output pixel sizes are compatible
(5:30 or 10:30 but not 4:30), default = True
:param match_gsd (bool): True: match the input pixel size to the reference pixel size,
default = False
:param target_xyGrid(list): a list with a target x-grid and a target y-grid like [[15,45], [15,45]]
This overrides 'out_gsd', 'align_grids' and 'match_gsd'.
:param resamp_alg_deshift(str) the resampling algorithm to be used for shift correction (if neccessary)
valid algorithms: nearest, bilinear, cubic, cubic_spline, lanczos, average, mode,
max, min, med, q1, q3
default: cubic
:param resamp_alg_calc(str) the resampling algorithm to be used for all warping processes during calculation
of spatial shifts
(valid algorithms: nearest, bilinear, cubic, cubic_spline, lanczos, average, mode,
max, min, med, q1, q3)
default: cubic (highly recommended)
:param footprint_poly_ref(str): footprint polygon of the reference image (WKT string or shapely.geometry.Polygon),
e.g. 'POLYGON ((299999 6000000, 299999 5890200, 409799 5890200, 409799 6000000,
299999 6000000))'
......@@ -76,9 +95,11 @@ class COREG_LOCAL(object):
:param q(bool): quiet mode (default: False)
:param ignore_errors(bool): Useful for batch processing. (default: False)
"""
# TODO outgsd, matchgsd
# assertions
assert fmt_out
assert fmt_out, "'%s' is not a valid GDAL driver code." %fmt_out
if match_gsd and out_gsd: warnings.warn("'-out_gsd' is ignored because '-match_gsd' is set.\n")
if out_gsd: assert isinstance(out_gsd, list) and len(out_gsd) == 2, 'out_gsd must be a list with two values.'
self.params = dict([x for x in locals().items() if x[0] != "self" and not x[0].startswith('__')])
......@@ -99,6 +120,12 @@ class COREG_LOCAL(object):
self.window_size = window_size
self.max_shift = max_shift
self.max_iter = max_iter
self.align_grids = align_grids
self.match_gsd = match_gsd
self.out_gsd = out_gsd
self.target_xyGrid = target_xyGrid
self.rspAlg_DS = resamp_alg_deshift
self.rspAlg_calc = resamp_alg_calc
self.calc_corners = calc_corners
self.nodata = nodata
self.outFillVal = outFillVal
......@@ -122,6 +149,7 @@ class COREG_LOCAL(object):
footprint_poly_tgt = footprint_poly_tgt,
data_corners_ref = data_corners_ref,
data_corners_tgt = data_corners_tgt,
resamp_alg_calc = self.rspAlg_calc,
calc_corners = calc_corners,
r_b4match = r_b4match,
s_b4match = s_b4match,
......@@ -164,8 +192,8 @@ class COREG_LOCAL(object):
return self._quality_grid
else:
self._quality_grid = Geom_Quality_Grid(self.COREG_obj, self.grid_res, outFillVal=self.outFillVal,
dir_out=self.projectDir, CPUs=self.CPUs, progress=self.progress,
v=self.v, q=self.q)
resamp_alg_calc=self.rspAlg_calc, dir_out=self.projectDir,
CPUs=self.CPUs, progress=self.progress, v=self.v, q=self.q)
if self.v:
self.view_CoRegPoints(figsize=(10,10))
return self._quality_grid
......@@ -337,8 +365,11 @@ class COREG_LOCAL(object):
path_out = self.path_out,
fmt_out = self.fmt_out,
out_crea_options = self.out_creaOpt,
out_gsd = (self.im2shift.xgsd,self.im2shift.ygsd),
align_grids = True,
align_grids = self.align_grids,
match_gsd = self.match_gsd,
out_gsd = self.out_gsd,
target_xyGrid = self.target_xyGrid,
resamp_alg = self.rspAlg_DS,
cliptoextent = cliptoextent,
#clipextent = self.im2shift.box.boxMapYX,
progress = self.progress,
......
......@@ -48,7 +48,8 @@ class DESHIFTER(object):
(5:30 or 10:30 but not 4:30), default = False
- match_gsd (bool): True: match the input pixel size to the reference pixel size,
default = False
- target_xyGrid(list): a list with an x-grid and a y-grid like [[15,45], [15,45]]
- target_xyGrid(list): a list with an x-grid and a y-grid like [[15,45], [15,45]].
This overrides 'out_gsd', 'align_grids' and 'match_gsd'.
- resamp_alg(str) the resampling algorithm to be used if neccessary
(valid algorithms: nearest, bilinear, cubic, cubic_spline, lanczos, average, mode,
max, min, med, q1, q3)
......
......@@ -33,7 +33,8 @@ global_shared_im2shift = None
class Geom_Quality_Grid(object):
"""See help(Geom_Quality_Grid) for documentation!"""
def __init__(self, COREG_obj, grid_res, outFillVal=-9999, dir_out=None, CPUs=None, progress=True, v=False, q=False):
def __init__(self, COREG_obj, grid_res, outFillVal=-9999, resamp_alg_calc='cubic', 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
......@@ -44,6 +45,11 @@ class Geom_Quality_Grid(object):
:param grid_res: grid resolution in pixels of the target image
:param outFillVal(int): if given the generated geometric quality grid is filled with this value in case
no match could be found during co-registration (default: -9999)
:param resamp_alg_calc(str) the resampling algorithm to be used for all warping processes during calculation
of spatial shifts
(valid algorithms: nearest, bilinear, cubic, cubic_spline, lanczos, average, mode,
max, min, med, q1, q3)
default: cubic (highly recommended)
: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 geometric quality grid
......@@ -55,17 +61,18 @@ class Geom_Quality_Grid(object):
if not isinstance(COREG_obj, COREG): raise ValueError("'COREG_obj' must be an instance of COREG class.")
self.COREG_obj = COREG_obj
self.grid_res = grid_res
self.dir_out = dir_out
self.outFillVal = outFillVal
self.CPUs = CPUs
self.v = v
self.q = q if not v else False # overridden by v
self.progress = progress if not q else False # overridden by q
self.COREG_obj = COREG_obj
self.grid_res = grid_res
self.outFillVal = outFillVal
self.rspAlg_calc = resamp_alg_calc
self.dir_out = dir_out
self.CPUs = CPUs
self.v = v
self.q = q if not v else False # overridden by v
self.progress = progress if not q else False # overridden by q
self.ref = self.COREG_obj.ref .GeoArray
self.shift = self.COREG_obj.shift.GeoArray
self.ref = self.COREG_obj.ref .GeoArray
self.shift = self.COREG_obj.shift.GeoArray
self.XY_points, self.XY_mapPoints = self._get_imXY__mapXY_points(self.grid_res)
self._CoRegPoints_table = None # set by self.CoRegPoints_table
......@@ -212,6 +219,7 @@ class Geom_Quality_Grid(object):
'pointID' : pID,
'wp' : wp,
'ws' : self.COREG_obj.win_size_XY,
'resamp_alg_calc' : self.rspAlg_calc,
'footprint_poly_ref' : self.COREG_obj.ref.poly,
'footprint_poly_tgt' : self.COREG_obj.shift.poly,
'r_b4match' : self.COREG_obj.ref.band4match+1, # band4match is internally saved as index, starting from 0
......@@ -229,7 +237,8 @@ class Geom_Quality_Grid(object):
# run co-registration for whole grid
if self.CPUs is None or self.CPUs>1:
if not self.q:
print("Calculating geometric quality grid (%s points) in mode 'multiprocessing'..." %len(GDF))
cpus = self.CPUs if self.CPUs is not None else multiprocessing.cpu_count()
print("Calculating geometric quality grid (%s points) using %s CPU cores..." %(len(GDF), cpus))
t0 = time.time()
with multiprocessing.Pool(self.CPUs) as pool:
......@@ -248,7 +257,7 @@ class Geom_Quality_Grid(object):
break
else:
if not self.q:
print("Calculating geometric quality grid (%s points) in mode 'singleprocessing'..." %len(GDF))
print("Calculating geometric quality grid (%s points) 1 CPU core..." %len(GDF))
results = np.empty((len(geomPoints),9))
bar = ProgressBar(prefix='\tprogress:')
for i,coreg_kwargs in enumerate(list_coreg_kwargs):
......@@ -292,7 +301,7 @@ class Geom_Quality_Grid(object):
self.GCPList = GDF.GCP.tolist()
if not self.q:
print('Found %s valid GCPs.' %len(self.GCPList))
print('Found %s valid tie points.' %len(self.GCPList))
return self.GCPList
......
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