opticallyshallowdeep 1.2.1__tar.gz → 1.2.3__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.1 → opticallyshallowdeep-1.2.3}/PKG-INFO +29 -9
- opticallyshallowdeep-1.2.1/opticallyshallowdeep.egg-info/PKG-INFO → opticallyshallowdeep-1.2.3/README.md +16 -26
- opticallyshallowdeep-1.2.3/opticallyshallowdeep/__init__.py +1 -0
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep/check_transpose.py +1 -4
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep/cloud_mask.py +1 -6
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep/find_epsg.py +0 -19
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep/make_multiband_image.py +1 -3
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep/make_vertical_strips.py +1 -6
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep/netcdf_to_multiband_geotiff.py +1 -5
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep/parse_string.py +1 -3
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep/process_as_strips.py +1 -20
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep/run.py +2 -6
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep/write_georef_image.py +1 -3
- opticallyshallowdeep-1.2.1/README.md → opticallyshallowdeep-1.2.3/opticallyshallowdeep.egg-info/PKG-INFO +46 -5
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep.egg-info/requires.txt +2 -2
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/setup.py +2 -2
- opticallyshallowdeep-1.2.1/opticallyshallowdeep/__init__.py +0 -2
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/LICENSE +0 -0
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/MANIFEST.in +0 -0
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep/models/SR.h5 +0 -0
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep/models/TOA.h5 +0 -0
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep.egg-info/SOURCES.txt +0 -0
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep.egg-info/dependency_links.txt +0 -0
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep.egg-info/top_level.txt +0 -0
- {opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: opticallyshallowdeep
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.3
|
|
4
4
|
Summary: Identify optically shallow and deep waters in satellite imagery
|
|
5
5
|
Author: Yulun Wu
|
|
6
6
|
Author-email: yulunwu8@gmail.com
|
|
@@ -9,8 +9,8 @@ Requires-Python: >=3.8
|
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
Requires-Dist: geopandas
|
|
12
|
-
Requires-Dist: rasterio
|
|
13
|
-
Requires-Dist: tifffile
|
|
12
|
+
Requires-Dist: rasterio==1.3.9
|
|
13
|
+
Requires-Dist: tifffile==2023.8.12
|
|
14
14
|
Requires-Dist: netCDF4
|
|
15
15
|
Requires-Dist: pyproj
|
|
16
16
|
Requires-Dist: joblib
|
|
@@ -18,6 +18,15 @@ Requires-Dist: scipy
|
|
|
18
18
|
Requires-Dist: matplotlib
|
|
19
19
|
Requires-Dist: imagecodecs
|
|
20
20
|
Requires-Dist: tensorflow
|
|
21
|
+
Dynamic: author
|
|
22
|
+
Dynamic: author-email
|
|
23
|
+
Dynamic: classifier
|
|
24
|
+
Dynamic: description
|
|
25
|
+
Dynamic: description-content-type
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
Dynamic: requires-dist
|
|
28
|
+
Dynamic: requires-python
|
|
29
|
+
Dynamic: summary
|
|
21
30
|
|
|
22
31
|
# Optically-Shallow-Deep
|
|
23
32
|
|
|
@@ -25,10 +34,13 @@ This python tool delineates optically shallow and deep waters in Sentinel-2 imag
|
|
|
25
34
|
|
|
26
35
|
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
36
|
|
|
28
|
-
|
|
37
|
+
**Home page:** <a href="https://github.com/yulunwu8/Optically-Shallow-Deep" target="_blank">https://github.com/yulunwu8/Optically-Shallow-Deep</a>
|
|
29
38
|
|
|
30
|
-
|
|
39
|
+
**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
40
|
|
|
41
|
+
Originally coded by G. Richardson and A. Knudby, modified and packaged by Y. Wu
|
|
42
|
+
|
|
43
|
+
Models trained by G. Richardson and N. Foreman
|
|
32
44
|
|
|
33
45
|
|
|
34
46
|
## Installation
|
|
@@ -50,14 +62,14 @@ python -m pip install tensorflow-macos
|
|
|
50
62
|
```
|
|
51
63
|
|
|
52
64
|
|
|
53
|
-
For
|
|
65
|
+
For Windows and Linux:
|
|
54
66
|
|
|
55
67
|
```bash
|
|
56
68
|
pip3 install tensorflow==2.13.0
|
|
57
69
|
```
|
|
58
70
|
|
|
59
71
|
|
|
60
|
-
|
|
72
|
+
More on installing tensorflow: [https://www.tensorflow.org/install](https://www.tensorflow.org/install)
|
|
61
73
|
|
|
62
74
|
|
|
63
75
|
**3 - Install opticallyshallowdeep:**
|
|
@@ -103,7 +115,7 @@ osd.run(file_L1C, folder_out, file_L2R=file_L2R)
|
|
|
103
115
|
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.
|
|
104
116
|
|
|
105
117
|
|
|
106
|
-
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.
|
|
118
|
+
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.
|
|
107
119
|
|
|
108
120
|
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.
|
|
109
121
|
|
|
@@ -114,6 +126,14 @@ A log file, an intermediate multi-band geotiff, and a preview PNG are also gener
|
|
|
114
126
|
|
|
115
127
|
<img src="images/OSW.jpeg" height="500">
|
|
116
128
|
|
|
129
|
+
|
|
130
|
+
## Tips
|
|
131
|
+
|
|
132
|
+
It is recommended to treat pixels with values between 0 and 40 as ODW, and those between 60 and 100 as OSW (Richardson et al., 2024).
|
|
133
|
+
|
|
134
|
+
Users have reported that averaging results from multiple images acquired on different days can help reduce noise and improve the overall accuracy of classification results.
|
|
135
|
+
|
|
136
|
+
|
|
117
137
|
## Training, test, and validation data
|
|
118
138
|
|
|
119
139
|
All annotated shapefiles used in training, testing, and validating the DNN model are in the annotated_shapefiles folder, grouped by Sentinel-2 Scene ID.
|
|
@@ -1,34 +1,16 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: opticallyshallowdeep
|
|
3
|
-
Version: 1.2.1
|
|
4
|
-
Summary: Identify optically shallow and deep waters in satellite imagery
|
|
5
|
-
Author: Yulun Wu
|
|
6
|
-
Author-email: yulunwu8@gmail.com
|
|
7
|
-
Classifier: Programming Language :: Python :: 3
|
|
8
|
-
Requires-Python: >=3.8
|
|
9
|
-
Description-Content-Type: text/markdown
|
|
10
|
-
License-File: LICENSE
|
|
11
|
-
Requires-Dist: geopandas
|
|
12
|
-
Requires-Dist: rasterio
|
|
13
|
-
Requires-Dist: tifffile
|
|
14
|
-
Requires-Dist: netCDF4
|
|
15
|
-
Requires-Dist: pyproj
|
|
16
|
-
Requires-Dist: joblib
|
|
17
|
-
Requires-Dist: scipy
|
|
18
|
-
Requires-Dist: matplotlib
|
|
19
|
-
Requires-Dist: imagecodecs
|
|
20
|
-
Requires-Dist: tensorflow
|
|
21
|
-
|
|
22
1
|
# Optically-Shallow-Deep
|
|
23
2
|
|
|
24
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.
|
|
25
4
|
|
|
26
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.
|
|
27
6
|
|
|
28
|
-
|
|
7
|
+
**Home page:** <a href="https://github.com/yulunwu8/Optically-Shallow-Deep" target="_blank">https://github.com/yulunwu8/Optically-Shallow-Deep</a>
|
|
8
|
+
|
|
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>
|
|
29
10
|
|
|
30
|
-
|
|
11
|
+
Originally coded by G. Richardson and A. Knudby, modified and packaged by Y. Wu
|
|
31
12
|
|
|
13
|
+
Models trained by G. Richardson and N. Foreman
|
|
32
14
|
|
|
33
15
|
|
|
34
16
|
## Installation
|
|
@@ -50,14 +32,14 @@ python -m pip install tensorflow-macos
|
|
|
50
32
|
```
|
|
51
33
|
|
|
52
34
|
|
|
53
|
-
For
|
|
35
|
+
For Windows and Linux:
|
|
54
36
|
|
|
55
37
|
```bash
|
|
56
38
|
pip3 install tensorflow==2.13.0
|
|
57
39
|
```
|
|
58
40
|
|
|
59
41
|
|
|
60
|
-
|
|
42
|
+
More on installing tensorflow: [https://www.tensorflow.org/install](https://www.tensorflow.org/install)
|
|
61
43
|
|
|
62
44
|
|
|
63
45
|
**3 - Install opticallyshallowdeep:**
|
|
@@ -103,7 +85,7 @@ osd.run(file_L1C, folder_out, file_L2R=file_L2R)
|
|
|
103
85
|
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.
|
|
104
86
|
|
|
105
87
|
|
|
106
|
-
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.
|
|
88
|
+
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.
|
|
107
89
|
|
|
108
90
|
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.
|
|
109
91
|
|
|
@@ -114,6 +96,14 @@ A log file, an intermediate multi-band geotiff, and a preview PNG are also gener
|
|
|
114
96
|
|
|
115
97
|
<img src="images/OSW.jpeg" height="500">
|
|
116
98
|
|
|
99
|
+
|
|
100
|
+
## Tips
|
|
101
|
+
|
|
102
|
+
It is recommended to treat pixels with values between 0 and 40 as ODW, and those between 60 and 100 as OSW (Richardson et al., 2024).
|
|
103
|
+
|
|
104
|
+
Users have reported that averaging results from multiple images acquired on different days can help reduce noise and improve the overall accuracy of classification results.
|
|
105
|
+
|
|
106
|
+
|
|
117
107
|
## Training, test, and validation data
|
|
118
108
|
|
|
119
109
|
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.1 → opticallyshallowdeep-1.2.3}/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
|
-
|
|
@@ -10,7 +10,7 @@ def make_multiband_image(file_in,folder_out):
|
|
|
10
10
|
basename = os.path.basename(file_in).rstrip(".SAFE")
|
|
11
11
|
|
|
12
12
|
# output path
|
|
13
|
-
imageFile = os.path.join(folder_out,basename
|
|
13
|
+
imageFile = os.path.join(folder_out, f"{basename}.tif")
|
|
14
14
|
|
|
15
15
|
if os.path.exists(imageFile):
|
|
16
16
|
print('Multi-band geotiff exists: ' + str(imageFile))
|
|
@@ -54,5 +54,3 @@ def make_multiband_image(file_in,folder_out):
|
|
|
54
54
|
print('Done')
|
|
55
55
|
|
|
56
56
|
return imageFile
|
|
57
|
-
|
|
58
|
-
|
|
@@ -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.1 → opticallyshallowdeep-1.2.3}/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.1 → opticallyshallowdeep-1.2.3}/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"]]]
|
|
@@ -353,7 +347,6 @@ def load_model_and_predict_pixels(value_list, model_path, cord_list, if_SR):
|
|
|
353
347
|
|
|
354
348
|
return cord_list.tolist(), pred_results.tolist(), con_1.tolist()
|
|
355
349
|
|
|
356
|
-
|
|
357
350
|
def load_tf_model(model_path, if_SR):
|
|
358
351
|
if if_SR == False:
|
|
359
352
|
model=d6_model(32,0.01)
|
|
@@ -422,16 +415,4 @@ def plot_RGB_img(RGB_img, image_path):
|
|
|
422
415
|
# plt.show()
|
|
423
416
|
|
|
424
417
|
out_path = image_path.replace('.tif','.png')
|
|
425
|
-
plt.savefig(out_path)
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
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
|
|
@@ -74,7 +70,7 @@ def run(file_L1C, folder_out, file_L2R = None, to_log=True):
|
|
|
74
70
|
if file_L2R is None:
|
|
75
71
|
|
|
76
72
|
if_SR = False
|
|
77
|
-
model = 'models
|
|
73
|
+
model = os.path.join('models', 'TOA.h5')
|
|
78
74
|
model_columns = GTOA_model_columns
|
|
79
75
|
file_in = file_L1C
|
|
80
76
|
|
|
@@ -88,7 +84,7 @@ def run(file_L1C, folder_out, file_L2R = None, to_log=True):
|
|
|
88
84
|
sys.exit('file_L2R does not exist: ' + str(file_L2R))
|
|
89
85
|
|
|
90
86
|
if_SR = True
|
|
91
|
-
model = 'models
|
|
87
|
+
model = os.path.join('models', 'SR.h5')
|
|
92
88
|
model_columns = GACOLITE_model_columns
|
|
93
89
|
file_in = file_L2R
|
|
94
90
|
|
|
@@ -1,13 +1,46 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: opticallyshallowdeep
|
|
3
|
+
Version: 1.2.3
|
|
4
|
+
Summary: Identify optically shallow and deep waters in satellite imagery
|
|
5
|
+
Author: Yulun Wu
|
|
6
|
+
Author-email: yulunwu8@gmail.com
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Requires-Python: >=3.8
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Dist: geopandas
|
|
12
|
+
Requires-Dist: rasterio==1.3.9
|
|
13
|
+
Requires-Dist: tifffile==2023.8.12
|
|
14
|
+
Requires-Dist: netCDF4
|
|
15
|
+
Requires-Dist: pyproj
|
|
16
|
+
Requires-Dist: joblib
|
|
17
|
+
Requires-Dist: scipy
|
|
18
|
+
Requires-Dist: matplotlib
|
|
19
|
+
Requires-Dist: imagecodecs
|
|
20
|
+
Requires-Dist: tensorflow
|
|
21
|
+
Dynamic: author
|
|
22
|
+
Dynamic: author-email
|
|
23
|
+
Dynamic: classifier
|
|
24
|
+
Dynamic: description
|
|
25
|
+
Dynamic: description-content-type
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
Dynamic: requires-dist
|
|
28
|
+
Dynamic: requires-python
|
|
29
|
+
Dynamic: summary
|
|
30
|
+
|
|
1
31
|
# Optically-Shallow-Deep
|
|
2
32
|
|
|
3
33
|
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
34
|
|
|
5
35
|
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
36
|
|
|
7
|
-
|
|
37
|
+
**Home page:** <a href="https://github.com/yulunwu8/Optically-Shallow-Deep" target="_blank">https://github.com/yulunwu8/Optically-Shallow-Deep</a>
|
|
38
|
+
|
|
39
|
+
**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>
|
|
8
40
|
|
|
9
|
-
|
|
41
|
+
Originally coded by G. Richardson and A. Knudby, modified and packaged by Y. Wu
|
|
10
42
|
|
|
43
|
+
Models trained by G. Richardson and N. Foreman
|
|
11
44
|
|
|
12
45
|
|
|
13
46
|
## Installation
|
|
@@ -29,14 +62,14 @@ python -m pip install tensorflow-macos
|
|
|
29
62
|
```
|
|
30
63
|
|
|
31
64
|
|
|
32
|
-
For
|
|
65
|
+
For Windows and Linux:
|
|
33
66
|
|
|
34
67
|
```bash
|
|
35
68
|
pip3 install tensorflow==2.13.0
|
|
36
69
|
```
|
|
37
70
|
|
|
38
71
|
|
|
39
|
-
|
|
72
|
+
More on installing tensorflow: [https://www.tensorflow.org/install](https://www.tensorflow.org/install)
|
|
40
73
|
|
|
41
74
|
|
|
42
75
|
**3 - Install opticallyshallowdeep:**
|
|
@@ -82,7 +115,7 @@ osd.run(file_L1C, folder_out, file_L2R=file_L2R)
|
|
|
82
115
|
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.
|
|
83
116
|
|
|
84
117
|
|
|
85
|
-
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.
|
|
118
|
+
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.
|
|
86
119
|
|
|
87
120
|
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.
|
|
88
121
|
|
|
@@ -93,6 +126,14 @@ A log file, an intermediate multi-band geotiff, and a preview PNG are also gener
|
|
|
93
126
|
|
|
94
127
|
<img src="images/OSW.jpeg" height="500">
|
|
95
128
|
|
|
129
|
+
|
|
130
|
+
## Tips
|
|
131
|
+
|
|
132
|
+
It is recommended to treat pixels with values between 0 and 40 as ODW, and those between 60 and 100 as OSW (Richardson et al., 2024).
|
|
133
|
+
|
|
134
|
+
Users have reported that averaging results from multiple images acquired on different days can help reduce noise and improve the overall accuracy of classification results.
|
|
135
|
+
|
|
136
|
+
|
|
96
137
|
## Training, test, and validation data
|
|
97
138
|
|
|
98
139
|
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.3',
|
|
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==1.3.9','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.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep/models/TOA.h5
RENAMED
|
File without changes
|
{opticallyshallowdeep-1.2.1 → opticallyshallowdeep-1.2.3}/opticallyshallowdeep.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|