Example #1
0
 def _validate_input(self):
     if self.vnir.gt != self.swir.gt:
         raise ValueError((self.vnir.gt, self.swir.gt), 'VNIR and SWIR geoinformation should be equal.')
     if not prj_equal(self.vnir.prj, self.swir.prj):
         raise ValueError((self.vnir.prj, self.swir.prj), 'VNIR and SWIR projection should be equal.')
     if self.vnir.bands != len(self.wvls.vnir):
         raise ValueError("The number of VNIR bands must be equal to the number of elements in 'vnir_wvls': "
                          "%d != %d" % (self.vnir.bands, len(self.wvls.vnir)))
     if self.swir.bands != len(self.wvls.swir):
         raise ValueError("The number of SWIR bands must be equal to the number of elements in 'swir_wvls': "
                          "%d != %d" % (self.swir.bands, len(self.wvls.swir)))
Example #2
0
    def compute_geolayer(self) -> (np.ndarray, np.ndarray):
        """Compute pixel-wise lon/lat arrays based on RPC coefficients, corner coordinates and image dimensions.

        :return: (2D longitude array, 2D latitude array)
        """
        # transform corner coordinates of EnMAP image to UTM
        grid_utm_epsg = get_UTMEPSG_from_LonLat(
            *get_center_coord(self.enmapIm_cornerCoords))
        cornerCoordsUTM = np.array([
            transform_any_prj(4326, grid_utm_epsg, lon, lat)
            for lon, lat in self.enmapIm_cornerCoords
        ])
        xmin, xmax = cornerCoordsUTM[:, 0].min(), cornerCoordsUTM[:, 0].max()
        ymin, ymax = cornerCoordsUTM[:, 1].min(), cornerCoordsUTM[:, 1].max()

        # get UTM bounding box and move it to the EnMAP grid
        xmin, ymin, xmax, ymax = \
            move_extent_to_coord_grid((xmin, ymin, xmax, ymax),
                                      enmap_coordinate_grid_utm['x'], enmap_coordinate_grid_utm['y'])

        # set up a regular grid of UTM points with a specific mesh width
        meshwidth = 300  # 10 EnMAP pixels
        y_grid_utm, x_grid_utm = np.meshgrid(np.arange(ymax, ymin - meshwidth,
                                                       -meshwidth),
                                             np.arange(xmin, xmax + meshwidth,
                                                       meshwidth),
                                             indexing='ij')

        if not isinstance(self.elevation, (int, float)):
            # transform UTM grid to DEM projection
            x_grid_demPrj, y_grid_demPrj = \
                (x_grid_utm, y_grid_utm) if prj_equal(grid_utm_epsg, self.elevation.epsg) else \
                transform_coordArray(CRS(grid_utm_epsg).to_wkt(),
                                     CRS(self.elevation.epsg).to_wkt(),
                                     x_grid_utm, y_grid_utm)

            # retrieve corresponding heights from DEM
            # -> resample DEM to EnMAP grid?
            xy_pairs_demPrj = np.vstack(
                [x_grid_demPrj.flatten(),
                 y_grid_demPrj.flatten()]).T
            heights = self.elevation.read_pointData(xy_pairs_demPrj).flatten()
        else:
            heights = np.full_like(x_grid_utm.flatten(), self.elevation)

        # transform UTM points to lon/lat
        lon_grid, lat_grid = \
            transform_coordArray(CRS(grid_utm_epsg).to_wkt(), CRS(4326).to_wkt(), x_grid_utm, y_grid_utm)
        lons = lon_grid.flatten()
        lats = lat_grid.flatten()

        # compute floating point EnMAP image coordinates for the selected UTM points
        rows, cols = self.transform_LonLatHeight_to_RowCol(lon=lons,
                                                           lat=lats,
                                                           height=heights)

        # interpolate lon/lats to get lon/lat coordinates integer image coordinates of EnMAP image
        rows_im, cols_im = self.enmapIm_dims_sensorgeo
        out_rows_grid, out_cols_grid = np.meshgrid(range(rows_im),
                                                   range(cols_im),
                                                   indexing='ij')
        out_xy_pairs = np.vstack(
            [out_cols_grid.flatten(),
             out_rows_grid.flatten()]).T
        in_xy_pairs = np.array((cols, rows)).T

        # Compute the triangulation (that takes time and can be computed for all values to be interpolated at once),
        # then run the interpolation
        triangulation = Delaunay(in_xy_pairs)
        lons_interp = LinearNDInterpolator(
            triangulation, lons)(out_xy_pairs).reshape(*out_rows_grid.shape)
        lats_interp = LinearNDInterpolator(
            triangulation, lats)(out_xy_pairs).reshape(*out_rows_grid.shape)

        # lons_interp / lats_interp may contain NaN values in case xmin, ymin, xmax, ymax has been set too small
        # to account for RPC transformation errors
        # => fix that by extrapolation at NaN value positions
        # FIXME: can this be avoided by modified xmin/ymin/xmy/ymax coords?

        lons_interp = self._fill_nans_at_corners(
            lons_interp, along_axis=0)  # extrapolate in left/right direction
        lats_interp = self._fill_nans_at_corners(lats_interp, along_axis=1)

        # return a geolayer in the exact dimensions like the EnMAP detector array
        return lons_interp, lats_interp
Example #3
0
 def warping_needed(self):
     """Return True if image warping is needed in consideration of the input parameters of DESHIFTER."""
     assert self.out_grid, 'Output grid must be calculated before.'
     equal_prj = prj_equal(self.ref_prj, self.shift_prj)
     return \
         False if (equal_prj and not self.GCPList and is_coord_grid_equal(self.updated_gt, *self.out_grid)) else True