Skip to main content

Geospatial object detection using RF-DETR

Project description

detr-geo

CI Python 3.10+ License: MIT Open In Colab

detr-geo: vehicle detection on satellite imagery

Object detection for satellite and aerial imagery. Feed in a GeoTIFF, get back georeferenced vector data -- GeoJSON, GeoPackage, or Shapefile -- with full CRS, coordinates, and attribute tables ready for QGIS, ArcGIS, or PostGIS.

detr-geo wraps RF-DETR and adds everything a geospatial workflow needs: automatic tiling with cross-tile NMS deduplication, multispectral band mapping, 16-bit imagery normalization, nodata handling, and spatial-aware training dataset preparation. Includes a training pipeline for fine-tuning on your own data, with xView-trained vehicle detection weights available as an example.

Quick Start

from detr_geo import DetrGeo

dg = DetrGeo(model_size="medium")
dg.set_image("parking_lot.tif")
detections = dg.detect_tiled(overlap=0.2, threshold=0.3)
dg.to_gpkg("vehicles.gpkg")

print(f"{len(detections)} vehicles found")
print(detections[["class_name", "confidence", "geometry"]].head())

Inspired by samgeo, but for bounding-box detection rather than segmentation.


What detr-geo does that raw RF-DETR cannot

Capability RF-DETR alone detr-geo
Input Single PIL image, <= 704px GeoTIFF of any size, any CRS, 8/16-bit
Output Pixel bounding boxes Georeferenced polygons with CRS
Large imagery Fails or requires manual slicing Automatic tiling, overlap, cross-tile NMS
Multispectral RGB only Band presets for NAIP, Sentinel-2, WorldView
Nodata Not handled Skip empty tiles, fill partial tiles
Export NumPy arrays GeoJSON, GeoPackage, Shapefile
Training Generic COCO format Spatial splitting to prevent geospatial data leakage
Overhead imagery Trained on ground-level photos Fine-tuning pipeline + example xView vehicle weights

xView Fine-Tuned Model

The COCO-pretrained model was trained on ground-level photography. It has never seen a car from above, and it shows -- overhead vehicles get labeled as "motorcycle", "skateboard", or "boat".

The xView fine-tuned model fixes this. Trained on the xView dataset (satellite imagery at 0.3m GSD), it detects 5 overhead vehicle classes:

Class Examples
Car Sedans, SUVs, hatchbacks
Pickup Truck Pickup trucks, utility pickups
Truck Semi trucks, cargo trucks, tankers
Bus Transit buses, school buses, coaches
Other Vehicle Construction equipment, engineering vehicles
from detr_geo import DetrGeo

dg = DetrGeo(
    model_size="medium",
    pretrain_weights="checkpoints/checkpoint_best_ema.pth",
    custom_class_names={
        0: "Car",
        1: "Pickup Truck",
        2: "Truck",
        3: "Bus",
        4: "Other Vehicle",
    },
)

dg.set_image("satellite_scene.tif")
detections = dg.detect_tiled(overlap=0.2, threshold=0.3)

# Per-class counts
print(detections["class_name"].value_counts())

# Export for QGIS
dg.to_gpkg("vehicle_detections.gpkg")

Download the xView fine-tuned weights (optional):

huggingface-cli download gpriceless/detr-geo-xview \
    checkpoint_best_ema.pth --local-dir checkpoints/

Installation

Prerequisites

detr-geo requires GDAL and rasterio. On most systems:

# Ubuntu/Debian
sudo apt install gdal-bin libgdal-dev

# macOS (with Homebrew)
brew install gdal

# conda (recommended for geospatial Python)
conda install -c conda-forge rasterio geopandas

Install detr-geo

pip install detr-geo          # Core geospatial tools only (no model, no viz)
pip install detr-geo[rfdetr]  # With RF-DETR model + PyTorch
pip install detr-geo[viz]     # With leafmap + matplotlib visualization
pip install detr-geo[all]     # Everything

Core installs rasterio, geopandas, pyproj, shapely, and numpy. This is sufficient for processing pre-computed detection results without running inference.

[rfdetr] adds the RF-DETR model, PyTorch, and supervision. Downloads ~2 GB of model weights on first use.

[viz] adds leafmap (interactive maps) and matplotlib (static plots).

GPU Support

RF-DETR runs on CPU but is 10-50x faster on GPU:

# CUDA (NVIDIA)
pip install torch --index-url https://download.pytorch.org/whl/cu121
pip install detr-geo[all]

# MPS (Apple Silicon) -- PyTorch detects automatically
pip install detr-geo[all]

Core Workflow

1. Load imagery

dg = DetrGeo(model_size="medium")
dg.set_image("orthomosaic.tif")

detr-geo reads the CRS and affine transform from your raster automatically. It supports GeoTIFF, COG, and any rasterio-readable format.

2. Detect objects

For small images (fits in memory):

detections = dg.detect(threshold=0.4)

For large rasters (orthomosaics, satellite scenes):

detections = dg.detect_tiled(
    overlap=0.2,           # 20% overlap prevents boundary artifacts
    nms_threshold=0.5,     # deduplicate across tiles
    nodata_threshold=0.5,  # skip tiles that are >50% empty
)

3. Export georeferenced results

dg.to_gpkg("detections.gpkg")         # GeoPackage -- recommended
dg.to_geojson("detections.geojson")   # GeoJSON (auto-reprojects to WGS84)
dg.to_shp("detections.shp")           # Shapefile (legacy)

Or work with the GeoDataFrame directly:

gdf = dg.detections
cars = gdf[gdf["class_name"] == "Car"]
confident = gdf[gdf["confidence"] > 0.7]

4. Visualize

# Static matplotlib plot
dg.show_detections(figsize=(15, 12), save_path="output.png")

# Interactive leafmap (Jupyter)
m = dg.show_map(basemap="SATELLITE")

Band Selection

RF-DETR expects 3-channel RGB input. Different sensors store RGB in different bands. detr-geo maps them automatically:

dg.set_image("naip.tif", bands="rgb")               # Default: bands 1-2-3
dg.set_image("sentinel2.tif", bands="sentinel2_rgb") # Sentinel-2: bands 4-3-2
dg.set_image("worldview.tif", bands="worldview_rgb") # WorldView: bands 5-3-2
dg.set_image("custom.tif", bands=(4, 3, 2))          # Any 3-band combo (1-indexed)

Fine-Tuning on Custom Data

Train RF-DETR on your own overhead imagery. detr-geo handles the full pipeline from GeoTIFF + vector annotations to trained model:

from detr_geo import prepare_training_dataset, train, DetrGeo

# 1. Tile raster, align CRS, clip annotations, split spatially
prepare_training_dataset(
    raster_path="ortho.tif",
    annotations_path="labels.geojson",
    output_dir="training_data/",
    tile_size=576,
    split_method="block",       # spatial splitting prevents leakage
    split_ratios=(0.8, 0.15, 0.05),
)

# 2. Train with geospatial augmentations (rotation, flip -- no "up" in overhead)
dg = DetrGeo(model_size="medium")
train(
    adapter=dg._adapter,
    dataset_dir="training_data/",
    epochs=50,
    batch_size=8,
    augmentation_preset="satellite_default",
)

# 3. Run inference with your trained weights
dg = DetrGeo(
    model_size="medium",
    pretrain_weights="output/checkpoint_best_ema.pth",
    custom_class_names={0: "Building", 1: "Road", 2: "Tree"},
)

See the Fine-Tuning Guide for hardware requirements, monitoring, xView training details, and troubleshooting.


Model Sizes

Size Resolution Parameters Best For
nano 384px ~15M CPU inference, quick prototyping
small 512px ~22M Balanced speed and accuracy
medium 576px ~25M Default. Best accuracy/speed tradeoff
base 560px ~29M Higher accuracy, more VRAM
large 704px ~30M Maximum accuracy, GPU recommended

Real-World Use Cases

Parking lot occupancy -- Count vehicles across a commercial property from a single satellite capture. Export per-class counts (cars, trucks, buses) as a GeoJSON layer for the facilities team.

Construction site monitoring -- Detect heavy equipment in weekly drone surveys. Compare detections across dates to track mobilization and demobilization.

Fleet asset tracking -- Process satellite imagery of a logistics yard to locate trucks and trailers. Output GeoPackage layers with confidence scores for the dispatch team.

Urban planning -- Tile a city-wide orthomosaic and detect all vehicles. Aggregate detections by census tract for traffic density analysis.

Disaster response -- Rapidly scan post-event imagery for vehicles (potential rescue targets) in flood zones or collapsed structures.


Known Limitations

  • Memory: detect() loads the full raster. Use detect_tiled() for rasters larger than ~5000x5000 pixels.
  • Geographic CRS tiling: Tiles in EPSG:4326 vary in ground size by latitude. Use a projected CRS for best results.
  • Per-tile normalization: In tiled mode, each tile is normalized independently. For consistent 16-bit results, pre-compute stretch parameters with detr_geo.io.compute_scene_stretch_params.
  • Batch inference: Tiles are processed sequentially on GPU. True tensor batching is planned.

Output Formats

Format Method Notes
GeoJSON to_geojson() Auto-reprojects to WGS84 per spec
GeoPackage to_gpkg() Recommended. Preserves CRS, supports layers
Shapefile to_shp() Legacy. 10-char field names, 2 GB limit
GeoDataFrame .detections In-memory geopandas for further analysis

License

Code: MIT

xView fine-tuned weights: CC BY-NC-SA 4.0 (following the xView dataset license). COCO-pretrained weights are unrestricted.


Links

Acknowledgments

  • RF-DETR by Roboflow -- transformer-based object detection
  • xView by DIUx -- satellite annotations for fine-tuning
  • samgeo by Qiusheng Wu -- the geospatial ML workflow model

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

detr_geo-0.1.0.tar.gz (1.3 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

detr_geo-0.1.0-py3-none-any.whl (53.6 kB view details)

Uploaded Python 3

File details

Details for the file detr_geo-0.1.0.tar.gz.

File metadata

  • Download URL: detr_geo-0.1.0.tar.gz
  • Upload date:
  • Size: 1.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for detr_geo-0.1.0.tar.gz
Algorithm Hash digest
SHA256 92902e3047f31bdec3caf6d0a8a46b369df228d84e5653323650a1364dc8ba04
MD5 d7715da845b4ae279e58ec8cc36e3464
BLAKE2b-256 f6f4ddf127683ecd7a4ec164a4480c532052046db4cc0d8843496cb26ff04c73

See more details on using hashes here.

Provenance

The following attestation bundles were made for detr_geo-0.1.0.tar.gz:

Publisher: publish.yml on gpriceless/detr-geo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file detr_geo-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: detr_geo-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 53.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for detr_geo-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5e1945b343415f311c5a63f779fbff880bf2fa96752252be1ae8621939f6eb23
MD5 53ce16260b924d5608885524c2e954ed
BLAKE2b-256 6fc4e0e8b899fe82285c74130a84bed52230844a537bff98ebcbba7c3102e35b

See more details on using hashes here.

Provenance

The following attestation bundles were made for detr_geo-0.1.0-py3-none-any.whl:

Publisher: publish.yml on gpriceless/detr-geo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page