Skip to content

interpolation

interpolate(ifg, weights, weight_cutoff=0.5, num_neighbors=20, max_radius=51, min_radius=0, alpha=0.75)

Interpolate a complex interferogram based on pixel weights.

Build upon persistent scatterer interpolation used in [Chen et al., 2015] and [Wang and Chen, 2022] by allowing floating-point weights instead of 0/1 PS weights.

Chen et al., 2015

Chen J., Zebker H.A. and Knight R., 2015. A Persistent Scatterer Interpolation for Retrieving Accurate Ground Deformation over InSAR-decorrelated Agricultural Fields. Geophysical Research Letters. 42, pp.9294--9301. 10.1002/2015GL065031

Wang and Chen, 2022

Wang K. and Chen J., 2022. Accurate Persistent Scatterer Identification Based on Phase Similarity of Radar Pixels. IEEE Transactions on Geoscience and Remote Sensing. 60, pp.1--13. 10.1109/TGRS.2022.3210868

Parameters:

Name Type Description Default
ifg np.ndarray, 2D complex array

wrapped interferogram to interpolate

required
weights 2D float array

Array of weights from 0 to 1 indicating how strongly to weigh the ifg values when interpolating. A special case of this is a PS mask where weights[i,j] = True if radar pixel (i,j) is a PS weights[i,j] = False if radar pixel (i,j) is not a PS Can also pass a coherence image to use as weights.

required
weight_cutoff float

Threshold to use on weights so that pixels where weight[i, j] < weight_cutoff have phase values replaced by an interpolated value. The default is 0.5: pixels with weight less than 0.5 are replaced with a smoothed version of the surrounding pixels.

0.5
num_neighbors int

number of nearest PS pixels used for interpolation num_neighbors = 20 by default

20
max_radius int(optional)

maximum radius (in pixels) for PS searching max_radius = 51 by default

51
min_radius int(optional)

minimum radius (in pixels) for PS searching max_radius = 0 by default

0
alpha float(optional)

hyperparameter controlling the weight of PS in interpolation: smaller alpha means more weight is assigned to PS closer to the center pixel. alpha = 0.75 by default

0.75

Returns:

Name Type Description
interpolated_ifg 2D complex array

interpolated interferogram with the same amplitude, but different wrapped phase at non-ps pixels.

Source code in src/dolphin/interpolation.py
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
def interpolate(
    ifg: ArrayLike,
    weights: ArrayLike,
    weight_cutoff: float = 0.5,
    num_neighbors: int = 20,
    max_radius: int = 51,
    min_radius: int = 0,
    alpha: float = 0.75,
) -> np.ndarray:
    """Interpolate a complex interferogram based on pixel weights.

    Build upon persistent scatterer interpolation used in
    [@Chen2015PersistentScattererInterpolation] and
    [@Wang2022AccuratePersistentScatterer] by allowing floating-point weights
    instead of 0/1 PS weights.

    Parameters
    ----------
    ifg : np.ndarray, 2D complex array
        wrapped interferogram to interpolate
    weights : 2D float array
        Array of weights from 0 to 1 indicating how strongly to weigh
        the ifg values when interpolating.
        A special case of this is a PS mask where
            weights[i,j] = True if radar pixel (i,j) is a PS
            weights[i,j] = False if radar pixel (i,j) is not a PS
        Can also pass a coherence image to use as weights.
    weight_cutoff: float
        Threshold to use on `weights` so that pixels where
        `weight[i, j] < weight_cutoff` have phase values replaced by
        an interpolated value.
        The default is 0.5: pixels with weight less than 0.5 are replaced with a
        smoothed version of the surrounding pixels.
    num_neighbors: int (optional)
        number of nearest PS pixels used for interpolation
        num_neighbors = 20 by default
    max_radius : int (optional)
        maximum radius (in pixels) for PS searching
        max_radius = 51 by default
    min_radius : int (optional)
        minimum radius (in pixels) for PS searching
        max_radius = 0 by default
    alpha : float (optional)
        hyperparameter controlling the weight of PS in interpolation: smaller
        alpha means more weight is assigned to PS closer to the center pixel.
        alpha = 0.75 by default

    Returns
    -------
    interpolated_ifg : 2D complex array
        interpolated interferogram with the same amplitude, but different
        wrapped phase at non-ps pixels.

    """
    nrow, ncol = weights.shape
    ifg_is_valid_mask = ifg != 0

    weights_float = np.clip(weights.astype(np.float32), 0, 1)
    # Ensure weights are between 0 and 1
    if np.any(weights_float > 1):
        logger.warning("weights array has values greater than 1. Clipping to 1.")
    if np.any(weights_float < 0):
        logger.warning("weights array has negative values. Clipping to 0.")
    weights_float = np.clip(weights_float, 0, 1)

    interpolated_ifg = np.zeros((nrow, ncol), dtype=np.complex64)

    indices = np.array(
        get_circle_idxs(max_radius, min_radius=min_radius, sort_output=False)
    )

    _interp_loop(
        ifg,
        weights_float,
        weight_cutoff,
        ifg_is_valid_mask,
        num_neighbors,
        alpha,
        indices,
        interpolated_ifg,
    )
    return interpolated_ifg