Source code for cars.data_structures.format_transformation

#!/usr/bin/env python
# coding: utf8
#
# Copyright (c) 2020 Centre National d'Etudes Spatiales (CNES).
#
# This file is part of CARS
# (see https://github.com/CNES/cars).
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""
Contains function for format transformation between region and windows:
"""

# Third party imports

# Standard imports
import math

import numpy as np
import xarray as xr

from cars.orchestrator.cluster.log_wrapper import cars_profile

# CARS imports


@cars_profile(name="Grid margins 2 overlaps", interval=0.5)
def grid_margins_2_overlaps(grid, margins_fun):
    """
    Convert margins to overlap grid format used in CarsDatasets

    :param grid: region grid
    :type grid: np.ndarray
    :param margins_fun: function to compute margis
    :type margins_fun: fun


    :return: overlap grid left, overlap grid right
    :rtype: np.ndarray, np.ndarray

    """

    def fill_overlap(  # pylint: disable=too-many-positional-arguments
        cars_ds_overlaps,
        margins,
        row_up,
        row_max,
        row_down,
        col_left,
        col_max,
        col_right,
    ):
        """
        Fill overlap arrays for given margins
        """
        # margins : pandora convention : ['left','up', 'right', 'down']
        overlap_row_up = abs(math.floor(margins[1]))
        overlap_row_down = abs(math.ceil(margins[3]))
        overlap_col_left = abs(math.floor(margins[0]))
        overlap_col_right = abs(math.ceil(margins[2]))

        # fill overlap [OL_row_up, OL_row_down, OL_col_left,
        #  OL_col_right]
        cars_ds_overlaps[i, j, 0] = row_up - max(0, row_up - overlap_row_up)
        cars_ds_overlaps[i, j, 1] = (
            min(row_max, row_down + overlap_row_down) - row_down
        )

        cars_ds_overlaps[i, j, 2] = col_left - max(
            0, col_left - overlap_col_left
        )
        cars_ds_overlaps[i, j, 3] = (
            min(col_max, col_right + overlap_col_right) - col_right
        )

    nb_rows, nb_cols = grid.shape[0], grid.shape[1]

    cars_ds_overlaps_left = np.ndarray(shape=(nb_rows, nb_cols, 4), dtype=float)
    cars_ds_overlaps_right = np.ndarray(
        shape=(nb_rows, nb_cols, 4), dtype=float
    )
    used_disp_min = np.full((nb_rows, nb_cols), 0)
    used_disp_max = np.full((nb_rows, nb_cols), 0)

    row_max = np.max(grid[:, :, 1])
    col_max = np.max(grid[:, :, 3])

    for j in range(0, nb_cols):
        for i in range(0, nb_rows):
            row_up = grid[i, j, 0]
            row_down = grid[i, j, 1]
            col_left = grid[i, j, 2]
            col_right = grid[i, j, 3]

            margins_dataset = margins_fun(row_up, row_down, col_left, col_right)
            margins_left = margins_dataset["left_margin"]
            margins_right = margins_dataset["right_margin"]
            if "disp_min" in margins_dataset.attrs:
                if margins_dataset.attrs["disp_min"] is not None:
                    used_disp_min[i, j] = margins_dataset.attrs["disp_min"]
                if margins_dataset.attrs["disp_max"] is not None:
                    used_disp_max[i, j] = margins_dataset.attrs["disp_max"]

            # fill left
            fill_overlap(
                cars_ds_overlaps_left,
                margins_left,
                row_up,
                row_max,
                row_down,
                col_left,
                col_max,
                col_right,
            )
            # fill right
            fill_overlap(
                cars_ds_overlaps_right,
                margins_right,
                row_up,
                row_max,
                row_down,
                col_left,
                col_max,
                col_right,
            )

    return (
        cars_ds_overlaps_left,
        cars_ds_overlaps_right,
        used_disp_min,
        used_disp_max,
    )


[docs] def get_corresponding_indexes(row, col): """ Get point cloud tiling grid indexes, corresponding to given raster indexes. In rasterio convention. :param row: row :type row: int :param col: col :type col: int :return: corresponding indexes (row, col) :rtype: tuple(int, int) """ pc_row = col pc_col = row return pc_row, pc_col
[docs] def terrain_coords_to_pix(point_cloud_cars_ds, resolution): """ Compute the tiling grid in pixels, from a tiling grid in geocoordinates :param point_cloud_cars_ds: point clouds :type point_cloud_cars_ds: CarsDataset :param resolution: resolution :type resolution: float :return: new tiling grid :rtype: np.ndarray """ raster_tiling_grid = np.empty( point_cloud_cars_ds.tiling_grid.shape ).transpose(1, 0, 2) for row in range(raster_tiling_grid.shape[0]): for col in range(raster_tiling_grid.shape[1]): # get corresponding tile in point cloud pc_row, pc_col = get_corresponding_indexes(row, col) # Get window window_dict = point_cloud_cars_ds.get_window_as_dict( pc_row, pc_col, from_terrain=True, resolution=resolution, ) # apply window raster_tiling_grid[row, col, :] = [ window_dict["row_min"], window_dict["row_max"], window_dict["col_min"], window_dict["col_max"], ] return raster_tiling_grid
[docs] def region_margins_from_window( window, left_overlaps, right_overlaps, used_disp_min=None, used_disp_max=None, ): """ Convert window to margins. Add used disp min and max used for resampling :param window: window to use :type window: Dict :param left_overlaps: left overlap to use :type left_overlaps: Dict :param right_overlaps: right overlap to use :type right_overlaps: Dict :param used_disp_min: min disp min used in resampling :param used_disp_max: max disp max used in resampling :return: Region, Margin :rtype: Tuple(List, List) """ # margin : 'left', 'up', 'right', 'down' left_margin = [ abs(left_overlaps["left"]), abs(left_overlaps["up"]), abs(left_overlaps["right"]), abs(left_overlaps["down"]), ] right_margin = [ abs(right_overlaps["left"]), abs(right_overlaps["up"]), abs(right_overlaps["right"]), abs(right_overlaps["down"]), ] # Generate margin dataset corner = ["left", "up", "right", "down"] col = np.arange(len(corner)) margin = xr.Dataset( { "left_margin": (["col"], np.array(left_margin)), "right_margin": (["col"], np.array(right_margin)), }, coords={"col": col}, ) # add disp min and max margin.attrs["disp_min"] = used_disp_min margin.attrs["disp_max"] = used_disp_max # region : xmin, ymin, xmax, ymax # window : row_min, row_max, col_min, col_max region = [ window["col_min"], window["row_min"], window["col_max"], window["row_max"], ] return region, margin
[docs] def reduce_overlap(current_overlaps, new_margin): """ Reduce overlap with margin :param current_overlaps: overlap array :type current_overlaps: np.ndarray :param new_margin: margin to use :type new_margin: int :return: new overlap array """ new_overlap = np.full(current_overlaps.shape, new_margin) # The new overlap cannot be more than current new_overlap = np.clip(new_overlap, 0, current_overlaps) return new_overlap