COLLEMBOT is a reproducible pipeline for counting Collembola organisms in ecotoxicity soil slide images. It includes YOLOv11-seg inference, training utilities for curated datasets, and comparative benchmarking for segmentation backbones. Release: v0.1.0.
This research project develops and validates an automated counting workflow for Folsomia candida in OECD 232 soil ecotoxicology tests, replacing manual counting with a reproducible deep-learning pipeline that improves throughput and reduces operator bias.
Wehrli, M., Meyer, A., da Silva, É. S., et al. (2026). COLLEMBOT: AI-based counting of Collembola for OECD 232 Tests. Environmental Toxicology and Chemistry. Publication DOI: 10.1093/etojnl/vgag068 (bioRxiv version)

Example detections of COLLEMBOT v0.1.0
configs/inference.yaml— inference configuration.train.yaml— single-run training configuration.train_multirun.yaml— multi-run training & model comparison configuration.
scripts/run_inference.py— tiling, YOLO inference, fusion, visualization, and metrics.train_model.py— dataset preparation + YOLO training and evaluation.compare_models.py— multi-model benchmarking (YOLO, Mask R-CNN, Mask2Former, MaskDINO).detectron_batching.py— VRAM-aware batch sizing for Detectron2.upscale_images.py— optional slide upscaling helper.gradio_app.py— Colab-ready Gradio helper.
data/— CC-BY-4.0 datasets and examples (seedata/README.md).notebooks/— Colab walkthroughs and launchers.
- Install Anaconda or Miniconda.
- Create and activate an environment:
conda create -n collembola python=3.10 conda activate collembola
- Install dependencies:
pip install -r requirements.txt
- Verify the GPU is visible to PyTorch:
python - <<'PY' import torch print('CUDA available:', torch.cuda.is_available()) PY
Inference images live in the folder referenced by images_folder in configs/inference.yaml. A typical layout is:
project_root/
├── configs/
│ └── inference.yaml
├── data/
│ ├── inference-examples/
│ ├── train-labelme-amsterdam/
│ ├── train-labelme-basel/
│ ├── train-labelme-bayreuth/
│ ├── train-labelme-cai_pyramids/
│ └── train-labelme-coimbra/
Tiles are automatically created at 576×576 pixels with an optional 288-pixel shift for overlap.
Key parameters for scripts/run_inference.py:
images_folder: data/inference-examples
experiments_dir: exps
model:
folder: model
archive: best.pt.7z
weights: best.pt
fuse: falseAdjust paths and parallelism to match local resources. The script extracts missing .pt weights from the archive automatically and records the originating image directory for reproducibility.
Model weights permalink: https://zenodo.org/records/17987887/files/collembot_yolo11xseg_v_0_1_0.pt?download=1
python scripts/run_inference.pyKey behaviors:
- Experiment folders — Each run creates
exps/exp_XXXX_<timestamp>/(or usesEXP_DIRif set) with subfolders for tiles, results, visualizations, logs, and stats. - Tiling & filtering — Slides are split into
oriandshiftgrids of 576×576 tiles. Bright or blueish tiles are skipped to reduce false positives; skip reasons are recorded alongside tile metadata. - YOLO inference — Multi-GPU, multi-processing inference loads one model per GPU, supports optional layer fusion, and can export tile-level LabelMe JSONs (
labelme/) with confidences preserved in theflagssection. - Polygon assembly — Tile detections are offset back to slide coordinates, cached in
raw_polygons.pkl, and enriched with tile bounding boxes and skip reasons to speed up re-runs. - Fusion & statistics — Graph-cut fusion merges overlapping polygons using the configured confidence/IoU/angle priors. The pipeline writes per-slide counts, precision, recall, F1, and R² against CSV annotations to
stats/pipeline_results.csvand a JSON summary. Annotated overlays are saved tofinal_viz/,final_viz_ori/, andfinal_viz_shift/.
scripts/train_model.py builds a YOLO dataset from one or more labeled sources and launches Ultralytics training:
- Config-driven: accepts a YAML file (default
configs/train.yaml) describing datasets, class names, image sizing, and hyperparameters. - Dataset handling: images/labels can live in separate directories per dataset; filenames are sanitised and deduplicated. Optional
tst_reserve.jsonfiles reserve specific images for testing. - Splitting: train/val/test splits are generated per dataset using the configured ratios, with logs detailing sample counts and any size mismatches between images and labels.
- Training: runs the Ultralytics CLI with the assembled
data.yaml, respecting multi-GPUdeviceentries and mixed-precision/augmentation settings. Checkpoints and metrics are stored undertrain_experiments/<timestamp>/. - Evaluation: after training, the script re-runs evaluation and summarises metrics alongside the split manifest for reproducibility.
Run training with:
python scripts/train_model.py --config configs/train.yamlTo re-evaluate an existing experiment without retraining:
python scripts/train_model.py --evalonly path/to/train_experiments/exp_xxxxconfigs/train_multirun.yaml defines lists of models, seeds, or datasets to sweep. Pass it to scripts/compare_models.py to launch multiple training runs and gather comparative metrics across checkpoints.
Use the toolkit in the following order for most projects:
- (Optional) Upscale slide imagery with
scripts/upscale_images.pyif the slides are too low-resolution for robust segmentation. - Prepare training data with LabelMe-style annotations, then run
scripts/train_model.pyto build YOLO datasets and train the segmentation model. - Benchmark models across YOLO/Detectron2 backbones with
scripts/compare_models.pyif you need a comparative study. - Run inference on new slides using
scripts/run_inference.py. - (Optional) Serve an interactive demo in Colab with
scripts/gradio_app.py.
The sections below document each script in detail, including inputs, outputs, and parameters.
Purpose: End-to-end inference (tiling → YOLO inference → polygon fusion → metrics + visualizations).
Invocation:
python scripts/run_inference.pyConfiguration: This script currently always reads configs/inference.yaml. If you need a different config file, edit configs/inference.yaml or change CONFIG_PATH inside the script.
Key inputs (from configs/inference.yaml):
images_folder: Folder with slide images to process.experiments_dir: Root for experiment outputs (e.g.,exps/).model.folder,model.weights: Folder and weights filename.model.archive: Optional7zarchive containing weights (auto-extracted if weights are missing).model.fuse: Fuse model layers for faster inference.tile.size/tile.shift: Tile size and overlap shift.parallel.n_gpus,parallel.n_jobs,parallel.batch_size: GPU and CPU parallelism.fusion.best_conf,fusion.best_iou,fusion.alpha: Graph-cut fusion parameters.skip_bright,skip_blue: Filters for tiles likely to be empty or overexposed.
Environment overrides:
EXP_DIR: If set, outputs are written into this directory instead of a newexps/exp_XXXX_...folder.
Outputs (under exps/exp_XXXX_<timestamp>/):
tiles/+results/: Raw tiling and per-tile YOLO outputs.labelme/: Optional tile-level LabelMe JSONs.final_viz/,final_viz_ori/,final_viz_shift/: Visual overlays.stats/pipeline_results.csv: Per-slide counts and metrics.stats/summary.json: Aggregated precision/recall/F1 (if annotations present).logs/pipeline.log: Run logs.
Notes:
- The script writes
source_folder.txtandtiles_source.txtto capture which image folders were used. - If
model.archiveis defined and themodel.weightsfile is missing, it is automatically extracted.
Purpose: Build a YOLO dataset from one or more annotated sources and launch Ultralytics training.
Invocation:
python scripts/train_model.py --config configs/train.yamlOptional evaluation-only mode:
python scripts/train_model.py --evalonly path/to/train_experiments/exp_train_YYYYMMDD-HHMMSSKey inputs (from configs/train.yaml):
datasets: List of{name, images, labels}entries (LabelMe JSONs per image).splits: Train/val/test ratios.image.target_size: Target tile size for YOLO.model.checkpoint: Base YOLO checkpoint (e.g.,yolo11x-seg.pt).model.device/training.device: GPU device list.training.*: Ultralytics training hyperparameters.
Outputs (under train_experiments/exp_train_YYYYMMDD-HHMMSS/):
dataset/: Prepared YOLO dataset (images/labels per split +data.yaml+manifest.csv).training/: Ultralytics training outputs (checkpoints, tensorboard logs, metrics).stats/: Post-training evaluation summaries.logs/train.log: Training logs.
Notes:
- If a dataset contains
tst_reserve.json, those images are reserved for testing. - The script sanitizes and deduplicates filenames across datasets to avoid collisions.
Purpose: Train/evaluate YOLOv11, Mask R-CNN, Mask2Former, and MaskDINO using the same prepared dataset.
Invocation:
python scripts/compare_models.py --config configs/train_multirun.yamlOptional overrides:
python scripts/compare_models.py --config configs/train_multirun.yaml --experiment-root train_experiments_customKey inputs (from configs/train_multirun.yaml):
models.*: Enable/disable each backbone viaactive: true/false.models.*.config_fileandmodels.*.weights_url: Detectron2/Mask2Former/MaskDINO configs and pretrained weights.optimizer,lr_scheduler,solver: Shared training settings.model_overrides: Per-backbone Detectron2 config overrides.
Outputs (under train_experiments/exp_train_YYYYMMDD-HHMMSS/):
dataset/: Copied YOLO dataset + COCO conversions for Detectron2.comparison/: Per-model metrics and summary tables.visualizations/: Sample overlays per dataset and model.logs/train.log: Comparison run logs.
Dependencies & setup notes:
- Requires Detectron2 and any local checkouts of Mask2Former/MaskDINO referenced in the config.
- If
config_filepoints inside a local repository, the script attempts to add the repo tosys.pathautomatically. - Batch sizes for Detectron2 models are sized using available GPU VRAM (see
scripts/detectron_batching.py).
Purpose: Utility functions to compute a safe Detectron2 batch size based on available GPU memory.
Usage (import in Python):
from scripts.detectron_batching import collect_gpu_vram, compute_vram_aware_batch_size
memories = collect_gpu_vram()
batch = compute_vram_aware_batch_size(memories, fallback_batch=4)
print("Batch size:", batch)This module is intended to be imported (not executed directly). It is used by scripts/compare_models.py.
Purpose: Upscale JPG slide images using Real-ESRGAN x2 across multiple GPUs.
Invocation:
python scripts/upscale_images.py --input_dir data/inference-examples --output_dir data/inference-examples-upscaledKey arguments:
--input_dir: Directory with.jpg/.jpegimages (recursive by default).--output_dir: Output directory with mirrored structure.--weights: Path toRealESRGAN_x2plus.pth(auto-download if omitted).--gpus: Comma-separated GPU ids (default: all visible).--tile: Tile size (use 512/1024 if you hit CUDA OOM).--tile_pad,--pre_pad: Tiling settings to avoid seams.--fp16: Enable FP16 inference (recommended on some GPUs).--jpg_quality: Output JPEG quality (0–100).--overwrite: Overwrite existing outputs.--no_recursive: Disable recursive input scanning.--warmup: Run a short warmup pass on each GPU.
Outputs: Upscaled images written to output_dir with the same relative paths as the input images.
License note: This script uses Real-ESRGAN components from https://github.com/xinntao/Real-ESRGAN/, which are licensed under BSD-3-Clause. The upstream weights are downloaded from the Real-ESRGAN releases page.
Purpose: Launch a lightweight Gradio UI for interactive inference in Colab or notebooks.
Usage (in Python/Colab):
from scripts.gradio_app import launch_app
launch_app(
model_path="model/best.pt",
fuse=False,
example_image="data/inference-examples/sample.jpg",
)Key parameters:
model_path: Path to YOLO weights (.pt).fuse: Whether to fuse model layers.preferred_device:"auto","cpu", or a CUDA device id string (e.g.,"0").predict_batch_size: Tile batch size.use_half: Force FP16/FP32 inference.
Outputs: The app returns an annotated image plus a JSON summary (fused counts + detection polygons).
The published model weights are AGPL-3.0 only and can be obtained from Zenodo: https://doi.org/10.5281/zenodo.17987886
Direct Link to the weights file: https://zenodo.org/records/17987887/files/collembot_yolo11xseg_v_0_1_0.pt?download=1
This project depends on YOLOv11 by Ultralytics, which is licensed under AGPL-3.0. The dependency is not bundled with this repository.
- Code: AGPL-3.0 only (see
LICENSE). - Data: CC-BY-4.0 (see
data/README.md). - Model weights: AGPL-3.0 only (see Zenodo DOI above).
- Real-ESRGAN elements (used by
scripts/upscale_images.py): BSD-3-Clause (see https://github.com/xinntao/Real-ESRGAN/).
Author attribution is required for academic or derivative use (see CITATION.md):
Wehrli & Meyer & Souza da Silva et al.; 2026; COLLEMBOT: AI-based counting of Collembola for OECD 232 tests (in preparation)
Authors (* shared first authors): Micha Wehrli*, Adrian Meyer*, Éverton Souza da Silva*, Sam van Loon, Bart G. van Hall, Cornelis A. M. van Gestel, Tiago Natal-da-Luz, Max V. R. Döring, Heike Feldhaar, Magdalena Mair, Denis Jordan, Miriam Langer
Affiliations: Eawag (CH) · FHNW (CH) · University of Zurich (CH) · University of Bayreuth (DE) · Vrije Universiteit Amsterdam (NL) · Cloverstrategy Lda (PT)
Adrian Meyer — adrian.meyer@fhnw.ch