Running with Docker¶
Every command in this section can be run from the pre-built Docker image (ghcr.io/open-forest-observatory/tree-detection-framework:latest) instead of a local
installation. This avoids installing Poetry, conda, Detectron2, SAM2, and SAM3 on your own machine,
and it is the quickest way to run a detector on a new system. It does require having Docker installed on your machine, which is assumed to be already completed.
The general form¶
The image sets WORKDIR /app and PYTHONPATH=/app, with the TDF source at
/app/tree_detection_framework. So the python -m ... commands documented on the other pages in
this section work unchanged — you just prefix them with docker run and append them to the image
name:
docker run --rm --gpus all \
-v /path/on/your/machine:/data \
ghcr.io/open-forest-observatory/tree-detection-framework:latest \
python -m tree_detection_framework.entrypoints.<script_name> [arguments]
Anything after the image name replaces the image's default command, so any entrypoint can be selected this way.
What each Docker flag does¶
| Flag | Required | What it does |
|---|---|---|
--rm |
no | Delete the container when the command finishes. Without it, every run leaves a stopped container behind. |
--gpus all |
no | Make the host's NVIDIA GPUs visible inside the container. Requires the NVIDIA Container Toolkit on the host. Omit it to run on CPU, which works but is much slower for the deep learning detectors. |
-v HOST:CONTAINER |
yes | Mount a host directory into the container. Without at least one of these, the container cannot see your data and anything it writes disappears when it exits. |
--user $(id -u):$(id -g) |
no | Run as your own user so output files are owned by you. See File ownership below. |
Getting data in and results out¶
The container has its own filesystem. Your orthomosaics are not in it, and files it writes are gone when it exits unless they land in a mounted directory.
The simplest approach is one mount for everything, using paths inside the container in the TDF arguments:
docker run --rm --gpus all \
-v "$PWD/data:/data" \
ghcr.io/open-forest-observatory/tree-detection-framework:latest \
python -m tree_detection_framework.entrypoints.generate_predictions \
--raster-folder-path /data/emerald-point-ortho \
--chip-size 1024 \
--chip-stride 768 \
--resolution 0.05 \
--tree-detection-model deepforest \
--run-nms \
--predictions-save-path /data/detections.gpkg
Note that --raster-folder-path and --predictions-save-path are /data/..., the paths inside
the container, not the host paths. This is the most common mistake: passing a host path that does
not exist in the container gives a confusing "file not found" for a file you can plainly see.
To keep inputs safe, mount them read-only and give outputs their own writable mount:
docker run --rm --gpus all \
-v "$PWD/data:/data:ro" \
-v "$PWD/outputs:/outputs" \
ghcr.io/open-forest-observatory/tree-detection-framework:latest \
python -m tree_detection_framework.entrypoints.generate_predictions \
--raster-folder-path /data/emerald-point-ortho \
--chip-size 1024 \
--tree-detection-model deepforest \
--predictions-save-path /outputs/detections.gpkg
File ownership¶
By default the container runs as root, so files it writes into a mounted directory are owned by
root on the host and you may not be able to delete or edit them without sudo. Passing your own
user and group ID avoids this:
Model weights¶
The image bundles the dependencies for every supported detector. Weights for most of them are
already baked in at /app/checkpoints, which is exactly where TDF's default checkpoint paths look,
so nothing extra is needed:
| Detector | Bundled in the image? | Notes |
|---|---|---|
deepforest |
downloaded on first use | The DeepForest package fetches its own weights from GitHub the first time it runs, so the container needs network access. They are re-downloaded on every fresh container unless you mount a cache. |
detectree2 |
yes | /app/checkpoints/230103_randresize_full.pth |
sam2 |
yes | /app/checkpoints/sam2.1_hiera_large.pt |
tcd |
yes | Cached in the image's HuggingFace cache. |
geometric |
not applicable | Learning-free; no weights at all. |
sam3 |
no | Must be supplied at runtime. See below. |
SAM3 weights are gated behind a HuggingFace access request and so are not included. Either mount a checkpoint you already have:
docker run --rm --gpus all \
-v "$PWD/data:/data" -v "$PWD/checkpoints:/checkpoints" \
ghcr.io/open-forest-observatory/tree-detection-framework:latest \
python -m tree_detection_framework.entrypoints.generate_predictions \
--raster-folder-path /data/ortho.tif --chip-size 2000 \
--tree-detection-model sam3 \
--sam3-checkpoint-path /checkpoints/sam3.pt \
--predictions-save-path /data/sam3_detections.gpkg
or let it download them, passing a token via an environment variable so the token does not appear in
your shell history or in docker ps output:
docker run --rm --gpus all -e HF_TOKEN \
-v "$PWD/data:/data" \
ghcr.io/open-forest-observatory/tree-detection-framework:latest \
python -m tree_detection_framework.entrypoints.generate_predictions \
--raster-folder-path /data/ortho.tif --chip-size 2000 \
--tree-detection-model sam3 \
--sam3-huggingface-token "$HF_TOKEN" \
--predictions-save-path /data/sam3_detections.gpkg
With -e HF_TOKEN (no value), Docker passes through the variable of that name from your shell.
More examples¶
Geometric detection from a canopy height model, which needs no GPU:
docker run --rm -v "$PWD/data:/data" \
ghcr.io/open-forest-observatory/tree-detection-framework:latest \
python -m tree_detection_framework.entrypoints.detect_geometric_two_stage \
/data/emerald-point-chm/chm.tif \
/data/tree_tops.gpkg \
--tree-crowns-save-path /data/tree_crowns.gpkg \
--resolution 0.2 \
--raster-blur-sigma 0.5
Export tiles to inspect how a raster will be chipped:
docker run --rm -v "$PWD/data:/data" \
ghcr.io/open-forest-observatory/tree-detection-framework:latest \
python -m tree_detection_framework.entrypoints.tile_data \
--raster-folder-path /data/emerald-point-ortho \
--chip-size 1024 --chip-stride 768 --resolution 0.05 \
--save-folder /data/tiles --save-n-tiles 20 --random-sample
Read a script's own help text:
docker run --rm ghcr.io/open-forest-observatory/tree-detection-framework:latest \
python -m tree_detection_framework.entrypoints.generate_predictions --help
Open a shell in the container to poke around:
docker run --rm -it -v "$PWD/data:/data" \
ghcr.io/open-forest-observatory/tree-detection-framework:latest bash
Things that do not work in a container¶
- Anything that opens a plot window.
--view-predictions-plotongenerate_predictionsand--visualize-n-tilesontile_databoth need a display the container does not have. Write results to a file and view them on the host instead, or usevisualize_detections, which saves PNGs rather than opening a window. - Host paths in TDF arguments. Every path you pass to a TDF script must be a path inside the
container, matching the right-hand side of a
-vmount.
The default command¶
The image declares a default command:
Running the image with no arguments therefore invokes generate_predictions with no arguments,
which exits with an error about missing required arguments. This is expected — always append the
command you actually want, as shown above.