Skip to content

Handlers API

obia.handlers.geotif

obia.handlers.geotif

Image

Image A class for handling geographic raster image data, providing utilities to manage its properties and to convert it into visualization formats.

Attributes

img_data : numpy.ndarray The image data array. crs : str or dict Coordinate reference system of the image. transform : affine.Affine Affine transformation matrix. affine_transformation : affine.Affine Deprecated attribute for affine transformation. rasterio_obj : rasterio.io.DatasetReader Rasterio dataset object for the image.

Methods

init(self, img_data, crs, affine_transformation, transform, rasterio_obj) Constructs all the necessary attributes for the Image object. to_image(self, bands) Converts specified bands of the image into an RGB image.

Source code in obia/handlers/geotif.py
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
class Image:
    """
        Image
        A class for handling geographic raster image data, providing utilities to manage its properties and to convert it into visualization formats.

        Attributes
        ----------
        img_data : numpy.ndarray
            The image data array.
        crs : str or dict
            Coordinate reference system of the image.
        transform : affine.Affine
            Affine transformation matrix.
        affine_transformation : affine.Affine
            Deprecated attribute for affine transformation.
        rasterio_obj : rasterio.io.DatasetReader
            Rasterio dataset object for the image.

        Methods
        -------
        __init__(self, img_data, crs, affine_transformation, transform, rasterio_obj)
            Constructs all the necessary attributes for the Image object.
        to_image(self, bands)
            Converts specified bands of the image into an RGB image.
    """
    img_data = None
    crs = None
    transform = None
    affine_transformation = None
    rasterio_obj = None

    def __init__(self, img_data, crs, affine_transformation, transform, rasterio_obj):
        self.img_data = img_data
        self.crs = crs
        self.affine_transformation = affine_transformation
        self.transform = transform
        self.rasterio_obj = rasterio_obj

    def to_image(self, bands, p_min=2, p_max=98, stretch_type=None):
        """
        always applies a linear stretch
        :param bands: A list or tuple of three integers representing the indices of the bands to use for the RGB image.
        :param p_min: Minimum percentile for rescaling.
        :param p_max: Maximum percentile for rescaling.
        :param stretch_type: Type of contrast stretching to apply ("linear", "histogram_equalization", "clahe").
        :return: A rescaled and contrast-stretched RGB image.
        """
        if not isinstance(bands, (list, tuple)) or len(bands) != 3:
            raise ValueError("'bands' should be a list or tuple of exactly three elements")

        num_bands = self.img_data.shape[2]
        rgb_data = np.empty((self.img_data.shape[0], self.img_data.shape[1], 3), dtype=np.float32)

        for i, band in enumerate(bands):
            if band >= num_bands or band < 0:
                raise IndexError(f"Band index {band} out of range. Available bands indices: 0 to {num_bands - 1}.")
            rgb_data[:, :, i] = self.img_data[:, :, band]

        rgb_data_rescaled = rescale_to_8bit(rgb_data, min=p_min, max=p_max)

        if stretch_type == "histogram_equalization":
            rgb_data_rescaled = apply_histogram_equalization(rgb_data_rescaled)
        elif stretch_type == "clahe":
            rgb_data_rescaled = apply_clahe(rgb_data_rescaled)
        elif stretch_type != None:
            raise ValueError(f"Unknown stretch_type: {stretch_type}")

        return fromarray(rgb_data_rescaled.astype(np.uint8))

to_image(bands, p_min=2, p_max=98, stretch_type=None)

always applies a linear stretch :param bands: A list or tuple of three integers representing the indices of the bands to use for the RGB image. :param p_min: Minimum percentile for rescaling. :param p_max: Maximum percentile for rescaling. :param stretch_type: Type of contrast stretching to apply ("linear", "histogram_equalization", "clahe"). :return: A rescaled and contrast-stretched RGB image.

Source code in obia/handlers/geotif.py
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
def to_image(self, bands, p_min=2, p_max=98, stretch_type=None):
    """
    always applies a linear stretch
    :param bands: A list or tuple of three integers representing the indices of the bands to use for the RGB image.
    :param p_min: Minimum percentile for rescaling.
    :param p_max: Maximum percentile for rescaling.
    :param stretch_type: Type of contrast stretching to apply ("linear", "histogram_equalization", "clahe").
    :return: A rescaled and contrast-stretched RGB image.
    """
    if not isinstance(bands, (list, tuple)) or len(bands) != 3:
        raise ValueError("'bands' should be a list or tuple of exactly three elements")

    num_bands = self.img_data.shape[2]
    rgb_data = np.empty((self.img_data.shape[0], self.img_data.shape[1], 3), dtype=np.float32)

    for i, band in enumerate(bands):
        if band >= num_bands or band < 0:
            raise IndexError(f"Band index {band} out of range. Available bands indices: 0 to {num_bands - 1}.")
        rgb_data[:, :, i] = self.img_data[:, :, band]

    rgb_data_rescaled = rescale_to_8bit(rgb_data, min=p_min, max=p_max)

    if stretch_type == "histogram_equalization":
        rgb_data_rescaled = apply_histogram_equalization(rgb_data_rescaled)
    elif stretch_type == "clahe":
        rgb_data_rescaled = apply_clahe(rgb_data_rescaled)
    elif stretch_type != None:
        raise ValueError(f"Unknown stretch_type: {stretch_type}")

    return fromarray(rgb_data_rescaled.astype(np.uint8))

open_binary_geotiff_as_mask(mask_path)

:param mask_path: Path to the binary GeoTIFF file to be opened. :return: A tuple containing the binary mask array, bounding box, affine transform, and profile of the raster.

Source code in obia/handlers/geotif.py
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
def open_binary_geotiff_as_mask(mask_path):
    """
    :param mask_path: Path to the binary GeoTIFF file to be opened.
    :return: A tuple containing the binary mask array, bounding box, affine transform, and profile of the raster.
    """
    with rasterio.open(mask_path) as src:
        mask_array = src.read(1).astype(bool)  # Read the mask as a binary array
        transform = src.transform  # Get the affine transform of the raster
        width, height = src.width, src.height  # Get the dimensions of the raster
        profile = src.profile  # Capture the profile to use later

        # Calculate the bounding box from the transform and dimensions
        left, top = transform * (0, 0)
        right, bottom = transform * (width, height)
        bbox = (left, bottom, right, top)

    return mask_array, bbox, transform, profile

open_geotiff(image_path, bands=None)

:param image_path: Path to the GeoTIFF file to be opened. :type image_path: str :param bands: List of band indices to be read from the GeoTIFF file. If None, all bands are read. :type bands: list of int, optional :return: An Image object containing the raster data, coordinate reference system, affine transformation matrix, and the original rasterio object. :rtype: Image

Source code in obia/handlers/geotif.py
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
def open_geotiff(image_path, bands=None):
    """
    :param image_path: Path to the GeoTIFF file to be opened.
    :type image_path: str
    :param bands: List of band indices to be read from the GeoTIFF file. If None, all bands are read.
    :type bands: list of int, optional
    :return: An Image object containing the raster data, coordinate reference system, affine transformation matrix, and the original rasterio object.
    :rtype: Image
    """
    rasterio_obj = rasterio.open(image_path)

    crs = rasterio_obj.crs
    transform = rasterio_obj.transform
    affine_transformation = [transform.a, transform.b, transform.d, transform.e, transform.c, transform.f]

    x_size = rasterio_obj.width
    y_size = rasterio_obj.height
    num_bands = rasterio_obj.count

    if bands is None:
        bands = list(range(1, num_bands + 1))

    data = np.empty((y_size, x_size, len(bands)), dtype=np.float32)

    for i, b in enumerate(bands):
        band_array = rasterio_obj.read(b)
        data[:, :, i] = band_array

    return Image(data, crs, affine_transformation, transform, rasterio_obj)