detr-geo
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. Usedetect_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
- API Reference -- full method documentation
- Geospatial Guide -- tiling, CRS, bands, 16-bit, nodata
- Fine-Tuning Guide -- train on your own overhead imagery
- Examples -- runnable scripts for common workflows
- RF-DETR -- the underlying detection architecture
- xView Dataset -- satellite imagery used for fine-tuning
- samgeo -- the project that inspired this one
Acknowledgments
Metadata
Release files for detr-geo 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| detr_geo-0.1.0.tar.gz | 1.3 MB | With provenance | Details for detr_geo-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| detr_geo-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for detr_geo-0.1.0-py3-none-any.whl |
Total release size: 1.3 MB
Release files / detr_geo-0.1.0.tar.gz
| Download URL | detr_geo-0.1.0.tar.gz |
|---|---|
| Size | 1.3 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
92902e3047f31bdec3caf6d0a8a46b369df228d84e5653323650a1364dc8ba04
|
|
BLAKE2b-256 checksum How to use checksums |
f6f4ddf127683ecd7a4ec164a4480c532052046db4cc0d8843496cb26ff04c73
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 9, 2026.
Transparency logRelease files / detr_geo-0.1.0-py3-none-any.whl
| Download URL | detr_geo-0.1.0-py3-none-any.whl |
|---|---|
| Size | 53.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5e1945b343415f311c5a63f779fbff880bf2fa96752252be1ae8621939f6eb23
|
|
BLAKE2b-256 checksum How to use checksums |
6fc4e0e8b899fe82285c74130a84bed52230844a537bff98ebcbba7c3102e35b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 9, 2026.
Transparency logSecurity for detr-geo 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for detr_geo-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 9, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.