Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Move from binary masks to thematic maps and GIS-ready spatial features

1. Motivation

Every workflow so far has predicted one of two classes. This page extends the same pattern to a full, multi-class land-cover scheme, and closes out the practical side of this lesson with the post-processing steps that turn a raster prediction into something you can actually use in QGIS.

Most land-cover mapping projects need more than “target class versus background.” Learning what actually changes, and what does not, when you move from 2 classes to 13 lets you extend everything from the earlier pages to your own multi-class project.


2. Core idea

Multi-class segmentation is the same underlying task as binary segmentation, with two differences: num_classes increases from 2 to however many categories your scheme defines, and your label rasters must store an integer class value (0, 1, 2, and so on) at every pixel, rather than a simple 0/1 mask. The loss function and evaluation metrics then operate across all classes simultaneously, and per-class results become essential reading, not an optional extra, exactly the lesson from evaluating detectors in L06.


3. Workflow

A. Inspect labels before training

Multi-class training data can contain more subtle errors than binary masks. Typically, you should check that the class values are valid and that the imagery and labels are aligned. Ensure that visually similar classes are consistently separated and that rare classes are present. Check that NoData and background values are handled correctly.

This page uses the Chesapeake Land Cover scheme, part of the broader land cover classification task, which defines 13 land-cover categories (water, tree canopy, impervious surfaces, and so on) for the Chesapeake Bay watershed, paired with NAIP 4-band imagery. Class 0 represents background or no-data, and classes 1 through 12 represent the actual land-cover types.

The source workflow compares the label map and imagery using a split view:

A Split-Panel Map is particularly useful for checking whether pixel labels correspond to the imagery.

B. Create the training tiles

The workflow remains familiar:

This is the same export_geotiff_tiles() call used for the binary building workflow; the only conceptual difference is that train_landcover_path now points to an integer-valued, 13-class label raster instead of a binary mask.

C. Train the multi-class model

The source example uses four-band NAIP imagery and 13 output classes:

The call is identical in shape to the binary examples, with num_classes=13 as the key change. With more classes to distinguish, some of them spectrally similar (deciduous forest and cropland can look alike at certain times of year), the model generally needs sufficient training time to learn the subtler distinctions, so multi-class problems often benefit from longer training runs than an equivalent binary task.

D. Evaluate per class

The evaluation call is the same plot_performance_metrics() used earlier in this lesson, but for multi-class problems, reading the per-class breakdown matters even more than it did for detection in L06: an aggregate IoU can look acceptable while masking a specific class, often a rare or spectrally ambiguous one, performing poorly. If a specific class matters most for your project, check its individual performance directly rather than relying on the overall number.

E. Run inference

Apply the trained model to an unseen raster:

The output raster stores the predicted class for every pixel.

F. Evaluate class-specific failures

Categorical predictions become easier to interpret when the same colour mapping is used for reference and prediction. The source workflow uses:

write_colormap() copies the same color scheme used for the training labels onto the predicted raster, so the two can be compared visually at a glance rather than needing a separate legend for each.

A consistent Colormap helps visual comparison, but colours do not replace quantitative evaluation. For multi-class segmentation, inspect not only whether a pixel is wrong but which classes are confused. A Confusion Matrix can reveal these class-to-class errors if suitable evaluation code and reference data are available. Per-class IoU is also useful.

G. Convert a class to vector output

For most downstream uses, you will vectorize one class at a time rather than the entire multi-class raster at once. For a binary water mask, the source workflow uses:

smooth_vector() softens the blocky, pixel-aligned edges that raw raster-to-vector conversion tends to produce, giving more natural-looking boundaries, a lighter-weight alternative to the full orthogonalization used for buildings in an earlier page. As before, add_geometric_properties() lets you filter out small, likely spurious polygons using an area or shape threshold before treating the result as finished.


4. Common pitfalls


5. Mini task

Your 13-class land-cover model reports an overall validation IoU of 0.75, which sounds reasonable. Per-class IoU shows tree canopy at 0.88 and wetlands at 0.31. Your project specifically needs to track wetland change over time. What does the overall number hide, and what would you do next?

Sample solution

The overall IoU of 0.75 is dominated by well-performing, likely common classes such as tree canopy, and hides the fact that wetlands, the class the project actually depends on, perform far worse at 0.31. Given this, the reasonable next step is not to accept the model as-is, but to investigate why wetlands underperform (likely candidates include class imbalance, given wetlands are probably a minority class, and spectral ambiguity with adjacent classes), and consider remedies such as a class-weighted loss, oversampling wetland-containing tiles, or adding more wetland-labeled training data before relying on the model for the project’s actual deliverable.


6. Key takeaways


Further reading