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.

Scaling training-data creation from one image to many paired files

Open In Colab

1. Motivation

Real project data rarely comes as a single tidy image and a single annotation file. You may have several scenes, tiles, or dates, each needing the same tiling treatment, and each needing to be paired correctly with its own annotations. Getting the pairing wrong, silently, is one of the more damaging mistakes you can make at this stage, since a model trained on mismatched images and masks can still appear to train “successfully” while learning nothing useful.


2. Core idea

export_geotiff_tiles_batch() extends single-image tiling to a folder of images, and supports three ways of matching images to their annotations, depending on how your files happen to be organized.


3. Workflow

A. Know your three pairing options

  • Single vector file covering all images: most efficient when one annotation file spans several image tiles.

  • Multiple vector files matched by sorted order: pairs the first image with the first mask file, the second with the second, and so on. Use this only when you are confident the sorted file lists genuinely line up.

  • Multiple vector files matched by filename: pairs files that share the same base name (for example, tile1.tif with tile1.geojson). This is the safest option whenever your naming convention supports it.

ModeUse whenKey parameter
Single vector fileOne annotation file covers all images.masks_file="path/to/file.geojson"
Multiple files by sorted orderFiles line up alphabetically.masks_folder="path/", match_by_name=False
Multiple files by filenameImages and labels share base names.masks_folder="path/", match_by_name=True

Matching by filename is usually the safest option when filenames are designed consistently.

B. Get and explore the sample data

The sample dataset for this page contains three adjacent SWISSIMAGE tiles (0.5 m RGB, Willisau 2024), plus swissBUILDINGS3D building footprints in two formats: one GeoJSON file covering all three tiles, and separate GeoJSON files matched to each tile. Downloading and listing it first shows you exactly what the three pairing modes below are actually operating on.

Images:
 - willisau_2024_swissimage_tile-01.tif
 - willisau_2024_swissimage_tile-02.tif
 - willisau_2024_swissimage_tile-03.tif

Annotations (single file):
 - willisau_2024_swissbuildings3D_clip.geojson

Annotations (multiple files):
 - willisau_2024_swissimage_tile-01.geojson
 - willisau_2024_swissimage_tile-02.geojson
 - willisau_2024_swissimage_tile-03.geojson

Notice that mask1/ holds one GeoJSON file for all three images, while mask2/ holds one GeoJSON file per image, this is exactly the “single file” versus “multiple files” distinction from step A.

C. Preview one pair before running all

Before pairing and tiling a whole folder, check that at least one image/annotation pair actually lines up, the same habit from the imagery and annotations page, just applied here to a batch dataset. display_image_with_vector() overlays a single annotation file on its image and reports the feature count.

<Figure size 1600x800 with 2 Axes>
Number of buildings: 94

D. Method 1: single file for all images

The function loads the vector file once, spatially filters features for each image based on that image’s bounds, and, with skip_empty_tiles=True, only keeps tiles that actually contain a feature.

The swissBUILDINGS3D footprints have no class attribute, so class_value_field="class" finds nothing to read and the function falls back to binary masks (1 = building, 0 = background). For a multi-class dataset, point this parameter at the attribute column holding your class codes.

Loading...
Images processed: 3
Total tiles generated: 116
Tiles with features: 116

This method is efficient, but only if the shared annotation file really overlaps all images. If the feature count is unexpectedly low for some images, check whether the annotation extent is smaller than the image coverage.

E. Method 2: matched by sorted order

This pairs the first image in the folder with the first mask file, the second with the second, and so on, based purely on alphabetical order. It works here because willisau_2024_swissimage_tile-01.tif and willisau_2024_swissimage_tile-01.geojson both sort first, but that alignment is a property of the filenames, not something the function checks for you.

Before using sorted-order matching, print the implied pairs.

willisau_2024_swissimage_tile-01.tif → willisau_2024_swissimage_tile-01.geojson
willisau_2024_swissimage_tile-02.tif → willisau_2024_swissimage_tile-02.geojson
willisau_2024_swissimage_tile-03.tif → willisau_2024_swissimage_tile-03.geojson

Continue only if all pairs clearly belong together.

Loading...
Images processed: 3
Total tiles generated: 116
Tiles with features: 116

F. Method 3: matched by filename

When each image has its own annotation file sharing the same base name, match_by_name=True is the most reliable pairing option, since it does not depend on file ordering at all.

Loading...
Images processed: 3
Total tiles generated: 116
Tiles with features: 116

This is usually the safest pairing mode for project datasets because willisau_2024_swissimage_tile-01.tif is paired with willisau_2024_swissimage_tile-01.geojson, not merely with the first file in a sorted list.

G. Working with raster masks

Some projects already have labels as raster masks, for example land-cover classification maps. In that case, you can pass a folder of raster masks directly instead of vector files. The function pairs images and masks the same way, just without the vector-to-raster conversion step.

Loading...

This skips the vector-to-raster conversion step. The key check is still the same: each image tile must have a corresponding mask tile with the same spatial extent and grid alignment.

The output folder gets the same images/ and masks/ structure as before, just built from raster labels instead of vector ones.

H. Advanced usage

export_geotiff_tiles_batch() accepts the same fine-grained parameters you met on the vector-to-raster page and the tiling page, buffer radius, all-touched, tile size, and stride, plus a max_tiles limit that is useful for a quick test run before committing to a full batch.

Loading...
Generated 24 tiles with 50% overlap
ParameterWhat it changesWhen to use carefully
tile_sizeSize of each image chip.Match to model input size and feature size.
strideOverlap between neighbouring chips.Use more overlap when edge objects matter.
buffer_radiusExpands vector labels before rasterisation.Only when small spatial misalignments are expected and documented.
all_touched=TrueIncludes all pixels touched by a polygon.Can enlarge masks, especially for small or narrow features.
skip_empty_tiles=TrueRemoves chips without labelled features.Useful for rare objects, but may remove background examples.
max_tilesLimits the number of generated tiles.Useful for testing before a full batch run.

I. Check summary statistics

Every batch run returns a summary dictionary. Use it as a first quality signal before inspecting individual tiles.

Images processed: 3
Total tiles generated: 24
Tiles with features: 24
Feature percentage: 100.0%

Watch for suspicious results:

ResultPossible meaningFirst action
processed_pairs is lower than expectedSome images were not paired with labels.Check filenames, folder paths and pairing mode.
total_tiles is zeroNo valid tiles were generated.Check image paths, extents, tile size and output folder.
tiles_with_features is zeroLabels may not overlap images, or class field is wrong.Inspect bounds and overlay labels on imagery.
Feature percentage is unexpectedly highEmpty tiles may have been skipped, or labels may cover too much.Check skip_empty_tiles and inspect masks.
Feature percentage is unexpectedly lowAnnotations may be incomplete or misaligned.Preview image-label pairs and check annotation coverage.

J. Visualise generated tiles

Statistics are useful, but they are not enough. Always inspect image-mask pairs after a batch run.

<Figure size 1800x1000 with 8 Axes>

Check whether:

  • each image tile has a matching mask tile,

  • masks mark the correct visible features,

  • labels are not shifted,

  • edge objects are handled as expected,

  • empty or background-only tiles are not dominating the dataset,

  • the output folder structure is clear.

A batch workflow is only successful when the generated tiles are usable for training, not merely when the code finishes without errors.


4. Common pitfalls

  • Assuming sorted-order pairing is safe without checking the file lists first. Print both folders’ contents and compare them manually before trusting match_by_name=False.

  • Not checking the feature percentage after a batch run. A very low percentage often means the pairing, not the data itself, is the problem.

  • Mixing vector and raster masks in the same batch call without realizing it. Decide up front which mode your annotations are in, since the function behaves differently for each.


5. Mini task

If your project involves more than one image, list your image and annotation files and decide which of the three pairing methods fits your naming convention. If your project has only one image so far, describe which method you would use once you add a second one.


6. Key takeaways

  • export_geotiff_tiles_batch() extends single-image tiling to a whole folder, with three ways of pairing images to annotations.

  • Matching by filename is the most robust option whenever your file naming supports it; sorted-order matching depends on an assumption that is easy to get wrong silently.

  • The function also accepts pre-rasterized mask folders directly, skipping the vector-to-raster step.

  • Always check the returned summary statistics, especially the feature percentage, before moving on to visual inspection.