Downloads · 30 days
0
aiprojektgaia/gaia_buildings_50e
gaia_buildings_50e is a image segmentation model from aiprojektgaia. Use it for the image segmentation task on the model card, and read the license before you ship it in a product. It is set up for segmentation-models-pytorch. The card lists the license as apache-2.0.
Binary semantic segmentation model that extracts buildings from aerial imagery. Produces a per-pixel likelihood map, not a thresholded mask.
Downloads · 30 days
0
Access
Public
Updated Nov 3, 2026
Repo size
278 MB
Likes
0
Public
Click a slice to open those files.
.ckpt278 MB · 100%
From the Hugging Face model README
Binary semantic segmentation model that extracts buildings from aerial imagery. Produces a per-pixel likelihood map, not a thresholded mask.
Trained for GAIA, a self-hosted system that turns aerial imagery into vector map data for Swedish municipalities.
An FPN (Feature Pyramid Network) segmentation model with a ResNet34 encoder,
trained to score each RGB pixel by how likely it is to be building. Built with
segmentation_models_pytorch and trained via PyTorch Lightning.
smp.encoders.get_preprocessing_params("resnet34"),
which returns ImageNet values — consistent with an ImageNet-pretrained
encoder. Confirm against ckpt["hyper_parameters"].segmentation module of gaia-engine, via
ResUNetInferencerNaming note. GAIA registers this checkpoint under
"model type": "resunet"insegmentation/parameters.json. That string selects the loader, not the architecture — the loader passesarchstraight from the checkpoint hyperparameters intosmp.create_model(). The architecture is whatever the checkpoint declares (FPN), despite theresunetlabel.
Building extraction from nadir aerial RGB orthophotos.
The model is resolution-sensitive and expects imagery at approximately
0.05 m/pixel. The GAIA inference wrapper rescales input to that target
before inference (resizeImageToTargetResolution), and additionally crops
dimensions to a multiple of 32 pixels, as the FPN decoder requires.
In production GAIA requests tiles from a WMS at 0.08 m/pixel and the wrapper upsamples them to 0.05 m/pixel. This is handled explicitly rather than being a silent mismatch, but upsampling cannot recover detail that was never captured — imagery natively at or near 0.05 m/pixel should be expected to perform better.
Output is a single-channel uint8 raster, 0–255, where the value is the
sigmoid-scaled likelihood that the pixel is building. It is not a binary
mask.
Within GAIA the likelihood raster feeds a fixed pipeline:
growing_rectangles) so
outlines have straight walls and square corners instead of the ragged edges
generic tracing produces.Keeping the model's output continuous is deliberate: it lets a run be re-thresholded without re-running inference.
Plausible uses beyond GAIA include map updating, building inventory and change detection — none of which have been evaluated here.
It segments roofs, not footprints. Nadir imagery sees the roof. For tall buildings, or anywhere the orthorectification is imperfect, the visible roof is displaced from the true ground footprint and overhanging eaves extend beyond it. Output approximates a footprint and should not be treated as a survey-grade one.
Geographic and architectural bias. The model was trained for Swedish municipal use. Roof materials, colours, building density, forms and the sun angles typical of northern latitudes all vary by region; performance elsewhere is unknown and should not be assumed. Dense informal settlements and irregular non-rectangular structures are common failure modes for this model family, and the rectangle-fitting vectoriser downstream compounds that by assuming angular geometry.
Adjoining buildings merge. Terraced housing and connected structures often segment as one region, because the boundary between them is a roof detail rather than a change in material.
Confusable surfaces. Flat grey roofs against adjacent asphalt or paving are a recurring source of both false positives and missed detections. Shadow and overhanging tree canopy remove parts of otherwise clear buildings.
Resolution sensitivity. The model targets 0.05 m/pixel. Imagery at materially different ground sampling distance is rescaled, which degrades quality in both directions.
Unquantified. No evaluation metrics are published with this checkpoint (see Evaluation). Its accuracy on any given imagery is therefore unverified.
Normalisation is applied inside the training wrapper, not by the bare
smpmodel. Loading the raw state dict as below and feeding it unnormalised images will produce poor results. Either reproduce the wrapper (shown second) or normalise with ImageNet statistics yourself.
import torch
import segmentation_models_pytorch as smp
# weights_only=True is a security control: without it, torch.load unpickles
# arbitrary Python objects and a crafted checkpoint can execute code.
ckpt = torch.load("buildings_100e.ckpt", map_location="cpu", weights_only=True)
hparams = ckpt["hyper_parameters"]
model = smp.create_model(
arch=hparams["arch"],
encoder_name=hparams["encoder_name"],
in_channels=hparams["in_channels"],
classes=hparams["out_classes"],
)
state_dict = {
k.replace("model.", "", 1): v
for k, v in ckpt["state_dict"].items()
if k.startswith("model.")
}
model.load_state_dict(state_dict)
model.eval()
Reproducing the wrapper, which matches how GAIA runs the model:
import cv2, numpy as np, torch
import pytorch_lightning as pl
import segmentation_models_pytorch as smp
class BuildingSegModel(pl.LightningModule):
def __init__(self, arch, encoder_name, in_channels, out_classes, **kwargs):
super().__init__()
self.save_hyperparameters()
self.model = smp.create_model(
arch, encoder_name=encoder_name,
in_channels=in_channels, classes=out_classes, **kwargs,
)
params = smp.encoders.get_preprocessing_params(encoder_name)
self.register_buffer("std", torch.tensor(params["std"]).view(1, 3, 1, 1))
self.register_buffer("mean", torch.tensor(params["mean"]).view(1, 3, 1, 1))
def forward(self, image):
return self.model((image - self.mean) / self.std)
ckpt = torch.load("buildings_100e.ckpt", map_location="cpu", weights_only=True)
model = BuildingSegModel(**ckpt["hyper_parameters"])
model.load_state_dict(ckpt["state_dict"])
model.eval()
TARGET_RES = 0.05 # m/pixel
def predict(image: np.ndarray, image_resolution: float) -> np.ndarray:
"""RGB HxWx3 uint8 -> HxW uint8 likelihood (0-255)."""
h, w = image.shape[:2]
scale = image_resolution / TARGET_RES
# FPN requires spatial dimensions divisible by 32
nh, nw = int(h * scale) // 32 * 32, int(w * scale) // 32 * 32
resized = cv2.resize(image, (nw, nh))
tensor = torch.tensor(np.array([np.moveaxis(resized, 2, 0)]))
with torch.no_grad():
logits = model(tensor)
pred = logits.sigmoid()[0].numpy().squeeze()
pred = cv2.resize(pred, (w, h), interpolation=cv2.INTER_NEAREST)
return np.uint8(255 * pred)
Threshold the result to obtain a binary mask, e.g. pred >= 191 for 75%
confidence.
[More Information Needed]
Not documented in the released artefacts. Required for a complete card: dataset provenance and licence, imagery source and date, ground sampling distance, geographic coverage, annotation guidelines (specifically whether roof outline or ground footprint was annotated, and how attached structures, garages, sheds and canopies were treated), dataset size, and the train/validation/test split with any geographic separation between them.
Check the licence of the source imagery before relying on the Apache-2.0 designation. Models derived from licensed orthophotography may carry obligations from the imagery provider.
smp.encoders.get_preprocessing_params("resnet34"), applied inside the model
wrapper.100e — confirm
which is correct and correct whichever is wrongThe epoch discrepancy is worth resolving before this card is relied on: 11,250 steps implies roughly 225 batches per epoch at 50 epochs, or about 113 at 100. Either figure is a useful signal of dataset size once the batch size is known. For comparison, the companion roads model ran 3,500 steps over 50 epochs, which suggests a substantially larger training set here — worth confirming rather than assuming.
.ckpt, includes optimizer state)The published checkpoint retains optimizer state, which roughly triples its size. Stripping it to weights only would reduce the download substantially for inference-only users, at the cost of resumable training.
[More Information Needed]
Evaluation should be disaggregated by at least: urban / suburban / rural setting; building size and density; roof material and colour; detached versus attached structures; occlusion by shadow or canopy; and imagery source, season and resolution.
[More Information Needed]
Recommended for building segmentation: IoU and F1 at the operating threshold, precision/recall across thresholds, and an instance-level measure — per-building detection rate and a count of merged instances. Pixel IoU hides the failure that matters most downstream, where two adjoining buildings become one polygon.
[More Information Needed]
No quantitative evaluation is published with this checkpoint. Its performance on any given imagery is unverified, and it should be validated before operational use.
Carbon emissions can be estimated using the Machine Learning Impact calculator presented in Lacoste et al. (2019).
FPN decoder over a ResNet34 encoder; single-channel output with a sigmoid, trained for binary building segmentation. ~23.2M parameters. Spatial dimensions must be divisible by 32.
[More Information Needed]
[More Information Needed]
The model is one component of GAIA, which handles tiling, thresholding and vectorisation around it. A companion model covers roads. See the GAIA repositories for the surrounding pipeline.