Self-hosted service
sentinel-hub/eo-learn avatar
sentinel-hub/eo-learn

eo-learn: A Task Graph Layer Between Sentinel Hub Imagery and Python ML

Earth observation processing framework for machine learning in Python

1,250 stars304 forksPythonMIT

At a glance

What is it?
eo-learn is an MIT-licensed Python framework that turns satellite image processing into a sequence of composable EOTask objects operating on a shared EOPatch container. It is a good fit when your pipeline is already Python and your imagery comes from Sentinel Hub; it is a poor fit if you want a self-contained geospatial engine with no service dependency.
Who is it for?
Adopt eo-learn if your imagery already flows through Sentinel Hub and you want cloud masking, co-registration and feature extraction expressed as reusable Python tasks rather than bespoke scripts. Do not adopt it if you need a self-contained processing engine with no external data service, or if your team will not maintain the GDAL, rasterio, shapely and fiona system dependencies across platforms.
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 7 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 gap eo-learn fills between raw scenes and a training set

The README frames the problem in terms of data volume: open Earth observation data from Copernicus and Landsat is described as an unprecedented resource, and the note that high spatial resolution arrives at high revisit frequency is the reason ad hoc scripting stops scaling. A single region of interest over a season is a spatio-temporal cube, not a stack of files. Someone has to fetch the scenes, mask cloud and snow, align them, compute indices, and only then hand a numeric array to a classifier. Each of those steps is small and each is easy to get subtly wrong.

eo-learn's stated aim is to make that extraction as easy as defining a sequence of operations. The audience is split, and the README says so: the library acts as a bridge between remote sensing and the Python data science ecosystem, with the goal of lowering the entry barrier for non-experts while bringing computer vision and machine learning tooling to remote sensing specialists. That is a two-sided claim, and it shapes the API. Remote sensing data is held in NumPy arrays, which is the format a scikit-learn or PyTorch user already expects. The cost is that the geographic metadata lives alongside those arrays rather than inside a labelled data model, and you feel that when you want to slice by coordinate rather than by index.

EOPatch, EOTask, EOWorkflow: the three objects you actually work with

The core module implements three building blocks, and the README names them explicitly: EOPatch, EOTask and EOWorkflow. The division of labour is clean. EOPatch is the container that travels through the pipeline, holding the raster data, the masks, the vector geometries and the metadata for one region of interest. EOTask is a single unit of work with a defined input and output, such as computing a cloud mask or co-registering an image pair. EOWorkflow is the sequence, and the README's illustration is a chain that maps water by thresholding the Normalised Difference Water Index inside a user-specified region.

The design consequence is that a workflow is data-driven rather than imperative. Tasks are meant to be shareable and reusable, which is why the project describes itself as encouraging collaboration around specific tasks in an EO value-extraction workflow. If you have written the same cloud-masking function in three notebooks, this is the abstraction that removes the duplication. If your processing is genuinely one-off, the abstraction adds a layer you will fight.

The module list shows how far the task catalogue reaches: coregistration for image alignment, features for extracting data properties and manipulating them, geometry for vector-to-raster conversion, io for pulling from Sentinel Hub services or reading and writing locally, mask for cloud, snow and other masks, ml-tools for pre- and post-processing around a model, and visualization for plotting the core elements. Note the naming convention: some modules carry an extra subfolder for tasks that need dependencies the default install does not pull in.

Getting a working install is the first real obstacle

The package requires Python 3.8 or newer. On Linux the README recommends installing system libraries first:

sudo apt-get install gcc libgdal-dev graphviz proj-bin libproj-dev libspatialindex-dev

On macOS the equivalent is Homebrew:

brew install graphviz gcc gdal cmake spatialindex proj

On Windows there is no package-manager line. The README points at the Unofficial Windows wheels repository for gdal, rasterio, shapely and fiona. That asymmetry is worth reading carefully. GDAL, PROJ and spatialindex are native libraries, and on Windows you are expected to source prebuilt wheels from a third-party index rather than from conda-forge or pip defaults. If your team is mixed-platform, this is the step most likely to consume a day.

Once the system libraries are present, the Python install is ordinary: pip install eo-learn, or conda config --add channels conda-forge followed by conda install eo-learn. A Docker image, sentinelhub/eolearn, is published on Docker Hub with a full installation plus a Jupyter notebook environment, which is the shortest path to a reproducible environment if you do not want to manage GDAL yourself.

The extras are the part people miss. pip install "eo-learn[EXTRA]" and pip install "eo-learn[VISUALIZATION]" are the documented examples, and the README lists RAY for ray and its dependencies, ZARR for chunked timestamp saving and loading, EXTRA for interpolation and clustering dependencies or for s2cloudless in cloud masking, VISUALIZATION for plotting libraries, FULL for everything, plus DOCS and DEV for contributors. The README is explicit about why: extras were kept separate to keep the installation light. So a cloud-masking workflow that relies on s2cloudless will fail until you install the EXTRA extra, and that failure arrives at runtime rather than at install time.

Where eo-learn is the wrong tool

The io module is described as dealing with data from Sentinel Hub services or with saving and loading locally. The framework's centre of gravity is the Sentinel Hub path. If your imagery comes from a local archive, an on-premises distribution, or a provider outside that ecosystem, you are using the framework against its grain: you would be writing your own io tasks to feed EOPatch objects that the rest of the library expects to receive in a particular shape. That is possible, and the task abstraction is designed to be extended, but the value proposition weakens considerably.

The second limitation is the dependency surface. GDAL, rasterio, shapely, fiona, PROJ and spatialindex are heavy native libraries with their own release cadences. The README's platform-specific instructions exist precisely because this stack is not uniformly installable. A container sidesteps the problem for one machine but does not remove the underlying coupling.

The third is the NumPy-array data model. Storing imagery as arrays is what makes the scikit-learn and PyTorch handoff natural, and it is also what makes label-aware slicing, lazy evaluation and out-of-core computation harder than they would be in a labelled-array framework. For a region of interest that fits comfortably in memory this never matters. For continental-scale mosaics, the framework's own answer is the ZARR extra for chunked timestamp saving and loading, which tells you the maintainers expect you to reach for a chunked storage layer rather than to hold everything in RAM.

How this differs from an xarray and dask stack

The obvious alternative for spatio-temporal Earth observation work in Python is to build on xarray with dask for out-of-core execution, using rioxarray for the raster I/O. The difference in approach is structural rather than cosmetic. xarray gives you labelled N-dimensional arrays: dimensions have names, coordinates carry the geospatial transform, and slicing by date or bounding box is a first-class operation. dask lets those arrays be chunked and computed lazily, so the size of your dataset is not bounded by RAM. You assemble the pieces yourself.

eo-learn inverts that. The unit of composition is the task, not the array. You get a catalogue of ready-made operations for cloud masking, co-registration, index computation and feature extraction, and you get a workflow runner that sequences them. What you give up is the labelled data model and the lazy execution graph. An EOPatch is eager materialised data; the framework's answer to scale is chunked storage via ZARR rather than a general task graph scheduler.

Neither choice is strictly better. If your bottleneck is writing and validating remote sensing algorithms, the task catalogue saves real time. If your bottleneck is moving terabytes through a cluster, the labelled lazy-array stack gives you more room. Some teams use both, with eo-learn handling the per-tile feature extraction and a chunked array layer handling the storage and assembly.

Release cadence, licence and what you are signing up to maintain

The release history shows v1.5.7 on 2024-09-27, v1.5.6 on 2024-06-26 and v1.5.5 on 2024-06-19. Two releases inside a week followed by a three-month gap is the pattern of a project that ships patch fixes in bursts rather than on a calendar. The repository is not archived and the last push date is recent, so the project is active, but the version numbers tell you this is a mature 1.x line where the API is not expected to churn.

The licence is MIT, which is permissive: it permits commercial and closed-source use, modification and redistribution provided the copyright notice and permission notice are preserved. That is a meaningful difference from the copyleft geospatial stack, and it matters if you are embedding eo-learn inside a product. This is a description of the licence text, not legal advice; run your own review if the distinction affects your distribution model.

Maintenance cost is dominated by the native dependency chain rather than by eo-learn's own code. Every GDAL or PROJ bump upstream can ripple into rasterio, fiona and shapely, and the README's Windows instructions already route you to third-party wheels. Pinning the whole stack, or using the published Docker image, is the practical mitigation. The extras system adds a second maintenance axis: because EXTRA, ZARR, RAY and VISUALIZATION are opt-in, your environment file has to track which tasks your workflows import, and a task added six months from now may pull in a dependency nobody recorded.

Who should adopt eo-learn

Adopt it if your imagery already arrives through Sentinel Hub, your team writes Python, and you have more than one workflow that repeats the same masking, alignment and index steps. The task abstraction pays for itself the second time you need the same cloud mask in a different notebook, and the NumPy data model means the output drops straight into scikit-learn or a PyTorch dataloader without a conversion layer.

Do not adopt it if you need a self-contained engine with no external data service, if your imagery comes from an archive the io module does not cover and you are unwilling to write those tasks, or if nobody on the team wants to own a GDAL-adjacent dependency stack across operating systems. In that last case the Docker image is the honest answer, and if a container is not acceptable, the framework's installation story is working against you.

Verify these before you commit. First, which extras your task list imports: check for s2cloudless in your masking tasks (EXTRA), zarr if you plan chunked timestamp storage (ZARR), and any ray usage (RAY). Second, whether the Sentinel Hub credential and account path your deployment will use is documented for your environment, since the io module is the entry point for data and the README does not cover authentication setup. Third, run the install on every platform your team uses, not just the one you develop on, because the Windows path through the Unofficial Windows wheels repository for gdal, rasterio, shapely and fiona is a different procedure from the apt and brew lines.

Editorial conclusion

Adopt eo-learn if your imagery already flows through Sentinel Hub and you want cloud masking, co-registration and feature extraction expressed as reusable Python tasks rather than bespoke scripts. Do not adopt it if you need a self-contained processing engine with no external data service, or if your team will not maintain the GDAL, rasterio, shapely and fiona system dependencies across platforms. Before committing, verify two things: that the Sentinel Hub account and credential path your pipeline will use is documented for your deployment, and which extras (EXTRA, ZARR, RAY, VISUALIZATION, FULL) your task list actually imports, since the default install deliberately excludes them.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. sentinel-hub/eo-learn on GitHub
Community notes

Community notes