Seagrass Mapping in the Florida Keys

Author

Tylar

Published

March 9, 2026

An attempt was made to map seagrasses in the Florida Keys region.

Background

Existing Maps

Florida’s Unified Reef Map

https://experience.arcgis.com/experience/a7ef122627414ee1a72c0a6a7527edff

Methods

Ground Truth Data

Lizcano 2019 and 2021

Ground truth data was ingested from the works of Luis Lizcano [^1].

groundTruth Ground truth data used for the Florida Keys region. Two data collections are displayed; one from 2019 and the other from 2021.The 2019 data is shown in lighter colors than the darker 2021 data. Classes are displayed are: seagrass in green, softbottom in red, and hardbottom (corals) in orange. Source code here.

FK2025-Visual Ground Truth

V1

Additional ground truth data was created using visual interpretation of S2 imagery from 2025 and the 2026 google maps satellite view. This visual interpretation was guided by the ground truth data of Lizcano to create a ground truth dataset with an increased diversity of classes. This dataset separates “dense” submerged aquatic vegetation from “sparse” submerged aquatic vegetation. The visual differences between dense and sparse seagrass are significant, and initial tests suggested that segmentation into these subclasses would improve classification accuracy.

V2

A further expanded version of seagrass ground truth data was created which add seagrass points to the northwest of the FKNMS. Although the statewide seagrass map from the SIMM program does not show seagrass in this region, satellite imagery appears to show seagrass in the region. It is possible this region is not assessed because it is outside of the FKNMS. A sampling effort of the area from the late 1990s shows seagrass in the area. Based on this seagrass points were added for this region. The water in this area is shallow and often very turbid. The turbidity may cause issues for the classifier.

S2 Multispectral Images

Images from the landsat-harmonized sentinel 2 collection on GEE were used.

S2 Image Pre-processing

Clouds were filtered from the images using the CloudScore+ product published on GEE. The band values are scaled using the sat_fns:s2_fns.scaleBands method, which implements:

  var scaledImg = img.select(exports.rrs_bands)
    .divide(10000).divide(3.1415926)
  ;

Land masking was applied using an NDWI calculation.

A depth-invariant index was applied using statistics calculated from sand polygons across multiple depths.

Bathymetry Layer

NOAA’s BlueTopo layer was extracted and uploaded into GEE.

A geojson for the FL Keys was created:

(base) tylar@tylar-laptop:~/Documents$ cat fk.geojson 
{
  "type": "FeatureCollection",
  "features": [{
    "type": "Feature",
    "geometry": {
      "type": "Polygon",
      "coordinates": [[[-82.5, 24.0], [-80.0, 24.0], [-80.0, 25.5], [-82.5, 25.5], [-82.5, 24.0]]]
    },
    "properties": {}
  }]
}

Conda and mamba were installed. A conda environment was specified with an environment.yml file:

name: habitat-mapping                                                                                               
channels:                                                                                                           
  - conda-forge                                                                                                     
dependencies:                                                                                                       
  - python=3.12                                                                                                     
  - gdal=3.12                                                                                                       

The environment was installed:

mamba env create -f environment.yml

The environment wass activated and dependencies installed:

conda activate habitat-mapping
pip install bluetopo

The bluetopo tool was used to fetch tiles and buld a virtual raster (.vrt) file.

(habitat-mapping) tylar@tylar-laptop:~/Documents/bluetopo$ fetch_tiles -d /home/tylar/Documents/bluetopo/fl_keys_bluetopo_tiles -g /home/tylar/Documents/bluetopo/fk.geojson

(habitat-mapping) tylar@tylar-laptop:~/Documents/bluetopo$ build_vrt -d /home/tylar/Documents/bluetopo/fl_keys_bluetopo_tiles

The .vrt was converted to WGS84 and built into a single .tif file using gdal. NOTE: This would be a good stage to drop bands 2 and 3, keeping only the b1 (elevation) band to reduce file size; this was not done here.

(habitat-mapping) tylar@tylar-laptop:~/Documents/bluetopo$ gdalwarp -t_srs EPSG:4326 -s_srs "EPSG:26917+5703" -r bilinear -overwrite -co COMPRESS=DEFLATE -co TILED=YES -co BIGTIFF=IF_SAFER fl_keys_bluetopo_tiles/BlueTopo_VRT/BlueTopo_Fetched_UTM17.vrt fl_keys_bluetopo_wgs84.tif


gdal_translate -of COG -co COMPRESS=DEFLATE -co BIGTIFF=YES fl_keys_bluetopo_wgs84.tif fl_keys_bluetopo_cog.tif

The .tif was uploading into google earth engine’s assets using the assets web interface at code.earthengine.google.com.

Results

S2 Lizcano-trained products

The first attempt at classification used minimal pre-processing (only cloud filter and scaling) and the Lizcano ground truth data. Bands ‘B1’,‘B2’,‘B3’,‘B4’,‘B2B3’ were used. This classification resulted in an image with no seagrass.

For the second result, the same experiment was run with extraneous S2 bands in the dataset removed; only the spectral bands were kept. The result was much better, indicating that inclusion of the extra bands were confusing the classifier.

results

S2 FK2025-Visual-trained Without Bathymetry

Bands ‘B1’,‘B2’,‘B3’,‘B4’,‘B2B3’ were used.

groundTruthAndResults2.png Classification and ground truth data for training on the FK2025-Visual data.

A clear issue with this product can be seen in the top-left of the view, where much of the area appears to be classified as coral. A closer view of this area reveals additional characteristics of this issue.

results2ConfusionRegionTopLeft Zoomed in view of top-left region with classification inaccuracies. Classification results (left) are very speckled and show features characteristic of image artifacts. S2 mean for the time range shows artifacts from mosaicing and cloud masking.

One potential cause could be poor image coverage of this area, resulting in a poor quality mean image. This could be explored further by mapping the image count per pixel.

Another explaination that accounts for the speckled texture is that this area is highly impacted by sunglint. Sunglint removal processing could reduce this misclassification.

Additional ground truth points could be used in this area, but I am uncertain what the true class of this region should be. The spectral signature appears different from the deep-water areas past the reef tract. I do not know what the depth in this region is.

S2 FK2025-Visual-trained With Bathymetry

Using only bands ‘B1’,‘B2’,‘B3’,‘B4’,‘B2B3’. With the addition of the bathymetry:

results-w-bathy
  • The hard-cover/coral class is showing up where it should not.
  • The deep water class is showing up in very shallow, sandy areas
  • Interesting features in the west which are not visible in the RGB.

S2 FK2025-Visual-v2-trained With Bathymetry

With seagrass allowed in the northwest region and the hardcover class being excluded, the results are looking quite good.

results-w-bathy-v2

Some features in the northwest from the bathymetry layer seem over-pronounced. Further refinement of the ground truth data from regional experts is needed.

Next Steps

Next steps might include:

  1. sunglint correction
  2. addition of texture ‘bands’
  3. implement bandSum-normalization

References

[^1] Seagrass Extent Expansion in the Gulf of Mexico and Northwestern Caribbean (1987–2021) Luis Lizcano-Sandoval, Susan Bell, Sergio Cerdeira-Estrada, Beatriz Martinez-Daranas, Enrique Montes, Brigitta van Tussenbroek, Frank Muller-Karger bioRxiv 2025.11.10.687714; doi: https://doi.org/10.1101/2025.11.10.687714