Commit cc553994 authored by Daniel Scheffler's avatar Daniel Scheffler
Browse files

internal array attributes of COREG and COREG_LOCAL are now GeoArray instances;...

internal array attributes of COREG and COREG_LOCAL are now GeoArray instances; added algorithm for calculating shift confidence

components.CoReg.imParamObj:
- refactored class to 'GeoArray_CoReg' - a subclass of GeoArray from external package 'py_tools_ds'
-> fixes duplicate attributes within old class imParamObj
- revised attribute settings
- revised add_mask_bad_data()

components.CoReg.COREG:
- COREG.ref and COREG.shift are now instances of GeoArray
- refactored attribures 'matchWin' and 'otherWin' to new attributes 'matchBox' and 'otherBox' (instances of boxObj)
- attribures 'matchWin' and 'otherWin' are now instances of GeoArray class -> allows easy visualization and attribute access
- added new attribute 'confidence_shifts' -> represents some kind of quality assessment for the calculated shifts
- show_matchWin():
     - added docstring
     - function body simplification due to new GeoArray attributes
     - added alternative to interactive mode
- added show_cross_power_spectrum(): function for quickly visulaizing an interactive 3D surface plot of cross power spectrum
- _get_opt_winpos_winsize():
    - added docstring
    - added automatic adjustion of matching window size in case matching window extent exceeds dimensions of input image overlap area
         -> fixes wrong shift values at the input images (appeared in case of slighly structured image border / if border was no straight line)
- _get_image_windows_to_match(): adapted function body to new GeoArray attributes
- _shrink_winsize_to_binarySize():
    - adapted function body to new GeoArray attributes
    - bugfix for not updating COREG.success in case matchign window became too small
- _get_peakpos(): added docstring
- added _calc_shift_confidence(): function for calculating a single confidence percentage for assessing calculated shifts
- _get_deshifted_otherWin(): - adapted function body to new GeoArray attributes
- calculate_spatial_shifts(): added automatic calculation of shift confidence

components.CoReg_local.COREG_LOCAL:
- __init__():
    - added 2nd tieP_filter_level to docstring
    - COREG_LOCAL.imref and COREG_LOCAL.im2shift are now instances of GeoArray
    - added assertion regarding tieP_filter_level

components.Geom_Quality_Grid.Geom_Quality_Grid:
- _get_spatial_shifts(): now additionally returns COREG.confidence_shifts
- get_CoRegPoints_table():
     - 'added new column 'CONFIDENCE' to Geom_Quality_Grid.CoRegPoints_table
- _flag_outliers(): catched empty GeoDataFrame exception
- test_if_singleprocessing_equals_multiprocessing_result(): now disables RANSAC outlier detection during calculation

- updated __version__
parent e06e354b
......@@ -9,7 +9,7 @@ from .components import utilities
from .components import geometry
__author__ = 'Daniel Scheffler'
__version__= '2016-11-17_01'
__version__= '2016-11-18_01'
__all__=['COREG',
'COREG_LOCAL',
......
This diff is collapsed.
......@@ -44,7 +44,7 @@ class COREG_LOCAL(object):
:param path_out(str): target path of the coregistered image
- if None (default), no output is written to disk
- if 'auto': /dir/of/im1/<im1>__shifted_to__<im0>.bsq
:param fmt_out(str): raster file format for output file. ignored if path_out is None. can be any GDAL
:param fmt_out(str): raster file format for output file. ignored if path_out is None. Can be any GDAL
compatible raster file format (e.g. 'ENVI', 'GeoTIFF'; default: ENVI)
:param out_crea_options(list): GDAL creation options for the output image,
e.g. ["QUALITY=80", "REVERSIBLE=YES", "WRITE_METADATA=YES"]
......@@ -59,6 +59,7 @@ class COREG_LOCAL(object):
- Level 1: 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 2: SSIM filtering and RANSAC outlier detection
: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
......@@ -121,14 +122,17 @@ class COREG_LOCAL(object):
self.params = dict([x for x in locals().items() if x[0] != "self" and not x[0].startswith('__')])
if isinstance(im_ref, GeoArray) and nodata is not None: im_ref.nodata = nodata[0]
if isinstance(im_tgt, GeoArray) and nodata is not None: im_tgt.nodata = nodata[1]
self.imref = im_ref if isinstance(im_tgt, GeoArray) else GeoArray(im_ref, nodata=nodata[0])
self.im2shift = im_tgt if isinstance(im_tgt, GeoArray) else GeoArray(im_tgt, nodata=nodata[1])
self.imref.progress = progress
self.im2shift.progress = progress
self.imref.q = q
self.im2shift.q = q
self.imref = GeoArray(im_ref, nodata=nodata[0], progress=progress, q=q)
self.im2shift = GeoArray(im_tgt, nodata=nodata[1], progress=progress, q=q)
# if isinstance(im_ref, GeoArray) and nodata is not None: im_ref.nodata = nodata[0]
# if isinstance(im_tgt, GeoArray) and nodata is not None: im_tgt.nodata = nodata[1]
# self.imref = im_ref if isinstance(im_ref, GeoArray) else GeoArray(im_ref, nodata=nodata[0])
# self.im2shift = im_tgt if isinstance(im_tgt, GeoArray) else GeoArray(im_tgt, nodata=nodata[1])
# self.imref.progress = progress
# self.im2shift.progress = progress
# self.imref.q = q
# self.im2shift.q = q
self.path_out = path_out # updated by self.set_outpathes
self.fmt_out = fmt_out
......@@ -156,6 +160,7 @@ class COREG_LOCAL(object):
self.progress = progress if not q else False # overridden by v
self.ignErr = ignore_errors
assert self.tieP_filter_level in [0,1,2], 'Invalid tie point filter level.'
assert isinstance(self.imref, GeoArray) and isinstance(self.im2shift, GeoArray), \
'Something went wrong with the creation of GeoArray instances for reference or target image. The created ' \
'instances do not seem to belong to the GeoArray class. If you are working in Jupyter Notebook, reset the ' \
......
......@@ -80,8 +80,8 @@ class Geom_Quality_Grid(object):
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
self.shift = self.COREG_obj.shift
self.XY_points, self.XY_mapPoints = self._get_imXY__mapXY_points(self.grid_res)
self._CoRegPoints_table = None # set by self.CoRegPoints_table
......@@ -153,17 +153,17 @@ class Geom_Quality_Grid(object):
#for im in [global_shared_imref, global_shared_im2shift]:
# imX, imY = mapXY2imXY(coreg_kwargs['wp'], im.gt)
# if im.GeoArray[int(imY), int(imX), im.band4match]==im.nodata,\
# if im[int(imY), int(imX), im.band4match]==im.nodata,\
# return
assert global_shared_imref is not None
assert global_shared_im2shift is not None
CR = COREG(global_shared_imref, global_shared_im2shift, multiproc=False, **coreg_kwargs)
CR.calculate_spatial_shifts()
last_err = CR.tracked_errors[-1] if CR.tracked_errors else None
win_sz_y, win_sz_x = CR.matchWin.imDimsYX if CR.matchWin else (None, None)
CR_res = [win_sz_x, win_sz_y,
CR.x_shift_px, CR.y_shift_px, CR.x_shift_map, CR.y_shift_map,
CR.vec_length_map, CR.vec_angle_deg, CR.ssim_orig, CR.ssim_deshifted, CR.ssim_improved, last_err]
win_sz_y, win_sz_x = CR.matchBox.imDimsYX if CR.matchBox else (None, None)
CR_res = [win_sz_x, win_sz_y, CR.x_shift_px, CR.y_shift_px, CR.x_shift_map, CR.y_shift_map,
CR.vec_length_map, CR.vec_angle_deg, CR.ssim_orig, CR.ssim_deshifted, CR.ssim_improved,
CR.confidence_shifts, last_err]
return [pointID]+CR_res
......@@ -281,7 +281,7 @@ class Geom_Quality_Grid(object):
else:
if not self.q:
print("Calculating geometric quality grid (%s points) 1 CPU core..." %len(GDF))
results = np.empty((len(geomPoints),13), np.object)
results = np.empty((len(geomPoints),14), np.object)
bar = ProgressBar(prefix='\tprogress:')
for i,coreg_kwargs in enumerate(list_coreg_kwargs):
if self.progress:
......@@ -293,7 +293,7 @@ class Geom_Quality_Grid(object):
records = GeoDataFrame(np.array(results, np.object),
columns=['POINT_ID', 'X_WIN_SIZE', 'Y_WIN_SIZE', 'X_SHIFT_PX','Y_SHIFT_PX', 'X_SHIFT_M',
'Y_SHIFT_M', 'ABS_SHIFT', 'ANGLE', 'SSIM_BEFORE', 'SSIM_AFTER',
'SSIM_IMPROVED', 'LAST_ERR'])
'SSIM_IMPROVED', 'CONFIDENCE', 'LAST_ERR'])
GDF = GDF.merge(records, on='POINT_ID', how="inner")
GDF = GDF.fillna(int(self.outFillVal))
......@@ -322,24 +322,29 @@ class Geom_Quality_Grid(object):
# exclude all records where SSIM decreased or no match has been found
GDF = GDF[(GDF.ABS_SHIFT!=self.outFillVal) &(GDF.SSIM_IMPROVED==True)]
src = np.array(GDF[['X_UTM', 'Y_UTM']])
xyShift = np.array(GDF[['X_SHIFT_M', 'Y_SHIFT_M']])
dst = src + xyShift
if not GDF.empty:
src = np.array(GDF[['X_UTM', 'Y_UTM']])
xyShift = np.array(GDF[['X_SHIFT_M', 'Y_SHIFT_M']])
dst = src + xyShift
if algorithm=='RANSAC':
model_roust, outliers = self._ransac_outlier_detection(src, dst)
#print(np.count_nonzero(outliers), 'marked as outliers')
if algorithm=='RANSAC':
model_roust, outliers = self._ransac_outlier_detection(src, dst)
#print(np.count_nonzero(outliers), 'marked as outliers')
records = GDF[['POINT_ID']].copy()
records['OUTLIER'] = outliers
records = GDF[['POINT_ID']].copy()
records['OUTLIER'] = outliers
GDF = self.CoRegPoints_table.merge(records, on='POINT_ID', how="outer")
GDF['OUTLIER'].fillna(int(self.outFillVal), inplace=True)
GDF = self.CoRegPoints_table.merge(records, on='POINT_ID', how="outer")
GDF['OUTLIER'].fillna(int(self.outFillVal), inplace=True)
if inplace:
self.CoRegPoints_table = GDF
if inplace:
self.CoRegPoints_table = GDF
return GDF
return GDF
else:
if not inplace:
return GeoDataFrame(columns=['OUTLIER'])
@staticmethod
......@@ -451,6 +456,8 @@ class Geom_Quality_Grid(object):
def test_if_singleprocessing_equals_multiprocessing_result(self):
self.tieP_filter_level=1 # RANSAC filtering always produces different results because it includes random sampling
self.CPUs = None
dataframe = self.get_CoRegPoints_table()
mp_out = np.empty_like(dataframe.values)
......
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