Skip to content

Task 1: Co-registration

For many applications, we may wish to compare the results of drone-based tree detection and classification against ground reference data. However, before we can do any comparison, we need to make sure the two datasets are spatially co-registered (aligned).

Required input data

Name Source Example file
Canopy height model Photogrammetry post-processing composite1_chm-mesh.tif
Ground reference trees (geospatial points) Manual fieldwork ofo-ground-reference-trees_0030.gpkg

Setup

Before you begin, make sure you have gone through the OFO tutorial preparation guidance. We recommend running OFO tools via their Docker images. Follow our Docker guide to understand what Docker is and ensure your system is set up to run Docker containers. If instead you plan to run the tools in a local Python environment, follow the local installation instructions to set up a Conda environment for the following tools:

Dataset co-registration using height correlation

Although both the drone imagery and reference tree locations are usually georeferenced with GPS/GNSS, each set of measurements can have an independent bias due to GPS/GNSS error (e.g., atmospheric distortions, signal attenuation by the tree canopy) at the time of survey. This creates a spatial offset, commonly on the order of several meters, between the two sets of data. An example of this phenomenon can be seen below, where the field reference trees (blue points) are shifted upward and slightly left relative to the corresponding drone trees represented by the CHM. The white line represents the bounds of of the ground plot, showing the region within which trees were surveyed.

initial registration

The OFO has developed the Tree Registration and Matching Toolkit (TRAM) to automatically identify the spatial registration between two datasets. The specific algorithm we will be using here registers a set of ground reference trees (geospatial points) to a drone-derived CHM (a geospatial raster). TRAM also contains algorithms to register two sets of geospatial points (e.g., ground reference trees and drone-detected trees).

The algorithm use will use to align the drone and reference data takes the CHM and ground reference tree locations (with a height attribute for each tree) as input. The algorithm extracts the height value from the CHM at each reference tree location, then computes the correlation between the reference tree heights and the CHM-derived heights. It then shifts the reference tree locations across a grid of offsets in both the x and y directions, and at each offset, re-computes the height correlation. The result is a grid of correlation values, where the maximum correlation indicates the optimal shift to align the two datasets.

The commands to run this algorithm are below.

Linux/Mac:

docker run --rm --user "$(id -u):$(id -g)" \
    -v "${DATA_DIR}:/data" \
    ghcr.io/open-forest-observatory/tree-registration-and-matching:latest \
    python -m tree_registration_and_matching.entrypoints.register_trees_to_CHM \
        --CHM-file /data/photogrammetry-postprocessed/full/composite1_chm-mesh.tif \
        --tree-points-file /data/ground-reference/ofo-ground-reference-trees_0030.gpkg \
        --output-shifted-trees /data/output/registration/ofo-ground-reference-trees_0030_shifted.gpkg \
        --output-shift-summary /data/output/registration/reference-drone-registration.csv

Windows:

docker run --rm `
    -v "${env:DATA_DIR}:/data" `
    ghcr.io/open-forest-observatory/tree-registration-and-matching:latest `
    python -m tree_registration_and_matching.entrypoints.register_trees_to_CHM `
        --CHM-file /data/photogrammetry-postprocessed/full/composite1_chm-mesh.tif `
        --tree-points-file /data/ground-reference/ofo-ground-reference-trees_0030.gpkg `
        --output-shifted-trees /data/output/registration/ofo-ground-reference-trees_0030_shifted.gpkg `
        --output-shift-summary /data/output/registration/reference-drone-registration.csv

In development. The TRAM registration example notebook shows a similar process. To directly use this notebook you would need to modify both cells 2 and 3. Ensure Jupyter is using the the tree-registration-and-matching Conda environment.

In your terminal, activate the tree-registration-and-matching Conda environment.

conda activate tree-registration-and-matching

Then run the trees-to-CHM registration entrypoint script.

python -m tree_registration_and_matching.entrypoints.register_trees_to_CHM \
    --CHM-file ${DATA_DIR}/photogrammetry-postprocessed/full/composite1_chm-mesh.tif \
    --tree-points-file ${DATA_DIR}/ground-reference/ofo-ground-reference-trees_0030.gpkg \
    --output-shifted-trees ${DATA_DIR}/output/registration/ofo-ground-reference-trees_0030_shifted.gpkg \
    --output-shift-summary ${DATA_DIR}/output/registration/reference-drone-registration.csv

Run the following code from within the tree-registration-and-matching Conda environment.

from pathlib import Path

from tree_registration_and_matching.entrypoints.register_trees_to_CHM import register_trees_to_CHM

# Change this line
DATA_DIR = Path("path/to/data")

# Define the inputs
CHM_FILE = Path(DATA_DIR, "photogrammetry-postprocessed", "full", "composite1_chm-mesh.tif")
TREE_POINTS_FILE = Path(DATA_DIR, "ground-reference", "ofo-ground-reference-trees_0030.gpkg")

# Define the outputs
OUTPUT_SHIFTED_TREES = Path(DATA_DIR, "output", "registration", "ofo-ground-reference-trees_0030_shifted.gpkg")
OUTPUT_SHIFT_SUMMARY = Path(DATA_DIR, "output", "registration", "reference-drone-registration.csv")

register_trees_to_CHM(
    tree_points_file=TREE_POINTS_FILE,
    CHM_file=CHM_FILE,
    output_shifted_trees=OUTPUT_SHIFTED_TREES,
    output_shift_summary=OUTPUT_SHIFT_SUMMARY,
)

This algorithm identifies the optimal shift and saves out a CSV file that describes the shift, including diagnostic metrics that can be used to interpret whether the result is likely to be correct.

estimated_shift_x estimated_shift_y shift_CRS optimal_correlation ratio_quality_metric n_shift_trees CHM_file average_error_frac
1.0 -4.2 EPSG:32610 0.6992 0.7261 31 composite1_chm-mesh.tif 0.1958

It also saves a shifted copy of the original reference trees as a geospatial point file that is otherwise identical to the original.

final registration

Now the surveyed tree tops match up much better with the drone CHM. While there are some errors, these errors are in different directions for every tree, so no single shift would improve all trees dramatically. Some small amount of tree-level error is always expected, due largely to human error during ground survey and the fact that ground surveyed tree locations (tree stems) are not always directly under the tree tops. In the next task, we will see that despite these errors, we can use a simple matching algorithm to identify the tree-to-tree correspondences between the two datasets.