Land cover mapsfrom UAV and satellite images

The program cuts an image into objects, learns your classes from a dozen or so examples, and at the end tells you honestly how good the map is.

Image, objects, class map. Click to play it again.

Part 1 of 4

Get started

Download the version that suits you and check that your images and computer are up to it.

Three versions, one engine

Each computes exactly the same thing. Choose the one that fits your work.

QGIS plugin
when you want to see what is happening

You pick examples by clicking on the map. Accuracy assessment is available only here: point sampling, error matrix and areas with confidence intervals. English interface.

Windows application
when you do not want to install QGIS

A window with two tabs: training and classification of a whole folder. The installer does not need administrator rights. Polish interface.

Command line
when you have hundreds of images

Train a model once and run it on a folder. It fits into a script and resumes after an interruption. Polish commands and messages. How to classify a whole folder.

Installing the plugin: the plugin is in the official QGIS plugin repository. In QGIS open Plugins, Manage and Install Plugins, search for "GeoAI Classification" and click Install Plugin. QGIS will tell you about new versions. You can also download the ZIP file and choose Install from ZIP. The same plugin with a Polish interface is GeoAI Klasyfikator; both give identical results.

A browser warning for the program file means the publisher's signature is missing, not that a virus was found. The files are not signed yet; the project is preparing an application to the SignPath Foundation programme (Free code signing provided by SignPath.io, certificate by SignPath Foundation); the rules are in the code signing policy. SHA-256 checksums of all files are in the latest release.

What you need

ItemRequired?What for
RGB imageyes A drone orthomosaic, an aerial photo or a satellite scene. Three bands are enough.
Examplesyes A dozen or so places per class that you recognise for sure.
Elevation model (DSM)no, but… Without it 19 features, with it 24. It tells a roof from asphalt and a tree from a lawn. If you have one, use it.

Many images? Do not merge them, point to the folder

Dozens or hundreds of flights are classified with one command, without stitching them into a mosaic.

You do not have to merge images into one mosaic. You train the model once, on one representative image. Then you point to a folder, and the program takes the images one by one, classifies each separately and saves a separate map. At the end you get a summary report with the area of each class in each image.

One model, many images: each image in the folder is classified separately, and the results go to the maps folder.

Batch classification of folders is done by the command-line program and the Windows application. Both have a Polish interface, so the commands below keep their Polish names: ucz means train and klasyfikuj means classify.

  1. Train the model once On one image that represents the whole series well. On the command line use the ucz command; in the Windows application, the training tab. The model is saved to a .geoai file.
  2. Point to the image folder On the command line use klasyfikuj --folder; in the Windows application, the tab for classifying a whole folder. The program can also search subfolders.
  3. Collect the results For each image a GeoTIFF map with a .qml style file, and in the output folder a raport.csv file (semicolon separator, Excel-friendly encoding) with the area of each class in each image.
python geoai.py ucz --zdjecie flights/flight_01.tif --probki examples.gpkg ^
    --nmpt dsm/flight_01_nmpt.tif --model my_model.geoai

python geoai.py klasyfikuj --folder flights --model my_model.geoai ^
    --wyjscie maps --nmpt-folder dsm
All folder classification options
OptionWhat it does
--zdjecie, --probki, --nmpt, --wyjscieimage, training samples (polygons with a klasa column), DSM, output folder
--rekurencyjniealso searches subfolders for images
--nmpt-folderfolder with elevation models; for the image flight_01.tif the program picks the file flight_01_nmpt.tif (change the suffix with --nmpt-przyrostek)
--mmu 10removes patches smaller than 10 m²
--nadpisujalso reprocesses images that already have a result
--przerwij-na-bledziestops at the first problem; without this option the program reports the error for that image and carries on

Interrupted? Run it again

Without the --nadpisuj option the program skips images that already have a result, so you resume an interrupted run with the same command.

One model, similar images

A model works for images similar to those it learned from: the same camera, a similar season and lighting. A June flight and a September flight need two models.

The QGIS plugin works on one image at a time; all three versions compute with the same engine.

Computer and speed

What you need, what slows the computation down and how to speed it up without buying a new computer.

Requirements

VersionWhat it needs
QGIS pluginQGIS 3.22 or newer and nothing else
Windows application64-bit Windows; the installer (about 96 MB) contains all libraries, including the ones that speed things up
Command linePython 3.9 or newer and the numpy, rasterio and fiona libraries; scikit-image, scikit-learn and scipy are also recommended
Graphics cardnot needed: the program does not use neural networks

Memory is the main limit. The computation takes about 100 bytes per pixel of the working grid, so the largest allowed grid, 15 million pixels, needs about 1.5 GB of memory for the computation alone, on top of what the system and QGIS use. The program refuses a larger grid and suggests a coarser working resolution.

What determines computation time
FactorWhy
Number of pixels in the working grid every step goes through all pixels; a resolution twice as coarse means four times fewer pixels
Number of objects texture, shape and context are measured separately for each object; smaller objects mean more objects
Acceleration libraries with scikit-image and scikit-learn the computation runs several times faster; without scikit-image the practical limit is about half a million pixels
Elevation model (DSM) adds 5 features and estimation of the ground surface with a morphological filter
Extras the class separability check, greenness refinement and removal of small patches are separate steps
Processor Random Forest from scikit-learn spreads the trees over all processor cores

How to work faster without a new computer

Match the resolution to the goal

For fields, plots and roofs a 5 to 10 cm grid is enough. A drone image with 2 cm pixels processed on an 8 cm grid has 16 times fewer pixels. You need the finest grid, 3 to 5 cm, only for single trees and shrubs.

Try on a small part

In the plugin, tick processing only what is visible on screen. You can fine-tune the settings and examples in moments and process the whole image at the end.

Use the acceleration libraries

The Windows application includes them. In the plugin, click Install acceleration libraries in step 1 and restart QGIS. For the command line, install scikit-image, scikit-learn and scipy. The computation gets faster and the results match the reference implementation; for research work the full setup is recommended anyway.

Large objects where possible

An object should be smaller than the narrowest thing you want to show, but no smaller than that. When mapping fields, a 20 m² object instead of 5 m² means four times fewer objects to measure.

Run in the background and in batches

Run many images as a whole-folder classification, for example overnight. An interrupted run resumes with the same command, and finished images are skipped.

Mosaic too large? Split it

When a single image exceeds the limit even at a sensible resolution, split it into tiles (for example with the GDAL Retile tool in QGIS) and classify the folder of tiles with one model.

Train once, apply many times

Training takes seconds, but preparing examples takes time. In the command-line program and the Windows application the model is saved to a .geoai file, which you apply to further similar images without training again.

Free up memory

Close other programs, especially a browser with many tabs. Close to the memory limit, this can be the difference between a result and an out-of-memory message.

Sentinel-2 satellite images

It works without a drone too: 10 metres, the whole Earth, free of charge.

Sentinel-2 are satellites of the European Space Agency (Drusch et al., 2012). They image the same place every few days, and the archive goes back to 2015. A pixel is 10 metres, so one pixel covers 100 m² of ground. That is too coarse for a single tree but just right for fields, forests, water and built-up areas.

The most common trap. The program reads the first three bands of the file as red, green and blue. In a raw Sentinel-2 scene band one is aerosol, band two is blue and band three is green; red is not among them at all. The program will not report an error; it will compute something that looks like a map but is wrong. So always provide a ready RGB composite.

How to get a ready RGB image

The easiest way is the Sentinel Download plugin by the same author (Polish version: Pobieranie Sentinel). It downloads Sentinel-2 (L2A and L1C) and Sentinel-1 (GRD) images from the Copernicus Data Space and assembles ready products, including an RGB composite with the bands in the right order.

  1. Install the plugin In QGIS: Plugins, Manage and Install Plugins, type Sentinel Download and click Install.
  2. Define the area Load or draw a layer with the area you are interested in.
  3. Set dates and clouds Open the plugin, choose the area, set the date range and the maximum acceptable cloud cover.
  4. Choose the RGB product Pick RGB from the product list, download the file and wait.
  5. Give the file to the classifier Select the resulting RGB file in the Image (RGB) field.

What changes at 10 metres

AspectDroneSentinel-2
Pixel2 to 10 cm10 m
What can be recognisedsingle trees, field margins, parts of a rooflarge forms: fields, forest, built-up areas, water
Elevation modelusually available (DSM from the flight) usually not, so 19 features instead of 24
Object sizesquare metres a few dozen pixels are already thousands of square metres

Watch the clouds

A scene with 40 percent cloud cover can be useless even if your area happens to be clear, because cloud shadows remain on the ground.

A separate model for satellite data

A model trained on drone images is not suitable for Sentinel-2 and vice versa. A model works for data similar to what it learned from, so train it from scratch for satellite scenes.

Part 2 of 4

How it works

Why the program works on objects and how it learns classes from your examples.

Why objects and not pixels

The whole method rests on this, so it is worth understanding once.

Classical classification looks at each pixel separately. A pixel knows only its colour, and that is not enough to tell a grey roof from grey asphalt. The result is a map sprinkled with single dots.

Here the image is first cut into objects: groups of neighbouring pixels with similar colour. Such an object is a piece of a field, part of a roof, a tree crown. And it knows much more about itself: its colour, its texture, its shape, how high it is and what surrounds it.

1 · Image a pixel knows only its colour 2 · Objects colour + texture + shape + height 3 · Map soil crop grass road no single dots
From image to map. We classify objects, not pixels, so the map is not "littered".

What the program measures for each object

Nineteen numbers from the image alone, twenty-four if you add an elevation model. These numbers, not the picture, go into the classifier.

Colour: 7 numbers

Mean and variability of red, green and blue, and brightness. A ragged crown varies differently from a smooth roof.

Greenness: 3 numbers

ExG (Woebbecke et al., 1995), VARI (Gitelson et al., 2002), NGRDI (Hunt et al., 2005). Computed on colour proportions, so a leaf in shade and in sun look alike. They replace NDVI, which drone cameras do not provide.

Texture: 4 numbers

How much neighbouring pixels differ from each other. This tells a tree crown from metal roofing of the same colour.

Shape: 4 numbers

Area, perimeter, circularity and convexity. A long, narrow plot is something different from a compact square.

Context: 1 number

The brightness of an object compared with those that touch it. A ditch or a gap in a stand comes out darker than everything around it.

Height: 5 numbers

From the DSM: height, its variability, slope and, most importantly, height above ground. Roof versus asphalt, tree versus lawn.

Why there is no NDVI. Ordinary drone cameras record only red, green and blue and do not see near infrared at all. That is why we work with visible-band indices, texture, shape and height. In practice they are enough.

How the program learns

The whole algorithm on one small picture. The animation really computes; it is not a recording.

Image

The picture is 96 by 64 pixels with five kinds of land. The animation uses the same steps as the program, simplified: it computes 10 of the 19 features (colour and greenness), and the "operator" who picks examples is simulated by drawing objects of known class. The numbers in the panel come from this picture, not from real images.

The algorithm step by step, with all settings
  1. Reading and smoothing The program reads the first three bands of the image as red, green and blue and rescales brightness to the range 0 to 1. Before segmentation it smooths the image with a Gaussian filter (σ = 2.5) so that sensor noise and fine texture do not create artificial objects.
  2. SLIC segmentation (Achanta et al., 2012) A regular grid of seeds is placed on the image. Each pixel goes to the nearest seed, where the distance combines the colour difference in CIELAB space with the distance on the ground. The seeds move to the centre of their pixels and the whole process repeats 10 times. Compactness (0.15 by default) decides whether the boundaries follow colour or a regular grid. Finally, small leftovers are merged into neighbours so that each object is a single patch.
  3. Feature measurement Each object gets a vector of numbers: 19 features of colour, greenness (Gitelson et al., 2002; Hunt et al., 2005; Woebbecke et al., 1995), texture from the grey-level co-occurrence matrix (Haralick et al., 1973), shape and context, and 24 with an elevation model. From this point on the classifier no longer looks at the image, only at these numbers. The features are not scaled, because Random Forest splits on thresholds, not on distances.
  4. Examples and the separability check You pick examples of classes; the object containing an example gets its class. Before Random Forest learns anything, the program computes the Jeffries-Matusita distance on a scale from 0 to 2 for each pair of classes, with five-fold cross-validation, and shows which features separate them most. It also warns when the most frequent class has more than five times as many examples as the rarest one.
  5. Training the Random Forest classifier (Belgiu and Drăguţ, 2016; Breiman, 2001) 100 decision trees are built. Each learns from a random bootstrap sample of the examples, and at each node it chooses the best question "is feature X smaller than a threshold?" among randomly selected features, whose number is the integer part of √p (4 for both 19 and 24 features). The thresholds are chosen by the algorithm using the Gini criterion (Breiman et al., 2017), not by a person. The random seed is fixed (42), so the same data always give the same model.
  6. Voting and confidence Each tree passes the object through its questions and returns the class distribution of the leaf where the object landed. The distributions from 100 trees are averaged. The object gets the class with the largest share, and that share is stored as the confidence of the decision. The program counts and reports objects where the winning class got less than half of the votes.
  7. The correction loop The first map is used to find the kinds of errors. You add a few examples where Random Forest hesitates, train it again and classify again. Two or three rounds usually bring the biggest gain. In the command-line program and the Windows application the trained model is saved to a .geoai file and can be applied to further similar images.

The formulas, all constants and the literature are described in UWARUNKOWANIA_NAUKOWE.md (in Polish), chapters 3, 5 and 6.

Part 3 of 4

Step by step

From segmentation through training to the accuracy assessment of the map.

1Segmentation

One setting decides everything.

Object size is the most important decision of the whole job. There is one simple rule:

An object must be smaller than the narrowest thing you want to show on the map.

An object that is too large merges two kinds of land into one, and no classifier can fix that. One that is too small means more clicking for no gain and longer processing.

too large an object lies on two kinds of land at once just right object boundaries match boundaries on the ground too small works, but takes longer and more clicking
The yellow lines are object boundaries. Left: a problem; middle: the goal; right: only a waste of time.

Where to start

What you mapWorking resolution (m) Object size
Fields, plots, roofs0.05–0.105–20 m²
Single trees, shrubs0.03–0.052–5 m²
Canopy gaps, crowns0.10–0.2510–30 m²
Large flights, hundreds of hectares0.20–0.2520–50 m²

Before you process everything: in the plugin, tick "Process only what is visible on screen", zoom to a typical part of the image and choose the object size there. It will save you a lot of waiting.

After segmentation, look at the result and check two things: that no object lies on two different kinds of land at once (that is a problem: make the objects smaller), and that a uniform meadow has not broken into hundreds of specks (that is only an inconvenience you can live with).

2Examples

This, not the settings, decides the quality of the map.

You add classes and show the program what is what. In the plugin you click objects on the map; in the other versions you draw polygons in QGIS and save them to a file with a klasa (class) column.

Spread them over the whole image

Not in one corner. Light, shadow and soil moisture change from place to place, and the model learns what you show it.

Show every variant

"Bare soil" is freshly ploughed land, a trodden path and a dry embankment. If you show only one, the program will take the rest for something else.

Only what is certain

One wrong example teaches a wrong rule. Leave out an object on the border of two classes; the program will reject it anyway and tell you so.

How many examples? A dozen or so per class to start. You will add more anyway, and that is the normal course of work, not a sign that something went wrong.

How many classes? Four to six to begin with. Each new class is another pair to tell apart, and pairs grow faster than classes: with six classes there are already fifteen. Four well-separated classes are better than ten mixed ones.

3Training and correction

The first map is never good. That is not a bug, it is the method.

First check whether the classes can be told apart

Before you invest in clicking, the program computes how much your examples differ, pair by pair. The scale runs from 0 to 2:

ScoreWhat it meansWhat to do
above 1.9clearly different classes nothing, carry on
1.7 to 1.9fair, there will be errors add examples for this pair
below 1.7these classes will merge add examples or merge them into one

The program also shows which feature separates each pair most. If "grass" and "bare soil" differ mainly in greenness, that is a good sign. If they differ in object area, that is chance, not a pattern.

The correction loop

  1. Make a map A first version with a dozen or so examples per class.
  2. Review all of it Not just the most eye-catching patch. Scroll through the whole image.
  3. Write down the kinds of errors Not single places but kinds: "dry grass taken for soil", "shadow under a tree taken for water".
  4. Add a few examples of each kind In different parts of the image, not next to each other.
  5. Train and make the map again Two or three rounds improve the most. After that each one gives less and less.

A hint from the program: after each map you are told how many objects got less than half of the tree votes. That is exactly where the program hesitates and where your examples will make the biggest difference.

Two final corrections

Greenness refinement

A strip of grass between plots is often narrower than an object and gets lost. This option hands the decision to single pixels, but only for the two selected classes; the rest of the map stays object-based.

Note: recovered strips come out slightly wider than in reality, so be careful when reporting their area.

Minimum patch

Removes single specks by absorbing them into their surroundings. Set it for how the map will be used, not to raise the accuracy score: a sieve tuned to the check points is no longer an independent test.

4How good is this map

The part QGIS lacks, and the one that decides whether the result can be published.

A map is worth as much as you know about its errors. Judging "by eye" is not enough: you need to draw points, label them independently and count how often the map was right.

  1. The program draws check points Never on objects used for training; otherwise you would be testing the model on its own crib sheet.
  2. You label them by looking at the image alone With the classification layer turned off. The program reminds you and tells you what to turn off.
  3. You get the error matrix and figures to cite User's and producer's accuracy for each class, overall accuracy and areas with confidence intervals.

Why blind. If you can see the program's answer while labelling points, you will subconsciously agree with it. The result will be inflated by several to over a dozen percentage points, and a reviewer will notice.

How to read the result

rows: what the map says  ·  columns: what the image shows map \ image grass soil road total user's grass 46 3 1 50 92% soil 5 43 2 50 86% road 0 2 48 50 96% producer's 90% 90% 94% on the diagonal: the map and the image agree User's accuracy: when the map says "grass", how often it really is grass Producer's accuracy: how much of the real grass the map found
The two figures say different things and both are needed. In the literature they are called "user's accuracy" and "producer's accuracy".

Why the mapped area is not the true area

With stratified sampling a small class gets proportionally many points, so that something can be said about it at all. As a result the share of points is not the share of area, and a plain average over points distorts the result.

That is why the program computes everything weighting each class by its area and reports separately:

FigureWhat it isCite it?
Mapped area how many pixels the program assigned to the class no, it contains classification errors
Estimated area corrected for the errors found by the sample yes, together with the interval
95% confidence interval how precisely it was estimated yes, always next to the area

The procedure follows the recommendations of Olofsson et al. (2014) and Stehman (2014), which is what reviewers in remote sensing journals require today. The kappa coefficient is deliberately not computed: current recommendations advise against it (Pontius and Millones, 2011).

One honest remark: points labelled from the air are high-quality reference data, but not the same as field measurements. They should be described that way in a publication.

When something goes wrong

The most common problems and what to do about them.

SymptomCauseWhat to do
The map is "noisy", full of specks objects too small or too few examples increase the object size; set a minimum patch; add examples
Two classes keep getting confused they are too similar in the measured features check separability; if below 1.7, merge them or add an elevation model
Thin strips of grass disappear they are narrower than an object turn on greenness refinement or make the objects smaller
Roofs have zero height above ground you are processing a small extent, narrower than 40 m process the whole image, because the ground is estimated from wide surroundings
"Too large for the computer's memory" the working grid has more than 15 million pixels enter in Working resolution (m) at least the value given in the message, or process only the visible part
A class ended up without a single training object polygons smaller than objects draw larger polygons or reduce the object size
Processing takes very long acceleration libraries are missing in the plugin, the Install acceleration libraries button (step 1), then restart QGIS; results match the reference implementation, several times faster
Accuracy suspiciously high (above 97%) the classification layer was visible while labelling points turn it off and label the points again; otherwise the result is worthless

Part 4 of 4

For researchers

The method with sources, how to cite the program, and references.

Methods

Everything the program does has a source in the literature or in the documentation of the libraries used. Expand a subsection.

Unit of analysis

The program performs geographic object-based image analysis (GEOBIA) (Blaschke, 2010): the decision unit is not a pixel but an object, a coherent group of neighbouring pixels of similar colour. An object carries information unavailable to a single pixel, such as internal variability, texture, shape and relation to its surroundings. The output map contains no isolated misclassified pixels. Its thematic resolution is, however, limited by the object size: a feature narrower than an object will not be mapped.

Input data

The program interprets the first three bands of the image as red, green and blue and requires a projected coordinate reference system in metres. Brightness values are scaled to the range 0–1 according to the data type of the file (8-bit data divided by 255, unsigned 16-bit by 65,535, signed 16-bit by 32,767), not according to the value range in the image, so images stored in the same format remain comparable. The image is resampled to a working grid at a resolution chosen by the user, with pixel values averaged when coarsening. A working grid larger than 15 million pixels is rejected with a message. An optional digital surface model (DSM) must use the same coordinate reference system as the image. For Sentinel-2 scenes (Drusch et al., 2012) a ready RGB composite is required, because in a raw multiband product the first three bands do not correspond to red, green and blue.

Segmentation

Segmentation is performed by the SLIC algorithm (Achanta et al., 2012), that is, local k-means clustering in a five-dimensional space made of three colour components in CIELAB space and two pixel coordinates. The distance of a pixel from a cluster centre combines the colour difference dc with the spatial distance ds normalised by the seed grid interval S and weighted by compactness m: D = √(dc² + (ds/S)²·m²). The default compactness is 0.15. Before segmentation the image is smoothed with a Gaussian filter (σ = 2.5), and clustering runs for 10 iterations. Objects smaller than half of the ratio of image area to the number of objects are merged into a neighbour, so that every object forms one connected patch. When the scikit-image library (van der Walt et al., 2014) is available, the program calls its SLIC implementation with the same parameters; otherwise its own implementation of the same algorithm is used. At low compactness the realised number of objects can be two to three times smaller than requested, so the program reports the actual number of objects and the median and maximum of their areas.

Feature space

Each object is described by a vector of 19 features, or 24 when a DSM is available. The colour group comprises the means and standard deviations of the three bands and the mean brightness (7 features). The visible-band vegetation indices ExG (Woebbecke et al., 1995), VARI (Gitelson et al., 2002) and NGRDI (Hunt et al., 2005) are computed on chromatic coordinates (r = R/(R+G+B), and likewise g and b), which removes the brightness component and reduces the effect of variable illumination (3 features). Texture is described by four grey-level co-occurrence matrix measures (Haralick et al., 1973): contrast, homogeneity, energy and entropy. They are computed for luminance quantised globally to 15 levels, at a distance of 1 pixel and in four directions (0°, 45°, 90°, 135°); objects smaller than 16 pixels receive neutral values. Shape is described by area, perimeter estimated with the Crofton method, circularity 4πA/P² and convexity relative to the convex hull (4 features). Context is the difference between the brightness of an object and the mean brightness of adjacent objects in a 4-connected adjacency graph (1 feature). From the DSM the program derives the mean and standard deviation of height, mean slope, height relative to neighbours and height above ground (5 features). The ground surface is estimated from the DSM alone: minimum in blocks of about 1 m, morphological opening with a 40 m window and smoothing with a moving average. Features are not standardised, because Random Forest splits the feature space with thresholds and is insensitive to monotonic transformations of a single feature.

Classification

The decision rule is Random Forest (Breiman, 2001), a classifier widely used in remote sensing (Belgiu and Drăguţ, 2016). The model consists of 100 trees. Each tree learns from a bootstrap sample, and at each node it chooses a split among √p randomly selected features (the integer part of √p, that is 4 for both 19 and 24 features) using the Gini criterion (Breiman et al., 2017), without class weights and without a depth limit (up to 40 levels in the built-in implementation). The seed of the pseudo-random number generator is 42, which makes the result repeatable. An object receives the class with the largest share in the averaged class distribution from the leaves of all trees (soft voting), and that share is stored as the confidence of the decision. The program counts objects with confidence below 0.5 and warns when the ratio between the most and least frequent training class exceeds 5:1. When the scikit-learn library (Pedregosa et al., 2011) is available, its implementation is used with these parameters; otherwise the built-in implementation is used.

Class separability

Before training, the program estimates the separability of each pair of classes with the Jeffries-Matusita distance, JM = 2(1 − e−B), where B is the Bhattacharyya distance. The classical JM computed in the full feature space on the same samples from which the parameters were estimated reaches values close to 2 for almost every pair of classes with 24 features and a few hundred samples. A variant with five-fold cross-validation is therefore used. On the training part, the Fisher discriminant direction (Fisher, 1936) is determined with a covariance matrix estimated with Ledoit-Wolf shrinkage (Ledoit and Wolf, 2004), and the distance is computed on the projections of the test part. This measure is a lower bound of the full multivariate distance. The thresholds 1.9 and 1.7 are therefore indicative, and the most useful outputs are the ranking of class pairs and the ranking of the features that separate them.

Post-classification corrections

Two optional corrections break the purely object-based character of the map and, if used, should be reported. The first decides the membership of single pixels for two selected classes from ExG averaged in a 3 × 3 pixel window. The threshold is set on the training samples by maximising the mean accuracy of both classes. The correction recovers features narrower than an object at the cost of slightly widening the recovered strips. The second correction, the minimum mapping unit, absorbs patches smaller than the threshold into the surrounding class using the sieve filter of the GDAL library (GDAL/OGR contributors, 2026) with 4-connectivity. The sieve threshold should follow from the purpose of the map, not from optimising the accuracy assessment.

Accuracy assessment and area estimation

Accuracy assessment is based on stratified sampling by map class: each class receives at least 50 points (default value), and the remaining points are allocated in proportion to area. Check points do not fall on objects used for training, so the target population is the map outside those objects. The area weights of the strata are stored at the moment of sampling, so that the strata remain attached to the sample even if the map changes later (Stehman, 2014). The interpreter labels the points with the classification layer hidden, which limits confirmation bias. From the error matrix (Congalton and Green, 2019) the program derives overall accuracy, user's and producer's accuracy, and class proportions and areas using area-weighted estimators with 95 percent confidence intervals (Olofsson et al., 2014). The implementation reproduces the worked example from that paper (Table 8): overall accuracy is 0.9449 against the published value of 0.944. The kappa coefficient is not computed (Pontius and Millones, 2011).

Implementation and reproducibility

The program is written in Python and uses the NumPy (Harris et al., 2020) and SciPy (Virtanen et al., 2020) libraries. Reading and writing spatial data is done by GDAL (GDAL/OGR contributors, 2026) in the QGIS plugin and by the rasterio and Fiona libraries in the command-line program. The QGIS plugin, the command-line program and the Windows desktop application share the same computational engine; the English and Polish editions of the plugin are generated from the same code. The Windows application is built automatically in GitHub Actions from the code in the repository, and each release is published with SHA-256 checksums. The source code is available under the GPL-3.0-or-later licence. To reproduce a result, report the program version, the versions of scikit-image and scikit-learn (or that the built-in implementations were used), the random seed and the values of all user-set parameters.

Limitations

The method uses only the visible range, so it does not use near infrared or indices such as NDVI. A model does not transfer between flights without retraining, because illumination, phenological stage and camera settings shift the feature distributions. Features narrower than an object are underestimated. Under continuous cover wider than 40 m the estimated ground surface rises onto that cover, which underestimates height above ground. Without class weights, rare classes are systematically underestimated when the training set is imbalanced. The program does not use features derived from deep neural networks, so classes that differ only in spatial pattern, not in material, may remain inseparable.

How to cite

The program is archived in Zenodo and has persistent DOI identifiers.

G. Górniak, "GeoAI Klasyfikator," version 1.0.3, Zenodo, 2026, doi: 10.5281/zenodo.24011434.

The archived software is GeoAI Klasyfikator; the English plugin, GeoAI Classification, is built from the same code, so cite the same record.

IdentifierDOIWhen to use it
All versions 10.5281/zenodo.24005560 referring to the program in general; always resolves to the latest version
Version 1.0.3 10.5281/zenodo.24011434 a result computed with exactly this version, for example in a paper

References

Elsevier style (Harvard, with titles). All entries ready to import into Zotero: bibliografia.bib (in Zotero: File, Import).

Show all entries (21)
  1. Achanta, R., Shaji, A., Smith, K., Lucchi, A., Fua, P., Süsstrunk, S., 2012. SLIC Superpixels Compared to State-of-the-Art Superpixel Methods. IEEE Transactions on Pattern Analysis and Machine Intelligence 34, 2274–2282. https://doi.org/10.1109/TPAMI.2012.120
  2. Belgiu, M., Drăguţ, L., 2016. Random forest in remote sensing: A review of applications and future directions. ISPRS Journal of Photogrammetry and Remote Sensing 114, 24–31. https://doi.org/10.1016/j.isprsjprs.2016.01.011
  3. Blaschke, T., 2010. Object based image analysis for remote sensing. ISPRS Journal of Photogrammetry and Remote Sensing 65, 2–16. https://doi.org/10.1016/j.isprsjprs.2009.06.004
  4. Breiman, L., 2001. Random Forests. Machine Learning 45, 5–32. https://doi.org/10.1023/A:1010933404324
  5. Breiman, L., Friedman, J.H., Olshen, R.A., Stone, C.J., 2017. Classification and Regression Trees. Routledge, New York. https://doi.org/10.1201/9781315139470
  6. Congalton, R.G., Green, K., 2019. Assessing the Accuracy of Remotely Sensed Data: Principles and Practices, 3rd ed. CRC Press, Boca Raton. https://doi.org/10.1201/9780429052729
  7. Drusch, M., Del Bello, U., Carlier, S., Colin, O., Fernandez, V., Gascon, F., Hoersch, B., Isola, C., Laberinti, P., Martimort, P., Meygret, A., Spoto, F., Sy, O., Marchese, F., Bargellini, P., 2012. Sentinel-2: ESA’s Optical High-Resolution Mission for GMES Operational Services. Remote Sensing of Environment 120, 25–36. https://doi.org/10.1016/j.rse.2011.11.026
  8. Fisher, R.A., 1936. The use of multiple measurements in taxonomic problems. Annals of Eugenics 7, 179–188. https://doi.org/10.1111/j.1469-1809.1936.tb02137.x
  9. GDAL/OGR contributors, 2026. GDAL/OGR Geospatial Data Abstraction software Library. Open Source Geospatial Foundation. https://doi.org/10.5281/zenodo.5884351
  10. Gitelson, A.A., Kaufman, Y.J., Stark, R., Rundquist, D., 2002. Novel algorithms for remote estimation of vegetation fraction. Remote Sensing of Environment 80, 76–87. https://doi.org/10.1016/S0034-4257(01)00289-9
  11. Haralick, R.M., Shanmugam, K., Dinstein, I., 1973. Textural Features for Image Classification. IEEE Transactions on Systems, Man, and Cybernetics SMC-3, 610–621. https://doi.org/10.1109/TSMC.1973.4309314
  12. Harris, C.R., Millman, K.J., van der Walt, S.J., Gommers, R., Virtanen, P., Cournapeau, D., Wieser, E., Taylor, J., Berg, S., Smith, N.J., Kern, R., Picus, M., Hoyer, S., van Kerkwijk, M.H., Brett, M., Haldane, A., del Río, J.F., Wiebe, M., Peterson, P., Gérard-Marchant, P., Sheppard, K., Reddy, T., Weckesser, W., Abbasi, H., Gohlke, C., Oliphant, T.E., 2020. Array programming with NumPy. Nature 585, 357–362. https://doi.org/10.1038/s41586-020-2649-2
  13. Hunt, E.R., Cavigelli, M., Daughtry, C.S.T., McMurtrey, J.E., Walthall, C.L., 2005. Evaluation of Digital Photography from Model Aircraft for Remote Sensing of Crop Biomass and Nitrogen Status. Precision Agriculture 6, 359–378. https://doi.org/10.1007/s11119-005-2324-5
  14. Ledoit, O., Wolf, M., 2004. A well-conditioned estimator for large-dimensional covariance matrices. Journal of Multivariate Analysis 88, 365–411. https://doi.org/10.1016/S0047-259X(03)00096-4
  15. Olofsson, P., Foody, G.M., Herold, M., Stehman, S.V., Woodcock, C.E., Wulder, M.A., 2014. Good practices for estimating area and assessing accuracy of land change. Remote Sensing of Environment 148, 42–57. https://doi.org/10.1016/j.rse.2014.02.015
  16. Pedregosa, F., Varoquaux, G., Gramfort, A., Michel, V., Thirion, B., Grisel, O., Blondel, M., Prettenhofer, P., Weiss, R., Dubourg, V., Vanderplas, J., Passos, A., Cournapeau, D., Brucher, M., Perrot, M., Duchesnay, É., 2011. Scikit-learn: Machine Learning in Python. Journal of Machine Learning Research 12, 2825–2830. https://jmlr.org/papers/v12/pedregosa11a.html
  17. Pontius, R.G., Millones, M., 2011. Death to Kappa: birth of quantity disagreement and allocation disagreement for accuracy assessment. International Journal of Remote Sensing 32, 4407–4429. https://doi.org/10.1080/01431161.2011.552923
  18. Stehman, S.V., 2014. Estimating area and map accuracy for stratified random sampling when the strata are different from the map classes. International Journal of Remote Sensing 35, 4923–4939. https://doi.org/10.1080/01431161.2014.930207
  19. Virtanen, P., Gommers, R., Oliphant, T.E., Haberland, M., Reddy, T., Cournapeau, D., Burovski, E., Peterson, P., Weckesser, W., Bright, J., van der Walt, S.J., Brett, M., Wilson, J., Millman, K.J., Mayorov, N., Nelson, A.R.J., Jones, E., Kern, R., Larson, E., Carey, C.J., Polat, İ., Feng, Y., Moore, E.W., VanderPlas, J., Laxalde, D., Perktold, J., Cimrman, R., Henriksen, I., Quintero, E.A., Harris, C.R., Archibald, A.M., Ribeiro, A.H., Pedregosa, F., van Mulbregt, P., Vijaykumar, A., Bardelli, A.P., Rothberg, A., Hilboll, A., Kloeckner, A., Scopatz, A., Lee, A., Rokem, A., Woods, C.N., Fulton, C., Masson, C., Häggström, C., Fitzgerald, C., Nicholson, D.A., Hagen, D.R., Pasechnik, D.V., Olivetti, E., Martin, E., Wieser, E., Silva, F., Lenders, F., Wilhelm, F., Young, G., Price, G.A., Ingold, G.-L., Allen, G.E., Lee, G.R., Audren, H., Probst, I., Dietrich, J.P., Silterra, J., Webber, J.T., Slavič, J., Nothman, J., Buchner, J., Kulick, J., Schönberger, J.L., de Miranda Cardoso, J.V., Reimer, J., Harrington, J., Rodríguez, J.L.C., Nunez-Iglesias, J., Kuczynski, J., Tritz, K., Thoma, M., Newville, M., Kümmerer, M., Bolingbroke, M., Tartre, M., Pak, M., Smith, N.J., Nowaczyk, N., Shebanov, N., Pavlyk, O., Brodtkorb, P.A., Lee, P., McGibbon, R.T., Feldbauer, R., Lewis, S., Tygier, S., Sievert, S., Vigna, S., Peterson, S., More, S., Pudlik, T., Oshima, T., Pingel, T.J., Robitaille, T.P., Spura, T., Jones, T.R., Cera, T., Leslie, T., Zito, T., Krauss, T., Upadhyay, U., Halchenko, Y.O., Vázquez-Baeza, Y., 2020. SciPy 1.0: fundamental algorithms for scientific computing in Python. Nature Methods 17, 261–272. https://doi.org/10.1038/s41592-019-0686-2
  20. van der Walt, S., Schönberger, J.L., Nunez-Iglesias, J., Boulogne, F., Warner, J.D., Yager, N., Gouillart, E., Yu, T., 2014. scikit-image: image processing in Python. PeerJ 2, e453. https://doi.org/10.7717/peerj.453
  21. Woebbecke, D.M., Meyer, G.E., Von Bargen, K., Mortensen, D.A., 1995. Color Indices for Weed Identification Under Various Soil, Residue, and Lighting Conditions. Transactions of the ASAE 38, 259–269. https://doi.org/10.13031/2013.27838
↑