opticallyshallowdeep 1.2.0__tar.gz → 1.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {opticallyshallowdeep-1.2.0/opticallyshallowdeep.egg-info → opticallyshallowdeep-1.2.2}/PKG-INFO +18 -19
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/README.md +16 -17
- opticallyshallowdeep-1.2.2/opticallyshallowdeep/__init__.py +1 -0
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/check_transpose.py +1 -4
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/cloud_mask.py +1 -6
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/find_epsg.py +0 -19
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/make_multiband_image.py +0 -2
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/make_vertical_strips.py +1 -6
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/netcdf_to_multiband_geotiff.py +1 -5
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/parse_string.py +1 -3
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/process_as_strips.py +5 -22
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/run.py +5 -5
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/write_georef_image.py +1 -3
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2/opticallyshallowdeep.egg-info}/PKG-INFO +18 -19
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep.egg-info/requires.txt +1 -1
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/setup.py +2 -2
- opticallyshallowdeep-1.2.0/opticallyshallowdeep/__init__.py +0 -2
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/LICENSE +0 -0
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/MANIFEST.in +0 -0
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/models/SR.h5 +0 -0
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/models/TOA.h5 +0 -0
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep.egg-info/SOURCES.txt +0 -0
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep.egg-info/dependency_links.txt +0 -0
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep.egg-info/top_level.txt +0 -0
- {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/setup.cfg +0 -0
{opticallyshallowdeep-1.2.0/opticallyshallowdeep.egg-info → opticallyshallowdeep-1.2.2}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: opticallyshallowdeep
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: Identify optically shallow and deep waters in satellite imagery
|
|
5
5
|
Author: Yulun Wu
|
|
6
6
|
Author-email: yulunwu8@gmail.com
|
|
@@ -10,7 +10,7 @@ Description-Content-Type: text/markdown
|
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
Requires-Dist: geopandas
|
|
12
12
|
Requires-Dist: rasterio
|
|
13
|
-
Requires-Dist: tifffile
|
|
13
|
+
Requires-Dist: tifffile==2023.8.12
|
|
14
14
|
Requires-Dist: netCDF4
|
|
15
15
|
Requires-Dist: pyproj
|
|
16
16
|
Requires-Dist: joblib
|
|
@@ -23,12 +23,13 @@ Requires-Dist: tensorflow
|
|
|
23
23
|
|
|
24
24
|
This python tool delineates optically shallow and deep waters in Sentinel-2 imagery. The tool uses a deep neural network (DNN) that was trained on a diverse set of global images.
|
|
25
25
|
|
|
26
|
-
Supported input includes L1C SAFE files and ACOLITE-processed L2R netCDF files. The output geotiff contains probabilities of water pixels being optically shallow and deep.
|
|
26
|
+
Supported input includes Level-1C (L1C) SAFE files and ACOLITE-processed L2R netCDF files. The output geotiff contains probabilities of water pixels being optically shallow and deep.
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
**Home page:** <a href="https://github.com/yulunwu8/Optically-Shallow-Deep" target="_blank">https://github.com/yulunwu8/Optically-Shallow-Deep</a>
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
**Publication:** Richardson, G., Foreman, N., Knudby, A., Wu, Y., & Lin, Y. (2024). Global deep learning model for delineation of optically shallow and optically deep water in Sentinel-2 imagery. *Remote Sensing of Environment*, 311, 114302. <a href="https://doi.org/10.1016/j.rse.2024.114302" target="_blank">https://doi.org/10.1016/j.rse.2024.114302</a>
|
|
31
31
|
|
|
32
|
+
Originally coded by by Galen Richardson and Anders Knudby, modified and packaged by Yulun Wu
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
## Installation
|
|
@@ -47,26 +48,17 @@ For mac OS:
|
|
|
47
48
|
```bash
|
|
48
49
|
conda install -c apple tensorflow-deps
|
|
49
50
|
python -m pip install tensorflow-macos
|
|
50
|
-
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
|
|
54
|
-
For
|
|
54
|
+
For Windows and Linux:
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
57
|
pip3 install tensorflow==2.13.0
|
|
58
|
-
|
|
59
58
|
```
|
|
60
59
|
|
|
61
|
-
In case of compatibility issues, please try the newest version of tensorflow:
|
|
62
60
|
|
|
63
|
-
|
|
64
|
-
pip3 install --upgrade --force-reinstall tensorflow
|
|
65
|
-
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
For Linux and more on installing tensorflow: [https://www.tensorflow.org/install](https://www.tensorflow.org/install)
|
|
61
|
+
More on installing tensorflow: [https://www.tensorflow.org/install](https://www.tensorflow.org/install)
|
|
70
62
|
|
|
71
63
|
|
|
72
64
|
**3 - Install opticallyshallowdeep:**
|
|
@@ -106,16 +98,23 @@ file_L2R = 'test_folder_in/L2R.nc'
|
|
|
106
98
|
folder_out = 'folder/test_folder_out'
|
|
107
99
|
|
|
108
100
|
# Run the OSW/ODW classifier
|
|
109
|
-
osd.run(
|
|
101
|
+
osd.run(file_L1C, folder_out, file_L2R=file_L2R)
|
|
110
102
|
```
|
|
111
103
|
|
|
112
|
-
The L1C file is always required as it contains a cloud mask. Pixels within 8 pixels of the cloud mask are masked to reduce the impact of clouds.
|
|
104
|
+
The L1C file is always required as it contains a built-in cloud mask. Pixels within 8 pixels of the cloud mask are masked to reduce the impact of clouds.
|
|
113
105
|
|
|
114
106
|
|
|
115
|
-
Output is a 1-band geotiff, with values of prediction probability of OSW
|
|
107
|
+
Output is a 1-band geotiff, with values of prediction probability of optically shallow water (OSW): 100 means most likely OSW, 0 means most likely optically deep water (ODW). Non-water pixels are masked. It is recommended to treat pixels between 0 and 40 as ODW, and pixels between 60 and 100 as OSW (Richardson et al., 2024).
|
|
116
108
|
|
|
117
109
|
A log file, an intermediate multi-band geotiff, and a preview PNG are also generated in the output folder. They can be deleted after the processing.
|
|
118
110
|
|
|
111
|
+
|
|
112
|
+
**Sample Sentinel-2 scene and output:**
|
|
113
|
+
|
|
114
|
+
<img src="images/TOA.jpeg" height="500">
|
|
115
|
+
|
|
116
|
+
<img src="images/OSW.jpeg" height="500">
|
|
117
|
+
|
|
119
118
|
## Training, test, and validation data
|
|
120
119
|
|
|
121
120
|
All annotated shapefiles used in training, testing, and validating the DNN model are in the annotated_shapefiles folder, grouped by Sentinel-2 Scene ID.
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
This python tool delineates optically shallow and deep waters in Sentinel-2 imagery. The tool uses a deep neural network (DNN) that was trained on a diverse set of global images.
|
|
4
4
|
|
|
5
|
-
Supported input includes L1C SAFE files and ACOLITE-processed L2R netCDF files. The output geotiff contains probabilities of water pixels being optically shallow and deep.
|
|
5
|
+
Supported input includes Level-1C (L1C) SAFE files and ACOLITE-processed L2R netCDF files. The output geotiff contains probabilities of water pixels being optically shallow and deep.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**Home page:** <a href="https://github.com/yulunwu8/Optically-Shallow-Deep" target="_blank">https://github.com/yulunwu8/Optically-Shallow-Deep</a>
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
**Publication:** Richardson, G., Foreman, N., Knudby, A., Wu, Y., & Lin, Y. (2024). Global deep learning model for delineation of optically shallow and optically deep water in Sentinel-2 imagery. *Remote Sensing of Environment*, 311, 114302. <a href="https://doi.org/10.1016/j.rse.2024.114302" target="_blank">https://doi.org/10.1016/j.rse.2024.114302</a>
|
|
10
10
|
|
|
11
|
+
Originally coded by by Galen Richardson and Anders Knudby, modified and packaged by Yulun Wu
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
## Installation
|
|
@@ -26,26 +27,17 @@ For mac OS:
|
|
|
26
27
|
```bash
|
|
27
28
|
conda install -c apple tensorflow-deps
|
|
28
29
|
python -m pip install tensorflow-macos
|
|
29
|
-
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
For
|
|
33
|
+
For Windows and Linux:
|
|
34
34
|
|
|
35
35
|
```bash
|
|
36
36
|
pip3 install tensorflow==2.13.0
|
|
37
|
-
|
|
38
37
|
```
|
|
39
38
|
|
|
40
|
-
In case of compatibility issues, please try the newest version of tensorflow:
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
pip3 install --upgrade --force-reinstall tensorflow
|
|
44
|
-
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
For Linux and more on installing tensorflow: [https://www.tensorflow.org/install](https://www.tensorflow.org/install)
|
|
40
|
+
More on installing tensorflow: [https://www.tensorflow.org/install](https://www.tensorflow.org/install)
|
|
49
41
|
|
|
50
42
|
|
|
51
43
|
**3 - Install opticallyshallowdeep:**
|
|
@@ -85,16 +77,23 @@ file_L2R = 'test_folder_in/L2R.nc'
|
|
|
85
77
|
folder_out = 'folder/test_folder_out'
|
|
86
78
|
|
|
87
79
|
# Run the OSW/ODW classifier
|
|
88
|
-
osd.run(
|
|
80
|
+
osd.run(file_L1C, folder_out, file_L2R=file_L2R)
|
|
89
81
|
```
|
|
90
82
|
|
|
91
|
-
The L1C file is always required as it contains a cloud mask. Pixels within 8 pixels of the cloud mask are masked to reduce the impact of clouds.
|
|
83
|
+
The L1C file is always required as it contains a built-in cloud mask. Pixels within 8 pixels of the cloud mask are masked to reduce the impact of clouds.
|
|
92
84
|
|
|
93
85
|
|
|
94
|
-
Output is a 1-band geotiff, with values of prediction probability of OSW
|
|
86
|
+
Output is a 1-band geotiff, with values of prediction probability of optically shallow water (OSW): 100 means most likely OSW, 0 means most likely optically deep water (ODW). Non-water pixels are masked. It is recommended to treat pixels between 0 and 40 as ODW, and pixels between 60 and 100 as OSW (Richardson et al., 2024).
|
|
95
87
|
|
|
96
88
|
A log file, an intermediate multi-band geotiff, and a preview PNG are also generated in the output folder. They can be deleted after the processing.
|
|
97
89
|
|
|
90
|
+
|
|
91
|
+
**Sample Sentinel-2 scene and output:**
|
|
92
|
+
|
|
93
|
+
<img src="images/TOA.jpeg" height="500">
|
|
94
|
+
|
|
95
|
+
<img src="images/OSW.jpeg" height="500">
|
|
96
|
+
|
|
98
97
|
## Training, test, and validation data
|
|
99
98
|
|
|
100
99
|
All annotated shapefiles used in training, testing, and validating the DNN model are in the annotated_shapefiles folder, grouped by Sentinel-2 Scene ID.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .run import *
|
{opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/cloud_mask.py
RENAMED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
1
|
import os, sys
|
|
6
2
|
import rasterio
|
|
7
3
|
import numpy as np
|
|
@@ -99,5 +95,4 @@ def cloud_mask(file_L1C, buffer_size = 8):
|
|
|
99
95
|
mask_cloud_buffered = ndimage.binary_dilation(mask_cloud, structure=struct1,iterations=buffer_size).astype(mask_cloud.dtype)
|
|
100
96
|
|
|
101
97
|
print('Done')
|
|
102
|
-
return mask_cloud_buffered
|
|
103
|
-
|
|
98
|
+
return mask_cloud_buffered
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
1
|
def find_epsg(data):
|
|
4
2
|
|
|
5
3
|
# Use regex to extract the desired part
|
|
@@ -29,25 +27,8 @@ def find_epsg(data):
|
|
|
29
27
|
# return f"The EPSG code for '{crs_name}' is {epsg_code}."
|
|
30
28
|
return epsg_code
|
|
31
29
|
|
|
32
|
-
|
|
33
30
|
else:
|
|
34
31
|
print( "EPSG code could not be found.")
|
|
35
32
|
|
|
36
|
-
|
|
37
33
|
except Exception as e:
|
|
38
34
|
return f"An error occurred: {str(e)}"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
1
|
import numpy as np
|
|
4
|
-
|
|
5
|
-
|
|
6
2
|
def make_vertical_strips(full_img):
|
|
7
3
|
'''use to save ram, process bigger images faster, and it overlaps so middle image is not
|
|
8
4
|
distorted from how edge pixels are handled'''
|
|
@@ -30,5 +26,4 @@ def make_vertical_strips(full_img):
|
|
|
30
26
|
import sys
|
|
31
27
|
sys.exit('Unknown dimension(s) of input imagery to be splited into strips')
|
|
32
28
|
|
|
33
|
-
return [strip1,strip2,strip3,strip4,strip5]
|
|
34
|
-
|
|
29
|
+
return [strip1,strip2,strip3,strip4,strip5]
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
import os
|
|
3
2
|
import numpy as np
|
|
4
3
|
import rasterio
|
|
@@ -7,9 +6,7 @@ from rasterio.crs import CRS
|
|
|
7
6
|
from rasterio.transform import from_origin
|
|
8
7
|
import netCDF4 as nc4
|
|
9
8
|
# from pyproj import Proj, transform
|
|
10
|
-
|
|
11
9
|
import pyproj
|
|
12
|
-
|
|
13
10
|
from .find_epsg import find_epsg
|
|
14
11
|
|
|
15
12
|
def netcdf_to_multiband_geotiff(netcdf_file, folder_out):
|
|
@@ -87,5 +84,4 @@ def netcdf_to_multiband_geotiff(netcdf_file, folder_out):
|
|
|
87
84
|
|
|
88
85
|
print('Done')
|
|
89
86
|
|
|
90
|
-
return output_geotiff_file
|
|
91
|
-
|
|
87
|
+
return output_geotiff_file
|
{opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/parse_string.py
RENAMED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
1
|
import re
|
|
3
|
-
|
|
4
2
|
def parse_string(s):
|
|
5
3
|
if s.lower() in ["lat", "long", "lat_abs"]:
|
|
6
4
|
return [s.lower()]#parses the column names for our model and makes into things that our scripts can interpret
|
|
@@ -19,4 +17,4 @@ def parse_string(s):
|
|
|
19
17
|
first_group_int = first_group
|
|
20
18
|
return [first_group_int, int(groups[2]), groups[4]] if groups[4] else [first_group_int, int(groups[2]), None]
|
|
21
19
|
else:
|
|
22
|
-
return None
|
|
20
|
+
return None
|
{opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/process_as_strips.py
RENAMED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
import os, gc, warnings, math
|
|
3
2
|
import numpy as np
|
|
4
3
|
import pandas as pd
|
|
@@ -20,7 +19,6 @@ tf.compat.v1.logging.set_verbosity(tf.compat.v1.logging.ERROR)
|
|
|
20
19
|
|
|
21
20
|
from .make_vertical_strips import make_vertical_strips
|
|
22
21
|
|
|
23
|
-
|
|
24
22
|
def process_as_strips (full_img, image_path, if_SR, model_path, selected_columns, model_columns, file_in, cloud_list):
|
|
25
23
|
striplist=make_vertical_strips(full_img) #create a list of strips with overlap
|
|
26
24
|
RGBlist=[]
|
|
@@ -57,9 +55,7 @@ def process_img_to_rgb(img, file_path, if_SR, model_path, selected_columns, mode
|
|
|
57
55
|
gc.collect()
|
|
58
56
|
return RGB_img #this image is 0: OSW/ODW, 1:pred/prob, 2: Mask
|
|
59
57
|
|
|
60
|
-
|
|
61
58
|
def correct_baseline(img,file_path, if_SR, file_in):
|
|
62
|
-
|
|
63
59
|
from xml.dom import minidom
|
|
64
60
|
|
|
65
61
|
# if ACOLITE input
|
|
@@ -160,7 +156,6 @@ def get_water_pix_coord(img,correction, if_SR, img_cloud):
|
|
|
160
156
|
gc.collect()
|
|
161
157
|
return common_coordinates_list
|
|
162
158
|
|
|
163
|
-
|
|
164
159
|
def make_blank_img(img):
|
|
165
160
|
Y_b, X_b, b = img.shape #sometimes the image is all no data or the correction value, in this instance, we make a blank image
|
|
166
161
|
RGB_img = np.zeros((Y_b, X_b, 3), dtype=np.uint8)
|
|
@@ -171,7 +166,6 @@ def make_blank_img(img):
|
|
|
171
166
|
def time_tracker(start_time):
|
|
172
167
|
return "{}sec".format(round((datetime.now() - start_time).total_seconds(), 2))
|
|
173
168
|
|
|
174
|
-
|
|
175
169
|
def process_image_with_filters(img, selected_columns):
|
|
176
170
|
height, width, bands = img.shape#the output of this is an image of the filters required for this model
|
|
177
171
|
filter_list = [value for value in selected_columns if value not in [["lat"], ["long"], ["lat_abs"]]]
|
|
@@ -179,13 +173,15 @@ def process_image_with_filters(img, selected_columns):
|
|
|
179
173
|
for band, kernel_size, filter_type in filter_list:
|
|
180
174
|
|
|
181
175
|
if filter_type is None:
|
|
182
|
-
filtered_band = img[:, :, band]
|
|
176
|
+
filtered_band = img[:, :, band]
|
|
183
177
|
else:
|
|
184
178
|
with warnings.catch_warnings():
|
|
185
179
|
warnings.simplefilter("ignore", category=RuntimeWarning)
|
|
186
180
|
filtered_band = apply_filter(img[:, :, band].astype(np.float32), kernel_size, filter_type)
|
|
187
181
|
filtered_band[filtered_band==-32768] = 32768
|
|
188
|
-
|
|
182
|
+
|
|
183
|
+
filtered_band[filtered_band<0] = 0
|
|
184
|
+
filtered_band = filtered_band.astype(np.uint16)#this means it is a single pixel
|
|
189
185
|
|
|
190
186
|
output_bands.append(filtered_band)#append to list of filters
|
|
191
187
|
del filtered_band
|
|
@@ -351,7 +347,6 @@ def load_model_and_predict_pixels(value_list, model_path, cord_list, if_SR):
|
|
|
351
347
|
|
|
352
348
|
return cord_list.tolist(), pred_results.tolist(), con_1.tolist()
|
|
353
349
|
|
|
354
|
-
|
|
355
350
|
def load_tf_model(model_path, if_SR):
|
|
356
351
|
if if_SR == False:
|
|
357
352
|
model=d6_model(32,0.01)
|
|
@@ -420,16 +415,4 @@ def plot_RGB_img(RGB_img, image_path):
|
|
|
420
415
|
# plt.show()
|
|
421
416
|
|
|
422
417
|
out_path = image_path.replace('.tif','.png')
|
|
423
|
-
plt.savefig(out_path)
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
418
|
+
plt.savefig(out_path)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
import sys, os, gc, time
|
|
3
2
|
import tifffile as tif
|
|
4
3
|
from importlib.metadata import version
|
|
@@ -14,9 +13,6 @@ from .netcdf_to_multiband_geotiff import netcdf_to_multiband_geotiff
|
|
|
14
13
|
from .make_vertical_strips import make_vertical_strips
|
|
15
14
|
from .cloud_mask import cloud_mask
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
16
|
def run(file_L1C, folder_out, file_L2R = None, to_log=True):
|
|
21
17
|
|
|
22
18
|
### Check the two
|
|
@@ -32,7 +28,11 @@ def run(file_L1C, folder_out, file_L2R = None, to_log=True):
|
|
|
32
28
|
# Start logging in txt file
|
|
33
29
|
orig_stdout = sys.stdout
|
|
34
30
|
|
|
35
|
-
|
|
31
|
+
if file_L2R is None:
|
|
32
|
+
log_base = os.path.basename(file_L1C).replace('.safe','.txt').replace('.SAFE','.txt')
|
|
33
|
+
else:
|
|
34
|
+
log_base = os.path.basename(file_L2R).replace('.nc','.txt')
|
|
35
|
+
|
|
36
36
|
log_base = 'OSD_log_'+ log_base
|
|
37
37
|
log_file = os.path.join(folder_out,log_base)
|
|
38
38
|
|
{opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2/opticallyshallowdeep.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: opticallyshallowdeep
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.2
|
|
4
4
|
Summary: Identify optically shallow and deep waters in satellite imagery
|
|
5
5
|
Author: Yulun Wu
|
|
6
6
|
Author-email: yulunwu8@gmail.com
|
|
@@ -10,7 +10,7 @@ Description-Content-Type: text/markdown
|
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
Requires-Dist: geopandas
|
|
12
12
|
Requires-Dist: rasterio
|
|
13
|
-
Requires-Dist: tifffile
|
|
13
|
+
Requires-Dist: tifffile==2023.8.12
|
|
14
14
|
Requires-Dist: netCDF4
|
|
15
15
|
Requires-Dist: pyproj
|
|
16
16
|
Requires-Dist: joblib
|
|
@@ -23,12 +23,13 @@ Requires-Dist: tensorflow
|
|
|
23
23
|
|
|
24
24
|
This python tool delineates optically shallow and deep waters in Sentinel-2 imagery. The tool uses a deep neural network (DNN) that was trained on a diverse set of global images.
|
|
25
25
|
|
|
26
|
-
Supported input includes L1C SAFE files and ACOLITE-processed L2R netCDF files. The output geotiff contains probabilities of water pixels being optically shallow and deep.
|
|
26
|
+
Supported input includes Level-1C (L1C) SAFE files and ACOLITE-processed L2R netCDF files. The output geotiff contains probabilities of water pixels being optically shallow and deep.
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
**Home page:** <a href="https://github.com/yulunwu8/Optically-Shallow-Deep" target="_blank">https://github.com/yulunwu8/Optically-Shallow-Deep</a>
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
**Publication:** Richardson, G., Foreman, N., Knudby, A., Wu, Y., & Lin, Y. (2024). Global deep learning model for delineation of optically shallow and optically deep water in Sentinel-2 imagery. *Remote Sensing of Environment*, 311, 114302. <a href="https://doi.org/10.1016/j.rse.2024.114302" target="_blank">https://doi.org/10.1016/j.rse.2024.114302</a>
|
|
31
31
|
|
|
32
|
+
Originally coded by by Galen Richardson and Anders Knudby, modified and packaged by Yulun Wu
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
## Installation
|
|
@@ -47,26 +48,17 @@ For mac OS:
|
|
|
47
48
|
```bash
|
|
48
49
|
conda install -c apple tensorflow-deps
|
|
49
50
|
python -m pip install tensorflow-macos
|
|
50
|
-
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
|
|
54
|
-
For
|
|
54
|
+
For Windows and Linux:
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
57
|
pip3 install tensorflow==2.13.0
|
|
58
|
-
|
|
59
58
|
```
|
|
60
59
|
|
|
61
|
-
In case of compatibility issues, please try the newest version of tensorflow:
|
|
62
60
|
|
|
63
|
-
|
|
64
|
-
pip3 install --upgrade --force-reinstall tensorflow
|
|
65
|
-
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
For Linux and more on installing tensorflow: [https://www.tensorflow.org/install](https://www.tensorflow.org/install)
|
|
61
|
+
More on installing tensorflow: [https://www.tensorflow.org/install](https://www.tensorflow.org/install)
|
|
70
62
|
|
|
71
63
|
|
|
72
64
|
**3 - Install opticallyshallowdeep:**
|
|
@@ -106,16 +98,23 @@ file_L2R = 'test_folder_in/L2R.nc'
|
|
|
106
98
|
folder_out = 'folder/test_folder_out'
|
|
107
99
|
|
|
108
100
|
# Run the OSW/ODW classifier
|
|
109
|
-
osd.run(
|
|
101
|
+
osd.run(file_L1C, folder_out, file_L2R=file_L2R)
|
|
110
102
|
```
|
|
111
103
|
|
|
112
|
-
The L1C file is always required as it contains a cloud mask. Pixels within 8 pixels of the cloud mask are masked to reduce the impact of clouds.
|
|
104
|
+
The L1C file is always required as it contains a built-in cloud mask. Pixels within 8 pixels of the cloud mask are masked to reduce the impact of clouds.
|
|
113
105
|
|
|
114
106
|
|
|
115
|
-
Output is a 1-band geotiff, with values of prediction probability of OSW
|
|
107
|
+
Output is a 1-band geotiff, with values of prediction probability of optically shallow water (OSW): 100 means most likely OSW, 0 means most likely optically deep water (ODW). Non-water pixels are masked. It is recommended to treat pixels between 0 and 40 as ODW, and pixels between 60 and 100 as OSW (Richardson et al., 2024).
|
|
116
108
|
|
|
117
109
|
A log file, an intermediate multi-band geotiff, and a preview PNG are also generated in the output folder. They can be deleted after the processing.
|
|
118
110
|
|
|
111
|
+
|
|
112
|
+
**Sample Sentinel-2 scene and output:**
|
|
113
|
+
|
|
114
|
+
<img src="images/TOA.jpeg" height="500">
|
|
115
|
+
|
|
116
|
+
<img src="images/OSW.jpeg" height="500">
|
|
117
|
+
|
|
119
118
|
## Training, test, and validation data
|
|
120
119
|
|
|
121
120
|
All annotated shapefiles used in training, testing, and validating the DNN model are in the annotated_shapefiles folder, grouped by Sentinel-2 Scene ID.
|
|
@@ -5,7 +5,7 @@ with open("readme.md", "r") as fh:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name='opticallyshallowdeep',
|
|
8
|
-
version='1.2.
|
|
8
|
+
version='1.2.2',
|
|
9
9
|
author='Yulun Wu',
|
|
10
10
|
author_email='yulunwu8@gmail.com',
|
|
11
11
|
description='Identify optically shallow and deep waters in satellite imagery',
|
|
@@ -18,7 +18,7 @@ setup(
|
|
|
18
18
|
'Programming Language :: Python :: 3'
|
|
19
19
|
],
|
|
20
20
|
python_requires='>=3.8',
|
|
21
|
-
install_requires=['geopandas','rasterio','tifffile','netCDF4','pyproj',
|
|
21
|
+
install_requires=['geopandas','rasterio','tifffile==2023.8.12','netCDF4','pyproj',
|
|
22
22
|
'joblib','scipy','matplotlib','imagecodecs','tensorflow']
|
|
23
23
|
)
|
|
24
24
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/models/TOA.h5
RENAMED
|
File without changes
|
{opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|