fieldsoftheworld/ftw-q
Updated • 31
Agricultural field boundary segmentation from one year of quarterly Sentinel-2 cloudless mosaics. A U-Net with an EfficientNet-B3 encoder, trained on FTW-Q.
| File | Description |
|---|---|
ftw-q-unet-efb3.pt |
PyTorch state dict |
ftw-q-unet-efb3.onnx |
ONNX (opset 18, fp32), dynamic batch |
(batch, 16, 512, 512) float32. Channels are [B04, B03, B02, B08] for each of
Q1, Q2, Q3, Q4, in that order (channel 4 * q + b), from the
Copernicus Sentinel-2 Global Mosaics
(int16, reflectance × 10000).logits, (batch, 3, 512, 512) at 2.5 m. Classes: 0 background, 1 field,
2 field boundary.import numpy as np
import onnxruntime as ort
import torch
import torch.nn.functional as F
x = torch.from_numpy(stack.astype(np.float32) / 3000)[None] # stack: (16, 128, 128) at 10 m
x = F.interpolate(x, scale_factor=4, mode="bilinear", align_corners=False)
sess = ort.InferenceSession("ftw-q-unet-efb3.onnx")
logits = sess.run(None, {"input": x.numpy()})[0]
PyTorch, with segmentation-models-pytorch 0.5.0:
import segmentation_models_pytorch as smp
import torch
model = smp.Unet(encoder_name="efficientnet-b3", encoder_weights=None, in_channels=16, classes=3)
model.load_state_dict(torch.load("ftw-q-unet-efb3.pt", map_location="cpu"))
model.eval()
a·x + b with a ~ U(0.9, 1.1), b ~ U(−0.1, 0.1) (p = 0.5); with p = 0.4, one quarter is
replaced by a copy of another.FTW-Q test split, 7,817 chips. Field polygons are extracted from the argmax field class, polygons under 1,000 m² are dropped, and each is matched to a label polygon at IoU > 0.5. Scores are averaged over countries, excluding Kenya and Portugal.
| Object F1 | Precision | Recall |
|---|---|---|
| 0.526 | 0.601 | 0.475 |
CC-BY-4.0.