--- license: cc0-1.0 tags: - remote-sensing - sentinel-1 - sar - semantic-segmentation - water-segmentation - shoreline - onnx - torchgeo library_name: onnx --- # SAR_3_band_model Binary **land/water semantic segmentation** for Sentinel-1 SAR imagery. A U-Net with a ResNet-50 encoder, fine-tuned from the SSL4EO-S12 Sentinel-1 MOCO weights (`ResNet50_Weights.SENTINEL1_GRD_MOCO`) on a 3-band composite: **VV, VH, VV−VH (dB)**. Built for shoreline delineation: the water mask is vectorized and intersected with shore-normal transects to give a shoreline position per Sentinel-1 acquisition. ## Model details | | | |---|---| | Architecture | U-Net decoder + ResNet-50 encoder (TorchGeo `SemanticSegmentationTask`) | | Encoder init | `ResNet50_Weights.SENTINEL1_GRD_MOCO` (SSL4EO-S12, self-supervised) | | Input | 3 channels: VV, VH, VV−VH (**dB scale**, normalized) | | Classes | `0 = land`, `1 = water` (`255 = ignore/nodata`) | | Training | 50 epochs, cross-entropy, AdamW (lr 1e-3), batch 8, 512×512 chips, 16-mixed precision | | Checkpoint | `epoch=46-val_loss=0.0719` | | Format | ONNX, dynamic batch/height/width (~130 MB) | ## Performance Held-out validation split (113 scenes, site-disjoint from training): | Overall acc. | Overall IoU | Water IoU | Land IoU | |---|---|---|---| | 0.9724 | 0.9462 | 0.9571 | 0.9280 | End-to-end shoreline accuracy against an independent optical shoreline dataset (16 US coastal sites, ~97,500 transect observations): **RMSE 60.1 m, MAE 25.2 m, bias +9.8 m**. Excluding two sites with known reference-data problems: RMSE 37.0 m, MAE 21.3 m. This 3-band, no-speckle-filter configuration was the best of four variants tested (2-band vs 3-band × with/without a Refined Lee filter), winning 12 of 16 sites. Applying a speckle filter before the network consistently hurt accuracy. ## Inputs and outputs ``` input image float32 [batch, 3, H, W] (normalized) output logits float32 [batch, 2, H, W] water_prob float32 [batch, 1, H, W] softmax(logits)[:, 1] = P(water) ``` `H` and `W` must be **multiples of 32** (encoder stride). Pad bottom/right with 0.0 and crop the output back. ## Classes The model predicts two classes per pixel. The `logits` channel axis is in this order: | Index | Class | Meaning | |---|---|---| | 0 | `land` | Anything that is not open water: beach, dune, vegetation, buildings, bare soil, and exposed intertidal flats. Generally high or variable SAR backscatter. | | 1 | `water` | Open water: ocean, bay, estuary, river, lake, and standing floodwater. Generally low SAR backscatter, because a smooth water surface reflects the radar pulse away from the sensor. | Take `argmax(logits, axis=1)` for a hard class map, or threshold `water_prob` (which is P(class 1)) at 0.5 for the same result with control over the operating point. Raise the threshold for a more conservative water mask, lower it to catch more wind-roughened water. Because the classes are defined by backscatter, the land/water boundary this model finds is the **instantaneous waterline at the time of acquisition**, not a tidal datum. Correct for tide separately if you need a datum-based shoreline. A third value, **255 = nodata/ignore**, appears in the training labels and in the prediction rasters this project writes, but **the model never outputs it**. It marks pixels with no valid input: outside the scene footprint, or nodata/NaN in VV or VH. Carry your input validity mask through inference and stamp 255 into those pixels yourself after `argmax`. ## ⚠️ Preprocessing is NOT in the graph The graph starts at the normalized tensor. Do this yourself, in order: 1. Read VV and VH in **dB**, tracking invalid pixels (nodata / NaN / ±Inf). 2. Derive `VV−VH` (dB difference) and stack as `[VV, VH, VV−VH]`. 3. Fill invalid pixels with that channel's mean. 4. Normalize `(x - mean) / std`: | Channel | mean | std | |---|---|---| | VV | −12.59 | 5.26 | | VH | −20.26 | 5.91 | | VV−VH | 10.5465 | 7.6855 | 5. Pad `H`/`W` up to a multiple of 32. **No speckle filter.** This model was trained on raw dB, so do not apply Lee/Refined Lee before inference. Preprocessing facts are also embedded in the ONNX `metadata_props`: ## Training data 792 Sentinel-1 IW GRD scenes (10 m, VV+VH, dB) over US coastal sites: 679 train and 113 validation, split by site so no site appears in both. Labels are a random-forest water/land classification of Lee-ENL-filtered composites, manually reviewed and re-labelled for problematic sites. Augmentation: random horizontal/vertical flips (p=0.5), random 90° rotations, Gaussian noise (σ=0.1). Scenes are randomly cropped/padded to 512×512 and never globally resized, which would smear SAR edges and corrupt categorical labels. ## Limitations - **Sentinel-1 IW GRD in dB only.** Linear amplitude/power, other sensors, or a different speckle-filter state will degrade results. - Trained on US coastal sites; performance elsewhere (ice, very sheltered/vegetated water, extreme incidence angles) is untested. - Wind-roughened water and radar shadow on steep terrain are the common failure modes for SAR water segmentation generally. - Slight landward shoreline bias (~+10 m) relative to optical references.