|
@@ -27,27 +27,31 @@ __all__ = [
|
|
|
]
|
|
|
|
|
|
EPS = 1e-32
|
|
|
-
|
|
|
-# | Band name | Description |
|
|
|
-# |-----------|-------------|
|
|
|
-# | b | Blue |
|
|
|
-# | g | Green |
|
|
|
-# | r | Red |
|
|
|
-# | re1 | Red Edge 1 |
|
|
|
-# | re2 | Red Edge 2 |
|
|
|
-# | re3 | Red Edge 3 |
|
|
|
-# | n | NIR |
|
|
|
-# | n2 | NIR 2 |
|
|
|
-# | s1 | SWIR 1 |
|
|
|
-# | s2 | SWIR 2 |
|
|
|
-# | t1 | Thermal 1 |
|
|
|
-# | t2 | Thermal 2 |
|
|
|
+BAND_NAMES = ["b", "g", "r", "re1", "re2", "re3", "n", "s1", "s2", "t1", "t2"]
|
|
|
+
|
|
|
+# | Band name | Description | Wavelength (μm) | Satellite |
|
|
|
+# |-----------|-------------|-----------------|-----------|
|
|
|
+# | b | Blue | 0.450-0.515 | Landsat8 |
|
|
|
+# | g | Green | 0.525-0.600 | Landsat8 |
|
|
|
+# | r | Red | 0.630-0.680 | Landsat8 |
|
|
|
+# | re1 | Red Edge 1 | 0.698-0.713 | Sentinel2 |
|
|
|
+# | re2 | Red Edge 2 | 0.733-0.748 | Sentinel2 |
|
|
|
+# | re3 | Red Edge 3 | 0.773-0.793 | Sentinel2 |
|
|
|
+# | n | NIR | 0.845-0.885 | Landsat8 |
|
|
|
+# | s1 | SWIR 1 | 1.560-1.660 | Landsat8 |
|
|
|
+# | s2 | SWIR 2 | 2.100-2.300 | Landsat8 |
|
|
|
+# | t1 | Thermal 1 | 10.60-11.19 | Landsat8 |
|
|
|
+# | t2 | Thermal 2 | 11.50-12.51 | Landsat8 |
|
|
|
|
|
|
|
|
|
class RSIndex(metaclass=abc.ABCMeta):
|
|
|
def __init__(self, band_indices):
|
|
|
super(RSIndex, self).__init__()
|
|
|
self.band_indices = band_indices
|
|
|
+ self.required_band_names = iintersection(
|
|
|
+ self._compute.__code__.co_varnames[1:], # strip self
|
|
|
+ BAND_NAMES # only save band names
|
|
|
+ )
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
def _compute(self, *args, **kwargs):
|
|
@@ -55,19 +59,40 @@ class RSIndex(metaclass=abc.ABCMeta):
|
|
|
|
|
|
def __call__(self, image):
|
|
|
bands = self.select_bands(image)
|
|
|
+ now_band_names = tuple(bands.keys())
|
|
|
+ if not iequal(now_band_names, self.required_band_names):
|
|
|
+ raise LackBandError("Lack of bands: {}.".format(
|
|
|
+ isubtraction(self.required_band_names, now_band_names)))
|
|
|
return self._compute(**bands)
|
|
|
|
|
|
def select_bands(self, image, to_float32=True):
|
|
|
bands = {}
|
|
|
for name, idx in self.band_indices.items():
|
|
|
- if idx == 0:
|
|
|
- raise ValueError("Band index starts from 1.")
|
|
|
- bands[name] = image[..., idx - 1]
|
|
|
- if to_float32:
|
|
|
- bands[name] = bands[name].astype('float32')
|
|
|
+ if name in self.required_band_names:
|
|
|
+ if idx == 0:
|
|
|
+ raise ValueError("Band index starts from 1.")
|
|
|
+ bands[name] = image[..., idx - 1]
|
|
|
+ if to_float32:
|
|
|
+ bands[name] = bands[name].astype('float32')
|
|
|
return bands
|
|
|
|
|
|
|
|
|
+class LackBandError(Exception):
|
|
|
+ pass
|
|
|
+
|
|
|
+
|
|
|
+def iintersection(iter1, iter2):
|
|
|
+ return tuple(set(iter1) & set(iter2))
|
|
|
+
|
|
|
+
|
|
|
+def isubtraction(iter1, iter2):
|
|
|
+ return tuple(set(iter1) - set(iter2))
|
|
|
+
|
|
|
+
|
|
|
+def iequal(iter1, iter2):
|
|
|
+ return set(iter1) == set(iter2)
|
|
|
+
|
|
|
+
|
|
|
def compute_normalized_difference_index(band1, band2):
|
|
|
return (band1 - band2) / (band1 + band2 + EPS)
|
|
|
|