Model or dataset
ucam-eo/tessera avatar
ucam-eo/tessera

TESSERA: A 128-Dimensional Per-Pixel Embedding Model for Satellite Time Series

[CVPR26] TESSERA is a foundation model that can process time-series satellite imagery for applications such as land classification and canopy height prediction. Developed at the University of Cambridge, it enables efficient extraction of temporal patterns from Earth observation

743 stars69 forksPythonMIT

At a glance

What is it?
TESSERA is a University of Cambridge foundation model that turns cloud-corrupted satellite time series into 128-dimensional per-pixel embeddings at 10-metre resolution. The idea is sound and the tooling is split across two repositories, which is the first thing to understand before adopting it.
Who is it for?
Adopt TESSERA if your task is per-pixel classification or regression over a region where annual 10m embeddings already exist, and you want to avoid training a temporal model from scratch. Do not adopt it if you need sub-10m detail, sub-annual temporal resolution, or an offline pipeline, since the practical access path runs through the geotessera package and the hosted embedding service.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 30 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem TESSERA targets is labelled data scarcity, not model capacity

The README frames the bottleneck precisely: satellite time series are voluminous and often cloud-corrupted, and the community's ability to extract insight is constrained by scarce labelled training datasets and the compute cost of temporal processing. That is a different problem from the one most remote sensing models solve. A segmentation network trained on a few thousand hand-annotated tiles will do well on those tiles and poorly elsewhere, because the labels, not the architecture, are the limit. TESSERA attacks the label side by producing a reusable representation. The intended user is a researcher or engineer who has labels for a small area and wants a feature vector per pixel that already encodes the phenological signal, so a linear probe or a shallow classifier can carry the rest. Habitat mapping, carbon accounting, and land use strategy are the applications named in the introduction. If your work is single-date image classification over RGB tiles, this is the wrong layer of the stack.

Barlow Twins over cloud-free pairs is the whole mechanism

The design rests on one insight, attributed in the README to Dr. Clement Atzberger: force auto-encoder embeddings derived from two cloud-free random samples of the same satellite time series to align using Barlow Twins, and the resulting embedding represents the entire time series, including the observations that were missing. That is the part worth pausing on. Cloud contamination is normally handled by masking, gap-filling, or compositing before the model sees anything. Here the corruption is part of the training signal. Two disjoint clear-sky subsets of one pixel's history are pushed toward the same latent point, so the encoder learns what is invariant across the two samples, which is the surface and its seasonal cycle rather than the particular dates that happened to be cloud-free. The output is a 128-dimensional vector per pixel at 10-metre resolution, described in the README as preserving per-pixel spectral-temporal signals. The claim that this preserves phenological signals typically lost in conventional approaches follows from the same construction: a mean composite throws away the shape of the season, and the embedding does not.

Two repositories, and the split matters for how you adopt it

The README shows a PyPI badge for geotessera alongside the tessera repository name, and the tip box links to ucam-eo/geotessera for embedding pre-requests. The practical reading is that tessera holds the model and inference code while geotessera is the client for precomputed embeddings. That distinction decides your integration path. If you only need features, you request or download embeddings and never touch the model weights. If you need embeddings for a region or date range nobody has processed, you are in the second path, and the README warns that v2 coverage is still rolling out, directing users who need embeddings immediately to request v1.1 instead. Note also that the bug tracker and feature request links in the README point at a different repository (FrankFeng-23/btfm_project), and the hero animation lives under FrankFeng-23/tessera-v2-animation. The project is real and the papers are listed, but the issue surface is not consolidated under ucam-eo, which is worth knowing before you file anything.

Four checkpoints, and the version choice is not cosmetic

The inference section lists TESSERA v2 as recommended, then v1.1 (QAT INT8), v1.0 (QAT INT8), and v1.0 (early, float32). The parenthetical labels are the useful part. QAT INT8 means quantization-aware training, so the int8 weights were trained with quantization in the loop rather than converted afterwards, which is why they are offered as first-class checkpoints rather than a compression afterthought. The early float32 v1.0 is the original. The README does not state whether embeddings from different versions are comparable, and that is the gap I would flag hardest. If you build a classifier on v1.1 embeddings and later switch a region to v2, nothing in the supplied material says the 128 dimensions mean the same thing across versions. Treat the version string as part of your feature schema and record it next to every embedding you store. The same caution applies to the v1.1 versus v2 coverage split: a map assembled from both is a map assembled from two feature spaces until someone confirms otherwise.

Getting embeddings without running inference

The lowest-friction path is the one the tip box pushes. Open an issue on ucam-eo/geotessera using the v2-embedding-prerequest template, which is linked with the label v2-embedding-prerequest, to reserve your region and join the early testers. The README states that v2 coverage is still rolling out and that areas are prioritised, so this is a queue, not an instant service. If you need embeddings now, the same tip points to requesting v1.1 embeddings through the geotessera README's missing-embeddings section. The PyPI badge indicates geotessera is published, which is the package to install if you intend to pull embeddings programmatically rather than by request. I have not installed it and cannot confirm the exact function signatures from the material supplied, so read the geotessera README for the call pattern rather than guessing from the badge. What the material does establish is the shape of the workflow: request or fetch a region, receive per-pixel 128-dimensional vectors on a 10-metre grid, then attach your labels.

Running the model yourself, and the cost that implies

The README separates Creating Your Own Embeddings from Inference, and lists the four checkpoint options under the inference heading. That is the path for regions the hosted service does not cover. The honest framing is that this is the expensive branch. The model consumes satellite time series, the introduction describes summarising petabytes of Earth observation data during training, and the input to inference is a temporal stack per pixel rather than a single image. Anyone choosing this route is signing up for the data acquisition and preprocessing work that the precomputed embeddings exist to spare them, plus GPU capacity for the encoder. The compensating argument is data sovereignty, which the README names directly: a privacy-preserving design that lets researchers keep their data in place. If your imagery cannot leave your infrastructure, self-hosting is not a preference, it is the only option, and the MIT licence on the code removes the licensing question from that decision.

The 10-metre, annual, per-pixel framing is a boundary, not a detail

Three constraints are baked into the design and each rules out a class of work. Resolution: 10 metres globally, which matches Sentinel-2's native grid and means field boundaries, hedgerows, and smallholder plots below that scale are not separable. The README's own crop classification paper is titled around compact embeddings suitable for small fields, which suggests the authors are aware of the pressure point. Temporal granularity: the README describes global annual coverage, so a task that turns on intra-season timing, such as distinguishing a crop that failed in June from one that failed in August, is working against the embedding's design intent. Spatial unit: per-pixel vectors. Tasks that need object-level reasoning, counting individual trees or delineating building footprints, will have to build that layer themselves on top of the pixel grid. There is also the coverage caveat already noted. A global model with rolling v2 coverage is, in practice, a model with a patchwork of availability, and any pipeline that assumes uniform coverage will break on the gaps.

Where TESSERA sits against Sentinel-2 compositing and task-specific models

The obvious alternative is the conventional approach: build cloud-free composites from Sentinel-2, stack bands and indices like NDVI across a season, and train a supervised classifier on those stacks. The difference is in what gets discarded. Compositing collapses a season into a handful of images or statistical summaries, so the shape of the phenological curve is compressed into whatever statistics you chose. TESSERA keeps the temporal signal in the embedding by training on the cloud-free structure itself. The cost of that choice is opacity: an NDVI time series can be plotted and reasoned about by an agronomist, while a 128-dimensional vector cannot. The second alternative is a task-specific model trained end to end on your labels. The README states that TESSERA closely matches or outperforms state-of-the-art task-specific models and other foundation models across five downstream tasks, which is the claim to check against your own data rather than accept. The trade-off is straightforward: a task-specific model can beat a general embedding when you have enough labels, and TESSERA's value is largest exactly when you do not.

Licence, maintenance, and what to verify before you commit

The code is MIT licensed, which is permissive and imposes no copyleft obligation on your downstream work. Two things sit outside that. The README links an Acceptable Use Policy section, so usage terms exist beyond the licence text, and the precomputed embeddings are served through geotessera rather than shipped as model weights. Whether the embedding service carries terms separate from the MIT code is not stated in the supplied material, and I am not in a position to give legal advice on it; read the AUP before you build a product on hosted embeddings. On maintenance, the last push recorded is 2026-08-17 and no releases were retrieved, so versioning appears to run through the PyPI package and the checkpoint names rather than GitHub releases. The papers list stretches from 2024 through 2026 with a CVPR 2026 appearance, which indicates an active research programme behind the code. For a team evaluating adoption, the concrete checks are these: confirm your region is covered and by which version, pin the geotessera version and the embedding version in your pipeline, and reproduce one of the five downstream tasks on your own labels before trusting the headline comparison.

Editorial conclusion

Adopt TESSERA if your task is per-pixel classification or regression over a region where annual 10m embeddings already exist, and you want to avoid training a temporal model from scratch. Do not adopt it if you need sub-10m detail, sub-annual temporal resolution, or an offline pipeline, since the practical access path runs through the geotessera package and the hosted embedding service. Before committing, check whether your region is covered by v1.1 or the rolling-out v2, and confirm which checkpoint the embedding you download was produced from.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. ucam-eo/tessera on GitHub
Community notes

Community notes