Productos de dron en Linux - OpenDroneMap - Tutorial avanzado
Contenido:- Video tutoriales
- Cómo instalar y usar OpenDroneMap
- Cómo ordenar y funcionar
- Los extras
- Conclusiones
- Segundas conclusiones
En este post volveremos a revisar de forma actualizada y más profesional la instalación, configuración y ejecución del programa Open Drone Map. Este programa, ejecutable totalmente desde terminal permite transformar cualquier secuencia ordenada de fotos y vídeos en un mesh (objeto 3D) o en una ortofoto.
Video tutoriales
Parte I - OpenDroneMap - Instalación, configuración y parámetros clave
Parte II - OpenDroneMap - Análisis de resultados en QGIS y Blender
Cómo instalar y usar OpenDroneMap
Este tutorial avanzado parte de la base de que ya sabéis manejar Docker, Linux y os sentís cómodos con la terminal
. Todo aquí se ha desarrollado y pensado desde Ubuntu 24.04, aunque confío que esta misma instalación y configuración será válidad en cualquier otra distribución de Linux.
Si no tienes Ubuntu 24.04 pero te gustaría tenerlo, te recomiendo pasarte por este post donde te explico cómo tener todo lo básico para funcionar como un pro.
Lo primero es tener instalado docker. Para ello, simplemente en terminal tenéis que instalar lo siguiente.
sudo apt update && sudo apt upgrade -y
sudo apt install -y ca-certificates curl gnupg lsb-release
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo groupadd -f docker
sudo usermod -aG docker $USER
sudo systemctl enable docker
# test
docker run hello-world
Una vez que tenéis Docker operativo podéis pasar a la instalación ya de OpenDroneMap. Supongo que habrá forma más linuxeras de instalarlo, con su compilación a partir de los binarios y todo ese rollo. Yo no me complico para este caso y lo que hago es instalarlo con snap
.
#---OpenDroneMap---#
sudo snap install --edge opendronemap
Esta instalación es la mar de fácil, pero aquí viene la complicación (ya resuelta): que funcione correctamente con CUDA. En mi caso, tengo dos RTX y lo que he tenido que hacer a fecha del 7/4/2025 es esto:
# Configuración para usar gpu
#SEE THIS LINK: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html #docker
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
# test
sudo docker run --rm --runtime=nvidia --gpus all nvidia/cuda:11.6.2-base-ubuntu20.04 nvidia-smi
Después de ese último test deberíais ver algo así:
Aunque la versión de cuda instalada en el pc sea una, la versión que funcionará en docker podría ser una menos actual. Para configurar docker con esta habría que ejecutar lo siguiente:
docker run -it --rm --gpus all nvidia/cuda:12.2.0-base-ubuntu22.04 nvidia-smi
Cómo ordenar y funcionar
Estructura de proyectos
Ejecutar ODM es muy fácil si tienes clara la estructura de carpetas que debes construir para tu proyecto. No tiene nada de misterio, pero idealmente, debes tener un directorio para las salidas del programa. Por ejemplo tendrás estos niveles:
- Carpeta de proyectos:
ODM
- Carpeta de proyecto:
ODM_test
- Carpeta de trabajo:
code
- Carpeta de imágenes:
images
- Carpeta de imágenes:
- Carpeta de trabajo:
- Carpeta de proyecto:
Preparación de imágenes
El programa está diseñado para crear las ortofotos y los modelos a partir de fotos. Sin embargo, está escrito internamente para que se le puedan dar directamente vídeos. El proceso partirá en caso de darle una carpeta con vídeos de la extracción previa de los fotogramas representativos para la construcción de los objetos deseados. No obstante, este paso de extracción de fotogramas clave de los vídeos se puede hacer también previamente y fuera de la herramienta, en este caso con las herramientas de ffmpeg. De esta forma, la extracción es muy más customizable. Esto permitiría extraer un número concreto de fotogramas y seleccionar solo aquellos que de verdad son buenos para el proceso. Si los archivos son de vídeo hay que convertirlos previamente en imágenes:
# Directorio donde están los videos
VIDEO_DIR="./"
# Crear carpeta frames en el mismo nivel que los videos si no existe
FRAMES_DIR="${VIDEO_DIR}/frames"
mkdir -p "$FRAMES_DIR"
# Procesar cada video en el directorio
for video in "$VIDEO_DIR"/*.MP4; do
# Obtener el nombre base del video sin extensión
base_name=$(basename "$video" .MP4)
# Crear una subcarpeta para los fotogramas de este video
video_frames_dir="$FRAMES_DIR/$base_name"
mkdir -p "$video_frames_dir"
# Extraer solo los I-frames (fotogramas clave) y aplicar filtro de nitidez
ffmpeg -i "$video" -vsync vfr -q:v 2 -vf "select='eq(pict_type,I)',unsharp=5:5:0.8:3:3:0.5" \
"$video_frames_dir/${base_name}_%04d.jpg"
echo "Fotogramas clave extraídos de $video en $video_frames_dir"
done
echo "Proceso completado."
En los vídeos que acompañan este post podréis ver los detalles de la selección y limpieza de imágenes. No obstante, aquí tenéis un pequeño extracto de las imágenes para que comprobéis que la clave es que entre ellas haya siempre cierto nivel de superposición.
Los parámetros de ODM
DEBES SABER IR A LAS FUENTES. TODOS LOS ARGUMENTOS ESTÁN AQUÍ
sudo chown -R $(id -u):$(id -g) /home/$USER/ODM/odm_test6
sudo docker run -ti --rm \
--gpus all \
-u $(id -u):$(id -g) \
-v /home/$USER/ODM/odm_test6:/OPENDRONEMAP/odm_test6 \
-w /OPENDRONEMAP/odm_test6 \
opendronemap/odm:gpu \
--project-path /OPENDRONEMAP/odm_test6/ \
--orthophoto-resolution 1 \
--matcher-type bruteforce \
--max-concurrency 16 \
--pc-rectify \
--pc-sample 0.5 \
--matcher-neighbors 5 \
--min-num-features 25000 \
--feature-quality high\
--feature-type sift \
--pc-quality ultra \
--build-overviews \
--auto-boundary \
--skip-3dmodel \
--sfm-algorithm planar \
--rerun-from odm_filterpoints \
--fast-orthophoto
Algunos apuntes al proceso:
-
Cuando ejecutas un contendor como root, todo lo que se crea en los volúmenes aparecerá con permisos de root en el host. Para evitarlo, hay que indicarle a docker que use tu propio usuario. Una forma simple es agregar esta línea al proceso
-u $(id -u):$(id -g) \
. Si lanzas el proceso sin esta línea verás que todas las carpetas se crearán con el típico símbolo del candado de Linux (por lo que requerirás permisos de supeusuario también para eliminar los archivos de forma rápida). -
Dentro del contenedor, los siguientes parámetros son de ODM:
- –project-path /OPENDRONEMAP/odm_test/: Define dónde se guardarán los resultados.
- –orthophoto-resolution 10: Resolución (en cm/píxel) del ortomosaico.
- –dsm: Genera un modelo de superficie (DSM).
- –dem-resolution 10: Resolución (en cm/píxel) del DEM.
- –min-num-features 15000: Cantidad mínima de puntos/características a extraer en la reconstrucción.
- –build-overviews: Crea pirámides (overview) para el ortomosaico final, optimizando la visualización.
- –mesh-octree-depth 12: Define la profundidad del octree en la creación de la malla (más alto, más detalle).
- –mesh-size 5000000: Tamaño objetivo máximo de la malla (número de caras).
- –texturing-single-material: Usa una sola textura en la malla en lugar de múltiples parches.
- –use-3dmesh: Genera el modelo 3D final (la malla 3D).
- –return-from puede resultar de mucho interés cuando se están haciendo pruebas sobre un proceso concreto. En mi caso, al estar probando y probando parámetros, una vez que he lanzado, por ejemplo, el proceso de
opensfm
con bruteforce, lo cual consume muchísimos recursos mucho tiempo, es mejor evitar revisar de nuevo las fotografías, ya que podemos asumir que al ejecutar esto con bruteforce ya no vamos a conseguir mas puntos en común entre imágenes. Por lo tanto, una vez hecho el bruteforce, se puede cambiar al proceso que falla directamente, por ejemplo en mi caso, el odm_meshing…
La ejecución más pro
Si has llegado hasta aquí y todo te ha ido funcionando estás justo donde yo quería, en el haber entendido la herramienta, su funcionamiento y los argumentos principales. Por eso quiero darte este regalo.
Como ya sabes, no me gusta escribir cosas por duplicado, por lo que aquí te dejo la ejecución de Docker un poquito más parametrizada. Si vuelves atrás a la estructura de proyectos que te explicaba entenderás mejor de donde sale cada uno de estos parámetros como BASE_DIR
(directorio de proyectos) y FOLDER_NAME
(subdirectorio de proyecto). Si las demás carpetas se llaman como se tienen que llamar, no necesitas indicar nada más. Fácil, ¿no?
Básicamente este código produce todo lo que verás al final de vídeo de la segunda parte, donde te muestro tanto la ortofoto, el modelo del terreno y lo que más mola, el modelo texturizado en Blender.
export BASE_DIR="/home/$USER/ODM/"
export FOLDER_NAME="odm_test7"
export PROJECT_DIR="${BASE_DIR}${FOLDER_NAME}"
sudo chown -R $(id -u):$(id -g) "$PROJECT_DIR"
sudo docker run -ti --rm \
--gpus all \
-u $(id -u):$(id -g) \
-v "$PROJECT_DIR":/OPENDRONEMAP/"$FOLDER_NAME" \
-w /OPENDRONEMAP/"$FOLDER_NAME" \
opendronemap/odm:gpu \
--project-path /OPENDRONEMAP/"$FOLDER_NAME"/ \
--dsm \
--dtm \
--dem-resolution 1 \
--orthophoto-resolution 1 \
--min-num-features 25000 \
--build-overviews
Los extras
Hugin
Aquí tienes la web del proyecto
Hugin básicamente es un mezclador de imágenes libre que sirve sobre todo para hacer panorámicas. Sin embargo, también puede usarse para la mezcla de imágenes aéreas aunque no esté pensado para esto. Hay infinidad de tutoriales ahí fuera, pero aquí lo que voy a dejar por escrito es que Hugin también puede ejecutarse totalmente desde la terminal. Yo no he llegado a componer una ortofoto completamente como indico en los videotutoriales, pero me he quedado cerca.
Lo importante aquí, que además es lo que quiero compartir, es que esta búsqueda automatizada de puntos de unión entre imágenes es realizable desde terminal.
Este sería el código más simple posible que puedo ofrecer (como veis sigue la lógica de parametrización y autoexplicación del caso anterior).
# Define las rutas
INPUT_FOLDER="code/images"
OUTPUT_FOLDER="ortofoto_hugin"
mkdir -p "$OUTPUT_FOLDER"
PROJECT="$OUTPUT_FOLDER/mosaico.pto"
FINAL_IMAGE="$OUTPUT_FOLDER/ortofoto.tif"
# Genera el proyecto a partir de las imágenes (ajusta la extensión si es necesario)
pto_gen -o "$PROJECT" "$INPUT_FOLDER"/*.JPG
# Detecta puntos de control
cpfind -o "$PROJECT" "$PROJECT" \
--multirow \
--fullscale \
--kdtreesteps 100 \
--minmatches 200 \
--ransaciter 2000
# Elimina puntos de control erróneos
cpclean -o "$PROJECT" "$PROJECT"
# Optimiza el proyecto
autooptimiser -a -l -s -m -o "$PROJECT" "$PROJECT"
# Crea el mosaico (fragmentos)
nona -g -m TIFF_m -o "$OUTPUT_FOLDER/mosaico_" "$PROJECT" --ignore-exposure
# Fusiona los fragmentos en la ortofoto final
enblend -o "$FINAL_IMAGE" "$OUTPUT_FOLDER"/mosaico_*.tif
Tenéis gente mucho más pro que hace scripts más complejos y avanzados.
Pero, **¿qué pasa si el algoritmo por defecto de detección automatica de puntos (cpfind) no es suficiente?
Hugin + cvfind, el extra del extra
Hugin se basa en una libería llamada cpfind
, la herramienta de autodetección de puntos en común entre series de imágenes. Sin embargo, en este entorno donde hay muchísimo pasto en las zonas de superposición, esta herramienta tiene problemas a la hora de identificar puntos comunes entre hierba y hierba.
Existe una herramienta creada por este tipo (Bob-O-Rama) que podría ayudar a resolver este problema de estructuras fractales o repetititvas. Creo que es el caso, así que vamos a probar. La instalación no es sencilla, pero aun así la llamaremos…
Instalación “sencilla”
# 0. Variables de versión
OPENCV_VERSION="4.7.0"
echo "Instalando dependencias..."
sudo apt update
sudo apt install -y git cmake build-essential libgtk2.0-dev libgtk-3-dev zlib1g-dev
echo "Compilando OpenCV ${OPENCV_VERSION} con opencv_contrib..."
mkdir -p ~/build/opencv
cd ~/build/opencv
echo "Clonando OpenCV..."
git clone https://github.com/opencv/opencv.git
cd opencv
git checkout ${OPENCV_VERSION}
cd ..
echo "Clonando opencv_extra..."
# opencv_extra contains reference data sets for regression and unit testing
git clone https://github.com/opencv/opencv_extra/
cd opencv_extra
git checkout ${OPENCV_VERSION}
cd ..
# opencv_contrib contains additional modules for 2D feature analysis
git clone https://github.com/opencv/opencv_contrib/
cd opencv_contrib
git checkout 4.7.0
cd ..
cd opencv
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE -D OPENCV_ENABLE_NONFREE=ON -D BUILD_EXAMPLES=ON -D INSTALL_C_EXAMPLES=ON -D OPENCV_GENERATE_PKGCONFIG=ON BUILD_PERF_TESTS=ON -D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules -D WITH_GTK=ON ..
make -j9
sudo make install
mkdir ~/build/opencv/cvfind
# ( Place cvfind.cpp and Makefile into /build/opencv/cvfind )
cd ~/build/opencv
git clone https://github.com/Bob-O-Rama/cvfind.git cvfind
cd cvfind
# edita el makefile antes de compilar
LDFLAGS = -Wl,-rpath=/usr/local/lib -L/usr/local/lib `pkg-config --libs opencv4`
# Instalar
make clean
make WITH_CONTRIB=TRUE
sudo make install
Verificaciones, después de todo este calvario, esto debe funcionar y dar el mismo resultado
cvfind --test
LD_LIBRARY_PATH=/usr/local/lib ./cvfind --test
# y eso debería mostrar librerías
ldd $(which cvfind) | grep opencv
MicMac
MicMac es posiblemente la herramienta más potente jamás creada para la teledetección y la unión de imágenes. Es tan potente que no hay quien la entienda. Le he metido un buen rato (algunas horas) a trastear con sus herramientas, y como podréis ver en el vídeo, no he llegado más que a una especie de Picasso del territorio. Si tuviera que encriptar fotografías aéreas, usaría esta herramienta.
Os dejo aquí toda su documentación para que podáis jugar vosotros y ojalá os vaya mejor que a mi.
Sé que el potencial de esta librería es la leche y seguramente vuelva a darle una oportunidad. Os dejo aquí hasta donde he llegado tanto con la instalación como con la ejecución.
Aquí el script para instalar
# instalar dependencias
sudo apt update
sudo apt install -y git cmake make g++ libimage-exiftool-perl libfftw3-dev libtiff-dev libpng-dev libjpeg-dev libproj-dev libboost-all-dev libopencv-dev python3-dev exiv2
# clonar repositorio de micmac
git clone https://github.com/micmacIGN/micmac.git
cd micmac
# compilar e instalar
mkdir build
cd build
cmake ..
make -j$(nproc) # Usa todos los núcleos del CPU para compilar más rápido
sudo make install
# configurar variables de entorno
echo 'export PATH=/home/cesarkero/micmac/bin:$PATH' >> ~/.bashrc
# prueba la isntalación
mm3d
Aquí el script para ejecutar
#!/bin/bash
# 1. Definir variables
DIR_IMAGENES="./" # Directorio con las imágenes JPG
PATRON_IMAGENES=".*JPG" # Patrón para seleccionar imágenes
NOMBRE_PROYECTO="mi_proyecto"
RESOLUCION_TAPIOCA=1000 # Tamaño para cálculo de puntos de enlace
MODELO_CALIB="RadialBasic" # Modelo de calibración (RadialBasic, RadialExtended, FishEyeEqui, etc.)
# 2. Calcular puntos de enlace (tie points)
mm3d Tapioca MulScale "$PATRON_IMAGENES" $RESOLUCION_TAPIOCA -1
# 3. Calcular orientación de las imágenes
mm3d Tapas $MODELO_CALIB "$PATRON_IMAGENES" Out=Ori-$NOMBRE_PROYECTO
# 4. (Opcional) Si tienes puntos de control terrestre (GCPs)
# mm3d GCPBascule "$PATRON_IMAGENES" Ori-$NOMBRE_PROYECTO Ori-$NOMBRE_PROYECTO-GCP gcp_3d.xml gcp_2d.xml
# 5. Emparejamiento denso (dense matching)
mm3d Malt Ortho "$PATRON_IMAGENES" Ori-$NOMBRE_PROYECTO Out=MEC-$NOMBRE_PROYECTO ZoomF=2
# 6. Generar ortofoto
mm3d Tawny Ortho-MEC-$NOMBRE_PROYECTO/
# Los resultados estarán en:
# - Ortofoto: Ortho-MEC-$NOMBRE_PROYECTO/Orthophotomosaic.tif
# - DSM: MEC-$NOMBRE_PROYECTO/Z_Num6_DeZoom2_STD-MALT.tif
# - DEM: MEC-$NOMBRE_PROYECTO/Z_Num6_DeZoom2_STD-MALT.tif (el mismo que DSM en este caso)
Mientras lo vuelvo a ver escribiendo este post creo que le estoy cogiendo cariño a este resultado:
MapsMadeEasy
Y para terminar con este apartado de extra, dejo el servicio más sencillo de usar. Para aquellos que no tenéis nada que perder ni nada que aprender. En este servicio, solo hay que arrastras las imágenes, esperar 24 h (en mi caso algo menos) y listo. Mapita descargable. Resultado: pobre, muy pobre.
Quizá sea porque las imágenes con las que estoy haciendo este “sencillo ejercicio” son más complicadas de lo que parecen (olas batiendo, hierba en constante movimiento, nubosidad cambiante…). De lejos podría dar el pego, pero de cerca veréis que ha fallado más que una escopeta de feria.
Esto no quiere decir que no ofrezcan un buen servicio, sino que con la prueba que yo he hecho no que quedado satisfecho. Volveré a intentarlo en el futuro, pero nada de pagar de momento.
Conclusiones
OPEN DRONE MAP ES LA HOSTIA
Segundas conclusiones
OpenDroneMap es la herramienta imprescindible si quieres generar Meshes y Ortofotos. Además, si te lo curras en la planificación de vuelo te aseguro que podrás tener unos modelos de superficies y elevación de elementos brutales. He realizado ya varias pruebas profesionales y estoy absolutamente maravillado. Además, todo lo que aquí muestro está realizado con un sencillo DJI Mini 2. ¿Te imaginas lo que se podría llegar a hacer con un Mini 4 Pro, por ejemplo? Pues si lo imaginas y me das un poco más de tiempo este verano espero hacer un vídeo más actualizado con él. Tengo varias cartografías y monumentos naturales en mente, pero todo a su debido tiempo.
Espero que hayas apreciado el esfuerzo en todo esto. Podrías apoyarme de muchas formas: contratándome, contactándome o símplemente compartiéndolo.