File size: 2,024 Bytes
9875bf8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
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
76
77
78
79
80
"""Preprocessing utilities for satellite imagery."""

import numpy as np
import cv2
from typing import Optional


def preprocess_image(
    image: np.ndarray,
    target_size: Optional[tuple] = None,
    normalize: bool = True
) -> np.ndarray:
    """
    Preprocess a satellite image for model input.

    Args:
        image: Input image (H, W, C), uint8 or float
        target_size: Optional (width, height) to resize to
        normalize: If True, output is float32 in [0, 1]

    Returns:
        Preprocessed image as float32 [0,1] or uint8 [0,255]
    """
    if image is None:
        raise ValueError("Input image is None")

    img = image.copy()

    # Ensure 3-channel
    if img.ndim == 2:
        img = np.stack([img, img, img], axis=-1)
    elif img.shape[2] == 1:
        img = np.concatenate([img, img, img], axis=-1)
    elif img.shape[2] > 3:
        img = img[:, :, :3]

    # Resize if requested
    if target_size is not None:
        img = cv2.resize(img, target_size, interpolation=cv2.INTER_LINEAR)

    # Normalise
    if normalize:
        if img.dtype == np.uint8:
            img = img.astype(np.float32) / 255.0
        else:
            img = np.clip(img, 0, 1).astype(np.float32)
    else:
        if img.dtype != np.uint8:
            img = (np.clip(img, 0, 1) * 255).astype(np.uint8)

    return img


def mask_clouds(
    image: np.ndarray,
    cloud_mask: np.ndarray,
    fill_value: float = 0.0
) -> np.ndarray:
    """
    Apply cloud mask to image, replacing cloud pixels with fill_value.

    Args:
        image: Input image (H, W, C)
        cloud_mask: Binary mask (H, W), 1 = cloud
        fill_value: Value to fill masked pixels with

    Returns:
        Masked image same dtype as input
    """
    masked = image.copy().astype(np.float32)
    mask_bool = cloud_mask.astype(bool)

    for c in range(masked.shape[2]):
        masked[:, :, c][mask_bool] = fill_value

    if image.dtype == np.uint8:
        masked = np.clip(masked, 0, 255).astype(np.uint8)

    return masked