DEV Community

Cover image for From Drone Video to 3D Maps: Automate WebODM Setup with GPU Acceleration
Prashant Piprotar
Prashant Piprotar

Posted on

From Drone Video to 3D Maps: Automate WebODM Setup with GPU Acceleration

The Problem: Drone Mapping Shouldn't Be This Hard

You've got a drone. You've captured stunning aerial footage. Now you want to turn those videos into orthophoto maps, 3D models, or point clouds — and you hit a wall.

Setting up WebODM (the open-source drone mapping platform built on OpenDroneMap) involves juggling Docker Compose files, configuring processing nodes, extracting frames from video, and — if you want any reasonable speed — wiring up GPU acceleration. Each step has its own pitfalls across Windows, Linux, and macOS (including Apple Silicon).

I built WebODM-Setup to solve this. One repo. One command. Full pipeline from raw drone video to finished map.


What This Repo Does

At its core, the toolkit automates the entire drone-mapping workflow:

Capture Video → Extract Frames → Upload to WebODM → Process → Export
Enter fullscreen mode Exit fullscreen mode

Here's what's inside:

  • One-command install scripts for Windows (PowerShell), Linux (Bash), and macOS (including native Apple Silicon support)
  • Docker Compose configs that wire up the full WebODM stack — webapp, worker, NodeODM processing node, PostGIS database, and Redis broker
  • GPU acceleration out of the box (NVIDIA GPUs via the nodeodm:gpu Docker image)
  • Video processing scripts — extract frames at configurable FPS with GPS metadata preservation
  • Batch processing for multi-video workflows

Quick Start (Under 5 Minutes)

Prerequisites

  • Docker Desktop (Windows/macOS) or Docker Engine (Linux)
  • Python 3.8+
  • Git

Linux / macOS

git clone https://github.com/prashplus/WebODM-Setup.git
cd WebODM-Setup
chmod +x scripts/*.sh
./scripts/install-linux.sh
./scripts/start-webodm.sh
Enter fullscreen mode Exit fullscreen mode

Windows (PowerShell)

git clone https://github.com/prashplus/WebODM-Setup.git
cd WebODM-Setup
.\scripts\install-windows.ps1
.\scripts\start-webodm.ps1
Enter fullscreen mode Exit fullscreen mode

Open http://localhost:8000 — done.

Apple Silicon users: The scripts auto-detect M1/M2/M3/M4 and use the correct arm64-native, CPU-only Docker images. No extra config needed.


The Architecture

The docker-compose.yml spins up five services:

Service Image Role
webapp opendronemap/webodm_webapp Web UI + API (port 8000)
worker opendronemap/webodm_webapp Celery task worker
node-odm-1 opendronemap/nodeodm:gpu Photogrammetry engine (port 3000)
db postgis/postgis:14-3.3 PostGIS database
broker redis:7 Task queue

A node-register init container auto-registers the processing node with the webapp on first boot — no manual setup.


GPU Acceleration: The Speed Multiplier

This is where things get exciting. By default, the compose file uses the nodeodm:gpu image with NVIDIA GPU reservation:

node-odm-1:
  image: opendronemap/nodeodm:gpu
  environment:
    - GPU_ENABLED=true
  deploy:
    resources:
      reservations:
        devices:
          - driver: nvidia
            count: 1
            capabilities: [gpu]
Enter fullscreen mode Exit fullscreen mode

Real-World Performance (200 images, 20MP)

Configuration Processing Time
CPU only (8 cores) ~2–4 hours
GPU (RTX 4060, 8GB VRAM) ~30–60 minutes

That's a 2–5x speedup across the photogrammetry pipeline — Structure from Motion, Multi-View Stereo, meshing, and texturing all benefit.

Requirements

  • NVIDIA GPU with CUDA 11.0+ and 4GB+ VRAM
  • NVIDIA Container Toolkit installed
  • On Windows: WSL2 backend with GPU passthrough enabled

If you don't have an NVIDIA GPU, just swap the image to opendronemap/nodeodm:latest and remove the deploy section — everything works on CPU.


From Video to Map: The Processing Pipeline

Most consumer drones record video, not individual photos. The repo includes Python scripts to bridge that gap.

Extract Frames

# 1 frame per second, JPEG quality 95
python scripts/extract-frames.py \
  --input DJI_0001.MP4 \
  --output ./frames/project1 \
  --fps 1 \
  --quality 95

# With GPS metadata extraction
python scripts/extract-frames.py \
  --input DJI_0001.MP4 \
  --output ./frames/project1 \
  --fps 2 \
  --extract-gps
Enter fullscreen mode Exit fullscreen mode

Batch Process Multiple Videos

python scripts/batch-process.py \
  --input-dir ./videos \
  --output-dir ./frames \
  --fps 1
Enter fullscreen mode Exit fullscreen mode

Choosing the Right FPS

Flight Speed Recommended FPS ~Frames per 5-min Video
Slow (2–3 m/s) 0.5–1 150–300
Normal (4–5 m/s) 1–2 300–600
Fast (6+ m/s) 2–3 600–900

The key is overlap — consecutive frames need 70–80% overlap for the photogrammetry algorithms to work.


Processing Presets

Once frames are uploaded to WebODM, choose a preset based on your needs:

Preset Time (200 imgs, 8C/16GB) Use Case
Fast ~15 min Quick previews, data validation
Default ~1.5 hours Most projects
High Quality ~4 hours Professional deliverables, detailed 3D
Ultra 8+ hours Maximum detail, heritage documentation

Output Formats

  • Orthophoto (GeoTIFF) — georeferenced 2D map
  • 3D Model (OBJ/PLY) — textured mesh
  • Point Cloud (PLY/LAS) — colored XYZ data
  • DEM (GeoTIFF) — elevation/terrain model
  • Contours (GeoJSON) — elevation contour lines

Real-World Use Cases

The workflow documentation covers four common scenarios:

  1. Agriculture Mapping — Grid pattern at 100m, orthophoto export for NDVI analysis
  2. Construction Site Surveys — DEM + orthophoto for volume calculations
  3. Building/Monument 3D Models — Circular flight pattern, high-quality 3D mesh export
  4. Infrastructure Inspection — Multi-angle capture, detailed textured model

Project Structure

WebODM-Setup/
├── scripts/
│   ├── install-windows.ps1 / install-linux.sh
│   ├── start-webodm.ps1 / start-webodm.sh
│   ├── stop-webodm.ps1 / stop-webodm.sh
│   ├── update-webodm.ps1 / update-webodm.sh
│   ├── extract-frames.py
│   ├── batch-process.py
│   └── common.sh
├── config/
│   ├── webodm-config.env
│   └── processing-presets.json
├── docker-compose.yml                # GPU-enabled (Linux/Windows)
├── docker-compose.apple-silicon.yml  # Apple Silicon (arm64, CPU-only)
├── requirements.txt
├── GPU_SETUP.md
├── MACOS_APPLE_SILICON.md
├── WORKFLOW.md
└── README.md
Enter fullscreen mode Exit fullscreen mode

Tips & Gotchas

  • Docker memory: Bump to 8GB+ in Docker Desktop settings. Processing large datasets with the default 2GB will crash.
  • Port conflicts: If port 8000 is taken, edit config/webodm-config.env and set WO_PORT=8080.
  • GPU monitoring: Run watch -n 2 nvidia-smi (Linux) or a looping nvidia-smi (Windows PowerShell) to monitor utilization during processing.
  • FFmpeg: Required for the frame extraction scripts. Install via brew install ffmpeg, apt install ffmpeg, or choco install ffmpeg.
  • Image quality matters: Blurry, overexposed, or sky-only frames will degrade results. Curate your frame set before uploading.

Contributing

The project is MIT-licensed and welcomes contributions. Fork, branch, PR — the standard flow:

git checkout -b feature/your-feature
git commit -m "Add your feature"
git push origin feature/your-feature
Enter fullscreen mode Exit fullscreen mode

Links


If this saves you time, drop a ⭐ on the repo — it helps others find it. Questions or issues? Open a GitHub issue or reach out in the comments below.

Happy mapping! 🗺️

Top comments (0)