TOFMapper is an semantic segmentation tool for mapping and classifying Trees outside Forest in high resolution aerial images.
- Segmentation and classification of aerial imagery into four trees outside forest classes (Forest, Patch, Linear, Tree)
- Can handle large inference images by slicing and stitching patches and neighboring images preventing edge effects
Prepare the following folders to organize this repo:
Project
├── TOFMapper (code)
├── pretrain_weights (pretrained weights of backbones, such as vit, swin, etc)
├── model_weights (save the model weights trained on your and our TOF data)
├── fig_results (save the masks predicted by models)
├── lightning_logs (CSV format training logs)
├── data
│ ├── tof
│ │ ├── train_images (original)
│ │ ├── train_masks (original)
│ │ ├── val_images (original)
│ │ ├── val_masks (original)
│ │ ├── test_images (original)
│ │ ├── test_masks (original)
│ │ ├── test_masks_eroded (original)
│ │ ├── train (processed)
│ │ ├── val (processed)
│ │ ├── test (processed)
│ ├── sites
│ │ ├── site name
│ │ | ├── TOP (True Orthophoto) Name: TOP_id.tif
│ │ | ├── SHP (Reference Shapefile) Name: site_name_TOF.shp
Open the folder Project using Linux Terminal and create python environment:
conda create -n TOFMapper python=3.8
conda activate TOFMapper
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
pip install -r TOFMapper/requirements.txt
| Model | mIoU | mF1 | Forest IoU | Forest F1 | Patch IoU | Patch F1 | Linear IoU | Linear F1 | Tree IoU | Tree F1 |
|---|---|---|---|---|---|---|---|---|---|---|
| ABCNet | 0.709 | 0.821 | 0.971 | 0.944 | 0.532 | 0.695 | 0.739 | 0.850 | 0.622 | 0.767 |
| BANet | 0.656 | 0.777 | 0.937 | 0.967 | 0.422 | 0.593 | 0.689 | 0.816 | 0.575 | 0.730 |
| DC-Swin | 0.714 | 0.824 | 0.949 | 0.974 | 0.570 | 0.726 | 0.751 | 0.858 | 0.586 | 0.727 |
| FT-UNetFormer | 0.739 | 0.843 | 0.952 | 0.975 | 0.606 | 0.754 | 0.774 | 0.872 | 0.626 | 0.770 |
| LSKNet | 0.697 | 0.812 | 0.943 | 0.971 | 0.545 | 0.705 | 0.718 | 0.836 | 0.582 | 0.736 |
| U-Net | 0.484 | 0.618 | 0.804 | 0.891 | 0.151 | 0.263 | 0.527 | 0.690 | 0.456 | 0.626 |
Get access to the dataset created for model training here.
Create your own reference data using this repository. Be aware that manual refinement will be required!
Create images (masks) in the same size as orthophotos from shapefiles.
python TOFMapper/tools/create_masks.py --state "site name" --epsg "EPSG:25833"
Define the training, validation and test split (here 90, 5, 5). This will split the data so that all classes are equally distributed. It is set up for 100 files.
python TOFMapper/tools/data_statistics.py --state "site name"
Copy the files into the designated training, validation and testing folders.
python copy_files.py --sites SITE_A SITE_B \
--dest_train_images "custom/train_images" \
--dest_train_masks "custom/train_masks" \
--dest_val_images "custom/val_images" \
--dest_val_masks "custom/val_masks" \
--dest_test_images "custom/test_images" \
--dest_test_masks "custom/test_masks"
Generate the training set.
python TOFMapper/tools/tof_patch_split.py \
--img-dir "data/tof/train_images" \
--mask-dir "data/tof/train_masks" \
--output-img-dir "data/tof/train/images_1024" \
--output-mask-dir "data/tof/train/masks_1024"\
--mode "train" --split-size 1024 --stride 1024 \
Generate the validation set.
python TOFMapper/tools/tof_patch_split.py \
--img-dir "data/tof/val_images" \
--mask-dir "data/tof/val_masks" \
--output-img-dir "data/tof/val/images_1024" \
--output-mask-dir "data/tof/val/masks_1024"\
--mode "val" --split-size 1024 --stride 1024 \
Generate the testing set.
python TOFMapper/tools/tof_patch_split.py \
--img-dir "data/tof/test_images" \
--mask-dir "data/tof/test_masks" \
--output-img-dir "data/tof/test/images" \
--output-mask-dir "data/tof/test/masks" \
--mode "val" --split-size 1024 --stride 1024 \
"-c" path of the config, use different config to train different models.
python TOFMapper/train_supervision.py -c TOFMapper/config/tof/ftunetformer.py
Testing is made to work on larger images without pre-cutting. A sliding window extracts overlapping patches to generate softmax predictions, which are then merged by averaging and majority voting. This approach improves boundary segmentation.
"-c" denotes the path of the config, Use different config to test different models.
"-o" denotes the output path
python TOFMapper/tof_test.py -c TOFMapper/config/tof/unetformer.py -o fig_results/tof/unetformer --rgb
This function is particularly suitable to tackle edge problems and operate over vast geographic extents. This script performs inference on a folder of georeferenced images using a sliding window approach with adjustable patch size (-ps) and stride (-st). It keeps only the inner part of every patch (-kr) to reduce boundary effects, averaging overlapping softmax scores to generate robust predictions. The script also combines neighboring images for added context and preserves the original geospatial metadata. Predictions are output as a GeoTIF and then converted to a shapefile.
"i" denotes the input image folder
"-c" denotes the path of the config, Use different config to test different models.
"-o" denotes the output path
"-st" stride for the sliding window (in pixels).
"-ps" Patch size for inference
"-b" Batch size
"-m" Margin size for neighboring images.
"-kr" Ratio of patch to keep during inference.
python TOFMapper/inference_with_overlap.py \
-i path/to/images \
-c TOFMapper/config/tof/ftunetformer.py \
-o path/to/output \
-st 256 \
-ps 1024 \
-b 2 \
-m 500 \
-kr 0.7
@article{lucas2025mapping,
title={Mapping and Classification of Trees Outside Forests using Deep Learning},
author={Lucas, Moritz and Ebrahimy, Hamid and Barkov, Viacheslav and Pecenka, Ralf and K{\"u}hnberger, Kai-Uwe and Waske, Bj{\"o}rn},
journal={arXiv preprint arXiv:2510.25239},
year={2025},
doi={10.48550/arXiv.2510.25239}
}Many thanks to Libo Wang for creating GeoSeg, which served as the foundation for this project.