Source code for geoh5py.shared.conversion.geo_image

#  Copyright (c) 2024 Mira Geoscience Ltd.
#
#  This file is part of geoh5py.
#
#  geoh5py is free software: you can redistribute it and/or modify
#  it under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  geoh5py is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public License
#  along with geoh5py.  If not, see <https://www.gnu.org/licenses/>.

from __future__ import annotations

from typing import TYPE_CHECKING

import numpy as np
from PIL import Image

from ... import objects
from .base import BaseConversion


if TYPE_CHECKING:
    from ...objects import GeoImage, Grid2D


[docs] class GeoImageConversion(BaseConversion): """ Convert a :obj:'geoh5py.objects.geo_image.GeoImage' object. """
[docs] @staticmethod def convert_to_grid2d_reference(geoimage: GeoImage, grid2d_attributes) -> dict: """ Extract the geographic information from the entity. """ if geoimage.vertices is None or geoimage.default_vertices is None: raise AttributeError("GeoImage has no vertices.") # get geographic information grid2d_attributes["origin"] = np.asarray( tuple(geoimage.vertices[3]), dtype=[("x", float), ("y", float), ("z", float)], ) grid2d_attributes["u_count"] = geoimage.default_vertices[1, 0].astype(np.int32) grid2d_attributes["v_count"] = geoimage.default_vertices[0, 1].astype(np.int32) # Compute the distances distance_u = np.linalg.norm(geoimage.vertices[2] - geoimage.vertices[3]) distance_v = np.linalg.norm(geoimage.vertices[0] - geoimage.vertices[3]) # Now compute the cell sizes grid2d_attributes["u_cell_size"] = distance_u / grid2d_attributes["u_count"] grid2d_attributes["v_cell_size"] = distance_v / grid2d_attributes["v_count"] grid2d_attributes["elevation"] = grid2d_attributes.get("elevation", 0) if geoimage.rotation is not None: grid2d_attributes["rotation"] = geoimage.rotation if geoimage.dip is not None: grid2d_attributes["dip"] = geoimage.dip return grid2d_attributes
[docs] @staticmethod def add_gray_data(values: np.ndarray, output: Grid2D): """ Send the image as gray in the new :obj:'geoh5py.objects.grid2d.Grid2D'. :param values: Input image values as an array of int. :param output: the new :obj:'geoh5py.objects.grid2d.Grid2D'. """ if values.ndim != 2: raise ValueError("To export to gray image, the array must be 2d. ") output.add_data( data={ "band[0]": { "values": values[::-1].flatten(), "association": "CELL", } } )
[docs] @staticmethod def add_color_data(values: np.ndarray, output: Grid2D): """ Send the image color bands to data. :param values: Input image values as an array of int. :param output: the new :obj:'geoh5py.objects.grid2d.Grid2D'. """ if values.ndim != 3: raise IndexError("To export to color image, the array must be 3d.") for ind in range(values.shape[2]): output.add_data( { f"band[{ind}]": { "values": values[::-1, :, ind].flatten(), "association": "CELL", } } )
[docs] @staticmethod def add_data_2dgrid(geoimage: Image, output: Grid2D): """ Select the type of the image transformation. :param geoimage: :obj:'geoh5py.objects.geo_image.GeoImage' object. :param output: the new :obj:'geoh5py.objects.grid2d.Grid2D'. """ values = np.asarray(geoimage) if values.ndim == 2: GeoImageConversion.add_gray_data(values, output) else: GeoImageConversion.add_color_data(values, output)
[docs] @staticmethod def to_grid2d( geoimage: GeoImage, mode: str | None, copy_children=True, **grid2d_kwargs, ) -> Grid2D: """ Transform the :obj:'geoh5py.objects.image.Image' to a :obj:'geoh5py.objects.grid2d.Grid2D'. :param geoimage: :obj:'geoh5py.objects.geo_image.GeoImage' object. :param mode: The outgoing image mode option. :return: the new :obj:'geoh5py.objects.grid2d.Grid2D'. """ workspace, grid2d_kwargs = GeoImageConversion.validate_workspace( geoimage, **grid2d_kwargs ) grid2d_kwargs = GeoImageConversion.verify_kwargs(geoimage, **grid2d_kwargs) grid2d_kwargs = GeoImageConversion.convert_to_grid2d_reference( geoimage, grid2d_kwargs ) output = objects.Grid2D.create( workspace, **grid2d_kwargs, ) if geoimage.image is not None: image = geoimage.image.copy() if mode is not None and mode != image.mode: image = image.convert(mode if mode != "GRAY" else "L") if copy_children: GeoImageConversion.add_data_2dgrid(image, output) return output