def remove_metaRotation(gA_rot: GeoArray, rspAlg='cubic') -> GeoArray: """Remove any metadata rotation (a rotation that only exists in the map info).""" gA = GeoArray(*warp_ndarray(gA_rot[:], gA_rot.gt, gA_rot.prj, rspAlg=rspAlg, # out_gsd=(gA_rot.xgsd, gA_rot.ygsd) ), nodata=gA_rot.nodata) gA.basename = os.path.basename(gA.basename) gA.meta = gA.meta return gA
def view_CoRegPoints_folium(self, attribute2plot='ABS_SHIFT', cmap=None, exclude_fillVals=True): warnings.warn( UserWarning( 'This function is still under construction and may not work as expected!' )) assert self.CoRegPoints_table is not None, 'Calculate tie point grid first!' import folium import geojson from folium.raster_layers import ImageOverlay lon_min, lat_min, lon_max, lat_max = \ reproject_shapelyGeometry(self.im2shift.box.mapPoly, self.im2shift.projection, 4326).bounds center_lon, center_lat = (lon_min + lon_max) / 2, (lat_min + lat_max) / 2 # get image to plot image2plot = self.im2shift[:, :, 0] # FIXME hardcoded band from py_tools_ds.geo.raster.reproject import warp_ndarray image2plot, gt, prj = \ warp_ndarray(image2plot, self.im2shift.geotransform, self.im2shift.projection, in_nodata=self.nodata[1], out_nodata=self.nodata[1], out_XYdims=(1000, 1000), q=True, out_prj='epsg:3857') # image must be transformed into web mercator projection # create map map_osm = folium.Map(location=[center_lat, center_lon]) # ,zoom_start=3) # import matplotlib ImageOverlay( colormap=lambda x: (1, 0, 0, x), # TODO a colormap must be given # colormap=matplotlib.cm.gray, # does not work image=image2plot, bounds=[[lat_min, lon_min], [lat_max, lon_max]], ).add_to(map_osm) points_values = self.CoRegPoints_table[['geometry', attribute2plot]] points_values.geometry.crs = points_values.crs folium.GeoJson(points_values).add_to(map_osm) # add overlap polygon overlapPoly = reproject_shapelyGeometry(self.COREG_obj.overlap_poly, self.im2shift.epsg, 4326) gjs = geojson.Feature(geometry=overlapPoly, properties={}) folium.GeoJson(gjs).add_to(map_osm) return map_osm
def correct_shifts(self) -> collections.OrderedDict: if not self.q: print('Correcting geometric shifts...') t_start = time.time() if not self.warping_needed: """NO RESAMPLING NEEDED""" self.is_shifted = True self.is_resampled = False xmin, ymin, xmax, ymax = self._get_out_extent() if not self.q: print( "NOTE: The detected shift is corrected by updating the map info of the target image only, i.e., " "without any resampling. Set the 'align_grids' parameter to True if you need the target and the " "reference coordinate grids to be aligned.") if self.cliptoextent: # TODO validate results # TODO -> output extent does not seem to be the requested one! (only relevant if align_grids=False) # get shifted array shifted_geoArr = GeoArray(self.im2shift[:], tuple(self.updated_gt), self.shift_prj) # clip with target extent # NOTE: get_mapPos() does not perform any resampling as long as source and target projection are equal self.arr_shifted, self.updated_gt, self.updated_projection = \ shifted_geoArr.get_mapPos((xmin, ymin, xmax, ymax), self.shift_prj, fillVal=self.nodata, band2get=self.band2process) self.updated_map_info = geotransform2mapinfo( self.updated_gt, self.updated_projection) else: # array keeps the same; updated gt and prj are taken from coreg_info self.arr_shifted = self.im2shift[:, :, self.band2process] \ if self.band2process is not None else self.im2shift[:] out_geoArr = GeoArray(self.arr_shifted, self.updated_gt, self.updated_projection, q=self.q) out_geoArr.nodata = self.nodata # equals self.im2shift.nodata after __init__() out_geoArr.metadata = self.im2shift.metadata[[self.band2process]] \ if self.band2process is not None else self.im2shift.metadata self.GeoArray_shifted = out_geoArr if self.path_out: out_geoArr.save(self.path_out, fmt=self.fmt_out) else: # FIXME equal_prj==False ist noch NICHT implementiert """RESAMPLING NEEDED""" # FIXME avoid reading the whole band if clip_extent is passed in_arr = self.im2shift[:, :, self.band2process] \ if self.band2process is not None and self.im2shift.ndim == 3 else self.im2shift[:] if not self.GCPList: # apply XY-shifts to input image gt 'shift_gt' in order to correct the shifts before warping self.shift_gt[0], self.shift_gt[3] = self.updated_gt[ 0], self.updated_gt[3] # get resampled array out_arr, out_gt, out_prj = \ warp_ndarray(in_arr, self.shift_gt, self.shift_prj, self.ref_prj, rspAlg=_dict_rspAlg_rsp_Int[self.rspAlg], in_nodata=self.nodata, out_nodata=self.nodata, out_gsd=self.out_gsd, out_bounds=self._get_out_extent(), # always returns an extent snapped to the target grid gcpList=self.GCPList, # polynomialOrder=str(3), # options='-refine_gcps 500 1.9', # warpOptions=['-refine_gcps 500 1.9'], # options='-wm 10000',# -order 3', # options=['-order 3'], # options=['GDAL_CACHEMAX 800 '], # warpMemoryLimit=125829120, # 120MB CPUs=self.CPUs, progress=self.progress, q=self.q) out_geoArr = GeoArray(out_arr, out_gt, out_prj, q=self.q) out_geoArr.nodata = self.nodata # equals self.im2shift.nodata after __init__() out_geoArr.metadata = self.im2shift.metadata[[self.band2process]] \ if self.band2process is not None else self.im2shift.metadata self.arr_shifted = out_arr self.updated_gt = out_gt self.updated_projection = out_prj self.updated_map_info = geotransform2mapinfo(out_gt, out_prj) self.GeoArray_shifted = out_geoArr self.is_shifted = True self.is_resampled = True if self.path_out: out_geoArr.save(self.path_out, fmt=self.fmt_out, creationOptions=self.out_creaOpt) # validation if not is_coord_grid_equal( self.updated_gt, *self.out_grid, tolerance=1.e8): raise RuntimeError( 'DESHIFTER output dataset has not the desired target pixel grid. Target grid ' 'was %s. Output geotransform is %s.' % (str(self.out_grid), str(self.updated_gt))) # TODO to be continued (extent, map info, ...) if self.v: print('Time for shift correction: %.2fs' % (time.time() - t_start)) return self.deshift_results