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.
Files changed (25) hide show
  1. {opticallyshallowdeep-1.2.0/opticallyshallowdeep.egg-info → opticallyshallowdeep-1.2.2}/PKG-INFO +18 -19
  2. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/README.md +16 -17
  3. opticallyshallowdeep-1.2.2/opticallyshallowdeep/__init__.py +1 -0
  4. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/check_transpose.py +1 -4
  5. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/cloud_mask.py +1 -6
  6. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/find_epsg.py +0 -19
  7. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/make_multiband_image.py +0 -2
  8. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/make_vertical_strips.py +1 -6
  9. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/netcdf_to_multiband_geotiff.py +1 -5
  10. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/parse_string.py +1 -3
  11. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/process_as_strips.py +5 -22
  12. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/run.py +5 -5
  13. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/write_georef_image.py +1 -3
  14. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2/opticallyshallowdeep.egg-info}/PKG-INFO +18 -19
  15. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep.egg-info/requires.txt +1 -1
  16. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/setup.py +2 -2
  17. opticallyshallowdeep-1.2.0/opticallyshallowdeep/__init__.py +0 -2
  18. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/LICENSE +0 -0
  19. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/MANIFEST.in +0 -0
  20. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/models/SR.h5 +0 -0
  21. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep/models/TOA.h5 +0 -0
  22. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep.egg-info/SOURCES.txt +0 -0
  23. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep.egg-info/dependency_links.txt +0 -0
  24. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/opticallyshallowdeep.egg-info/top_level.txt +0 -0
  25. {opticallyshallowdeep-1.2.0 → opticallyshallowdeep-1.2.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: opticallyshallowdeep
3
- Version: 1.2.0
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
- Originally coded by by Galen Richardson and Anders Knudby, modified and packaged by Yulun Wu
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
- Home page: <a href="https://github.com/yulunwu8/Optically-Shallow-Deep" target="_blank">https://github.com/yulunwu8/Optically-Shallow-Deep</a>
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 windows:
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
- ```bash
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(file_in, folder_out, file_L2R=file_L2R)
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 (100 means most likely OSW, 0 means most likely ODW). Non-water pixels are masked. It is recommended to use pixels between 0 and 40 as ODW, and pixels between 60 and 100 as OSW (publication in review).
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
- Originally coded by by Galen Richardson and Anders Knudby, modified and packaged by Yulun Wu
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
- Home page: <a href="https://github.com/yulunwu8/Optically-Shallow-Deep" target="_blank">https://github.com/yulunwu8/Optically-Shallow-Deep</a>
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 windows:
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
- ```bash
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(file_in, folder_out, file_L2R=file_L2R)
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 (100 means most likely OSW, 0 means most likely ODW). Non-water pixels are masked. It is recommended to use pixels between 0 and 40 as ODW, and pixels between 60 and 100 as OSW (publication in review).
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 *
@@ -1,10 +1,7 @@
1
-
2
1
  # Always output row, column, band
3
-
4
2
  def check_transpose(img):
5
3
  #if the #of bands is greater than the number of x or y cords
6
4
  y,x,b=img.shape
7
5
  if b>y or b>x:
8
6
  img=img.transpose(1,2,0)
9
- return img
10
-
7
+ return img
@@ -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
-
@@ -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
@@ -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
@@ -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].astype(np.uint16)#this means it is a single pixel
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
- filtered_band = filtered_band.astype(np.uint16)
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
- log_base = os.path.basename(file_L1C).replace('.safe','.txt').replace('.SAFE','.txt')
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
 
@@ -1,4 +1,3 @@
1
-
2
1
  import rasterio, gc
3
2
  import numpy as np
4
3
 
@@ -23,5 +22,4 @@ def write_georef_image(image_path,RGB_img):
23
22
  dst.write(output_band, 1)
24
23
 
25
24
  del raster_with_ref
26
- gc.collect()
27
-
25
+ gc.collect()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: opticallyshallowdeep
3
- Version: 1.2.0
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
- Originally coded by by Galen Richardson and Anders Knudby, modified and packaged by Yulun Wu
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
- Home page: <a href="https://github.com/yulunwu8/Optically-Shallow-Deep" target="_blank">https://github.com/yulunwu8/Optically-Shallow-Deep</a>
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 windows:
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
- ```bash
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(file_in, folder_out, file_L2R=file_L2R)
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 (100 means most likely OSW, 0 means most likely ODW). Non-water pixels are masked. It is recommended to use pixels between 0 and 40 as ODW, and pixels between 60 and 100 as OSW (publication in review).
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.
@@ -1,6 +1,6 @@
1
1
  geopandas
2
2
  rasterio
3
- tifffile
3
+ tifffile==2023.8.12
4
4
  netCDF4
5
5
  pyproj
6
6
  joblib
@@ -5,7 +5,7 @@ with open("readme.md", "r") as fh:
5
5
 
6
6
  setup(
7
7
  name='opticallyshallowdeep',
8
- version='1.2.0',
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
 
@@ -1,2 +0,0 @@
1
- from .run import *
2
-