Skip to content

Commit eab33f1

Browse files
committed
Theia glint corrected
1 parent e43b810 commit eab33f1

5 files changed

Lines changed: 57 additions & 31 deletions

File tree

waterdetect/Common.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
from shutil import copy
33
import configparser
44
import ast
5-
65
from sklearn.model_selection import train_test_split
7-
from sklearn.preprocessing import MinMaxScaler
6+
from sklearn.preprocessing import MinMaxScaler, RobustScaler
87
from sklearn.preprocessing import QuantileTransformer
98
from waterdetect import DWProducts, gdal
109

@@ -449,6 +448,24 @@ def calc_normalized_difference(img1, img2, mask=None, compress_cte=0.02):
449448

450449
return nd.filled(), nd.mask
451450

451+
@staticmethod
452+
def calc_mbwi(bands, factor, mask):
453+
# changement for negative SRE values scene
454+
min_cte = np.min([np.min(bands['Green'][~mask]), np.min(bands['Red'][~mask]),
455+
np.min(bands['Nir'][~mask]), np.min(bands['Mir'][~mask]), np.min(bands['Mir2'][~mask])])
456+
if min_cte <= 0:
457+
min_cte = -min_cte + 0.001
458+
else:
459+
min_cte = 0
460+
mbwi = factor * (bands['Green'] + min_cte) - (bands['Red'] + min_cte) - (bands['Nir'] + min_cte) \
461+
- (bands['Mir'] + min_cte) - (bands['Mir2'] + min_cte)
462+
mbwi[~mask] = RobustScaler(copy=False).fit_transform(mbwi[~mask].reshape(-1, 1)).reshape(-1)
463+
mbwi[~mask] = MinMaxScaler(feature_range=(-1, 1), copy=False).fit_transform(mbwi[~mask].reshape(-1, 1)) \
464+
.reshape(-1)
465+
mask = np.isinf(mbwi) | np.isnan(mbwi) | mask
466+
mbwi = np.ma.array(mbwi, mask=mask, fill_value=-9999)
467+
return mbwi, mask
468+
452469
@staticmethod
453470
def rgb_burn_in(red, green, blue, burn_in_array, color=None, min_value=None, max_value=None, colormap='viridis',
454471
fade=1, uniform_distribution=False, no_data_value=-9999, valid_value=1, transp=0.0):

waterdetect/Glint.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,32 @@
55

66

77
class DWGlintProcessor:
8+
supported_products = ['S2_S2COR', 'S2_THEIA']
9+
810
def __init__(self, image, limit_angle=30):
11+
912
self.image = image
1013
self.limit_angle = limit_angle
1114
self.adjustable_bands = ['Mir', 'Mir2', 'Nir', 'Nir2']
1215

1316
try:
14-
self.glint_array = self.create_glint_array(self.image.metadata)
17+
self.glint_array = self.create_glint_array(self.image.metadata, image.product)
1518

1619
except BaseException as err:
1720
self.glint_array = None
1821
print(f'### GLINT PROCESSOR ERROR #####')
1922
print(err)
2023

24+
@classmethod
25+
def create(cls, image, limit_angle=30):
26+
if image.product not in cls.supported_products:
27+
print(f'Product {image.product} not supported by GlintProcessor')
28+
print(f'Supported products: {cls.supported_products}')
29+
return None
30+
else:
31+
return cls(image, limit_angle)
32+
33+
2134
@staticmethod
2235
def get_grid_values_from_xml(tree_node, xpath_str):
2336
"""Receives a XML tree node and a XPath parsing string and search for children matching the string.
@@ -35,14 +48,16 @@ def get_grid_values_from_xml(tree_node, xpath_str):
3548
return np.nanmean(arrays_lst, axis=0)
3649

3750
@staticmethod
38-
def create_glint_array(xml_file):
51+
def create_glint_array(xml_file, product):
3952
xml_file = Path(xml_file)
4053
parser = etree.XMLParser()
4154
root = etree.parse(xml_file.as_posix(), parser).getroot()
4255

43-
sun_zenith = np.deg2rad(DWGlintProcessor.get_grid_values_from_xml(root, './/Sun_Angles_Grid/Zenith'))[:-1, :-1]
44-
sun_azimuth = np.deg2rad(DWGlintProcessor.get_grid_values_from_xml(root, './/Sun_Angles_Grid/Azimuth'))[:-1,
45-
:-1]
56+
sun_angles = 'Sun_Angles_Grid' if product == 'S2_S2COR' else 'Sun_Angles_Grids'
57+
# viewing_angles = 'Viewing_Incidence_Angles_Grids'
58+
59+
sun_zenith = np.deg2rad(DWGlintProcessor.get_grid_values_from_xml(root, f'.//{sun_angles}/Zenith'))[:-1, :-1]
60+
sun_azimuth = np.deg2rad(DWGlintProcessor.get_grid_values_from_xml(root, f'.//{sun_angles}/Azimuth'))[:-1,:-1]
4661

4762
view_zenith = np.deg2rad(
4863
DWGlintProcessor.get_grid_values_from_xml(root, './/Viewing_Incidence_Angles_Grids/Zenith'))[:-1, :-1]

waterdetect/Image.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ def check_necessary_bands(self, bands, bands_keys, invalid_mask):
6666
invalid_mask |= ndwi_mask
6767
bands.update({'ndwi': ndwi})
6868

69+
# check if the MBWI index exist
70+
if 'mbwi' not in bands.keys():
71+
mbwi, mbwi_mask = DWutils.calc_mbwi(bands, 3, invalid_mask)
72+
invalid_mask |= ndwi_mask
73+
bands.update({'mbwi': mbwi})
74+
6975
# todo: check the band for Principal Component Analysis
7076

7177
# check if the list contains the required bands
@@ -649,7 +655,7 @@ def apply_clustering(self):
649655

650656
for band, value in zip(self.config.clip_band, self.config.clip_sup_value):
651657
if value is not None:
652-
if self.config.glint_mode:
658+
if self.config.glint_mode and (self.glint_processor is not None):
653659
comp_array = self.glint_processor.glint_adjusted_threshold(band,
654660
value,
655661
'SUP',
@@ -663,7 +669,7 @@ def apply_clustering(self):
663669
# after obtaining the final labels, clip bands with inferior limit
664670
for band, value in zip(self.config.clip_band, self.config.clip_inf_value):
665671
if value is not None:
666-
if self.config.glint_mode:
672+
if self.config.glint_mode and (self.glint_processor is not None):
667673
comp_array = self.glint_processor.glint_adjusted_threshold(band,
668674
value,
669675
'INF',

waterdetect/WaterDetect.py

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -137,24 +137,7 @@ def calc_mbwi(self, bands, factor=3, save_index=False):
137137

138138
mask = self.loader.invalid_mask
139139

140-
# changement for negative SRE values scene
141-
min_cte = np.min([np.min(bands['Green'][~mask]), np.min(bands['Red'][~mask]),
142-
np.min(bands['Nir'][~mask]), np.min(bands['Mir'][~mask]), np.min(bands['Mir2'][~mask])])
143-
144-
if min_cte <= 0:
145-
min_cte = -min_cte + 0.001
146-
else:
147-
min_cte = 0
148-
149-
mbwi = factor * (bands['Green']+min_cte) - (bands['Red']+min_cte) - (bands['Nir']+min_cte)\
150-
- (bands['Mir']+min_cte) - (bands['Mir2']+min_cte)
151-
152-
mbwi[~mask] = RobustScaler(copy=False).fit_transform(mbwi[~mask].reshape(-1, 1)).reshape(-1)
153-
mbwi[~mask] = MinMaxScaler(feature_range=(-1, 1), copy=False).fit_transform(mbwi[~mask].reshape(-1, 1))\
154-
.reshape(-1)
155-
156-
mask = np.isinf(mbwi) | np.isnan(mbwi) | self.loader.invalid_mask
157-
mbwi = np.ma.array(mbwi, mask=mask, fill_value=-9999)
140+
mbwi, mask = DWutils.calc_mbwi(bands, factor, mask)
158141

159142
self.loader.update_mask(mask)
160143

@@ -165,6 +148,7 @@ def calc_mbwi(self, bands, factor=3, save_index=False):
165148

166149
return mbwi.filled()
167150

151+
168152
def calc_awei(self, bands, save_index=False):
169153
"""
170154
Calculates the AWEI Water Index and adds it to the bands dictionary
@@ -373,12 +357,16 @@ def create_mask_report(self, image, band_combination, composite_name, pdf_merger
373357
# calculate the sun glint rejection and add it to the pdf report
374358
# the glint will be passed to the
375359
if self.config.calc_glint:
376-
glint_processor = DWGlintProcessor(image)
377-
pdf_merger_image.append(glint_processor.save_heatmap(self.saver.output_folder))
360+
glint_processor = DWGlintProcessor.create(image)
361+
362+
# if there is a valid glint_processor, save the heatmap
363+
if glint_processor is not None:
364+
pdf_merger_image.append(glint_processor.save_heatmap(self.saver.output_folder))
365+
else:
366+
print(f'Glint_mode is On but no Glint Processor is available for this product')
378367

379368
else:
380369
glint_processor = None
381-
# self.calc_glint(image, self.saver.output_folder, pdf_merger_image)
382370

383371
# create a dw_image object with the water mask and all the results
384372
dw_image = self.create_water_mask(band_combination, pdf_merger_image, glint_processor=glint_processor)

waterdetect/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# todo: Implement logging
22
# import logging
3-
__version__ = '1.5.7'
3+
__version__ = '1.5.8'
44

55
class DWProducts:
66
Landsat8_USGS = 'L8_USGS'

0 commit comments

Comments
 (0)