Fotogrametría y Cartografía en Linux - Meshroom y los modelos 3D Mesh
Contenido:En este post volveremos a revisar de forma actualizada y más profesional la instalación, configuración y ejecución del programa Meshroom. Este programa permite reconstruir un modelo tridimensional de la forma más sencilla posible.
Video tutoriales
Parte I - Meshroom y los modelos
Parte II - Blender, limpieza e iluminación exacta del mesh
Parte I: Meshroom y los modelos
En este primer post de la serie actualizada de productos de dron en Linux, te mostraré cómo de forma muy sencilla puedes generar un modelo 3D de cualquier cosa con el programa más sencillo (para el usuario) del mundo y que en Linux funciona de maravilla: Meshroom.
Meshroom
es un software de fotogrametría basado en AliceVision que reconstruye modelos 3D a partir de fotos 2D. Es gratuito, de código abierto y compatible con Linux, pero requiere GPU NVIDIA con CUDA.
El equipo
Pues todo parte de tener una cámara o un dron. Para este ejercicio se ha usado el dron DJI Mini 2 en una zona próxima a Suances (Cantabria). No se ha utilizado DJI Fly sino un programa llamado Dronelink
que permite automatizar misiones. En el vídeo encontraréis los detalles de cómo se ha planificado este vuelo, en el que se incluye tanto la parte de las tomas orbitales de la torre como el vuelo para la generación de la ortofoto (motivo que dirige el vídeo y post siguientes).
Aquí los enlaces a los equipos y programas:
Sobre la fotogrametría
La fotogrametría es la técnica que permite obtener medidas y modelos 3D a partir de fotografías. Consiste en capturar múltiples imágenes de un objeto o escena desde diferentes ángulos y, mediante algoritmos, identificar puntos comunes en ellas para calcular la posición de la cámara y reconstruir la geometría del espacio. Es una herramienta muy útil en topografía, arquitectura, arqueología y en la creación de gemelos digitales.
Si lo que quieres es aprender esto desde el principio te recomendaría cualquiera de los tutoriales que puedes encontrara aquí. No obstante, considero este trabajo un poco más avanzado. Así que si quieres aprender detalles concretos sobre la secuencia de trabajo, no te vayas :-). Los dos programas principales para vivir de esto son:
Cómo instalar Meshroom
La instalación en Ubuntu 24.04 es tan sencilla como descargar el programa y descomprimir la carpeta donde se desee. Después, el programa funciona directamente con el ejecutable, sin necesidad de hacer ni instalar específicamente nada más. Si tenéis además gráficas Nvidia y usáis CUDA, todo debería ser detectado correctamente. Al menos así lo fue en mi caso. Descarga el archivo .tar.gz en esta web. Después descomprime el archivo. Se creará una carpeta con todo al mismo nivel del archivo descargado.
tar xvzf Meshroom-2023.3.0-linux.tar.gz
Si abrís el programa Meshroom os encontraréis una interfaz tal que así:
Cómo extraer los fotogramas del vídeo
Meshroom
solo funciona con imágenes estáticas. Por eso, en caso de que tu información de partida sea un vídeo, como se ha hecho en este ejemplo, lo mejor es usar una herramienta ffmpeg
en la terminal para transformar los vídeos en imágenes. Aquí te dejo el código. Solo tienes que ejecutarlo en la terminal apuntando a la ubicación de tus vídeos.
# 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."
Cómo configurar Drone Link
Como ya se habrá dado cuenta cualquier persona que se haya pasado por algunos de los posts de este blog, me encanta automatizar tareas. Me encantan volar a mano, por supuesto. Quiero decir, usar la propia aplicación de DJI y hacer vuelos con el DJI Mini 2 trazando órbitas, o sacando panorámicas de los paisajes “permitidos” a los que voy, sin embargo, si hablamos de realizar fotogrametría o generar mosaicos y ortofotos, el modo manual no es lo más recomendable.
Para aquellos que usamos el Mando RC y tenemos un dron compatible como este (DJI Mini 2), tenemos una posibilidad muy económica de realizar vueltos autogestionados, o mejor dicho, planeados. Con Dronelink, tenéis la posibilidad de hacer varias cosas:
- Waypoints (también ir grabando de punto a punto)
- Panorámicas esféricas (después hay que montarlas en Hugin)
- Orbitales
- ¡MAPAS! (ortofotos, modelos del terreno…)
- Programaciones (jamás las he usado)
En mi caso, como quería probar el plan de mapeo para generar modelos de terreno y ortofotos, me hice con el PREMIUM (59.99 $ pago único). Con eso ya podéis hacer tanto las orbitales como los mapas ortogonales. Si váis a vender directamente los productos derivados de dron, entonces, no será suficiente con esta licencia y necesitaréis una de las profesionales.
Cómo lanzar el proceso
Pues tan sencillo como se muestra en el vídeo. Arrastráis vuestros fotogramas al programa, guardar el proyecto (por si algo fallara) y le dais a START. El proceso, como podéis observar en el esquema inferior, consta de varias partes secuenciales. Cada una de estas partes, generará en la carpeta de proyecto una subcarpeta.
En este caso, el proyecto para la recreación de la torre consta de 98 imágenes, de unos 5 megas. Podrían ser muchísimas más, pero para esta escala y propósito son más que suficientes. Llegados a cierto punto, el proceso empieza a mostrar en la ventana derecha la construcción de la escena y el posicionamiento de las cámaras.
OFF THE RECORD - COLMAP & OPENMVS
Durante la búsqueda de soluciones libres para el levantamiento de modelos he trasteado con dos herramientas que se utilizan conjuntamente también para generar modelos texturizados 3D sin necesidad de interfaz. Es decir, que se puedan sistematizar tanto que solo hay que ejecutar una herramienta en la terminal.
Mi experiencia con COLMAP en la generación del modelo 3D ha sido positiva, sin embargo, no he sido capaz de generar el modelo de texturas que sí genera Meshroom. Me gustaría seguir profundizando en este sistema, pero según vaya teniendo más o menos tiempo. Recuerda que el vídeo de youtube incluye la vista del mesh conseguido hasta aquí. La documentación oficial, desde la instalación hasta casos de uso los tenéis aquí
Mi proceso de instalación COLMAP
En primer lugar hay que instalar paquetes, como siempre.
# instalar paquetes previos
sudo apt-get install \
git \
cmake \
ninja-build \
build-essential \
libboost-program-options-dev \
libboost-graph-dev \
libboost-system-dev \
libeigen3-dev \
libflann-dev \
libfreeimage-dev \
libmetis-dev \
libgoogle-glog-dev \
libgtest-dev \
libgmock-dev \
libsqlite3-dev \
libglew-dev \
qtbase5-dev \
libqt5opengl5-dev \
libcgal-dev \
libceres-dev
# compilador CUDA
sudo apt-get install -y \
nvidia-cuda-toolkit \
nvidia-cuda-toolkit-gcc
Clonar y compilar COLMAP.
git clone https://github.com/colmap/colmap.git
cd colmap
mkdir build
cd build
cmake .. -GNinja
ninja
sudo ninja install
Lanzar COLMAP.
colmap -h
colmap gui
Mi proceso de instalación OpenMVS
Antes de seguir, instalar también paquetes previos y necesarios a OpenMVS.
sudo apt update
sudo apt install cmake git build-essential libpng-dev libjpeg-dev libtiff-dev \
libglu1-mesa-dev libboost-all-dev libcgal-dev libatlas-base-dev \
libeigen3-dev libopencv-dev libcgal-dev libcgal-qt5-dev
Antes de instalar OpenMVS necesitarás CGAL y no será suficiente, a fecha de este post, con la instlaación típica…lo sabrás porque si buscas el archivo necesario dpkg -L libcgal-dev | grep AABB_traits_3
no lo encontrarás…
# clonar y entrar
git clone --recursive https://github.com/CGAL/cgal.git
cd cgal
# compilar e instalar
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
sudo make install
Ahora sí, el archivo aparecerá, aunque en otro lugar… find /usr/local/include/CGAL/ -name "AABB_traits_3.h"
El tema aquí es, ¿Cómo indicamos este archivo a la compilación de OpenMVS? Pues solo hay que indicarle al cmake
del repositorio de OpenMVS la ruta donde buscar este archivo que falta. (mira la primera línea del chunk más abajo).
Clona el repositorio de OpenMVS, incluyendo la librería VCG como submódulo o carpeta (fijate que hay unas especificaciones en la parte de la compilación, lo que hablamos antes…)
git clone --recursive https://github.com/cdcseacave/openMVS.git
cd openMVS
git submodule update --init --recursive
# compilar
export CMAKE_PREFIX_PATH="/usr/local:$CMAKE_PREFIX_PATH"
export VCG_ROOT="$(pwd)/libs/VCG"
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
Al acabar, en openMVS/build/bin
tendrás los binarios:
InterfaceVisualSFM
DensifyPointCloud
ReconstructMesh
TextureMesh
Mi proceso completo
Este script secuencial ha sido fruto de ir trabajando con la documentación de github, algunos pipelines de algunas personas (ya no recuerdo cuantas fuentes habré consultado) y por supuesto ChatGPT y DeepSeek. Con todo esto he llegado a generar el modelo pero no el texturizado. Así que si alguien sabe más estaré encantado de aprender. No me hago cargo de todos los parámetros aquí especificados, pero a mi me ha funcionado, insisto…sin texturas.
#!/bin/bash
# Directorio principal de tu proyecto COLMAP
# Reemplázalo por la ruta correcta (por ejemplo: /home/tu_usuario/ODM/colmap_test)
base_dir="ODM/colmap_test"
# 1. Extracción de características (SIFT) con GPU
colmap feature_extractor \
--database_path "$base_dir/colmap.db" \
--image_path "$base_dir/images" \
--SiftExtraction.use_gpu 1
# 2. Emparejamiento exhaustivo de características con GPU
colmap exhaustive_matcher \
--database_path "$base_dir/colmap.db" \
--SiftMatching.use_gpu 1
# 3. Reconstrucción inicial (sparse)
mkdir -p "$base_dir/sparse"
colmap mapper \
--database_path "$base_dir/colmap.db" \
--image_path "$base_dir/images" \
--output_path "$base_dir/sparse"
# 4. Reconstrucción densa
mkdir -p "$base_dir/dense"
# - Copia y corrige la calibración de la carpeta sparse/0 a dense/
colmap image_undistorter \
--image_path "$base_dir/images" \
--input_path "$base_dir/sparse/0" \
--output_path "$base_dir/dense" \
--output_type COLMAP \
--max_image_size 2000
# - PatchMatch Stereo (densifica la nube de puntos)
colmap patch_match_stereo \
--workspace_path "$base_dir/dense" \
--workspace_format COLMAP \
--PatchMatchStereo.gpu_index 0
# - Fusiona la nube de puntos densa en un archivo PLY
colmap stereo_fusion \
--workspace_path "$base_dir/dense" \
--workspace_format COLMAP \
--input_type geometric \
--output_path "$base_dir/dense/fused.ply"
# - Genera la malla con Poisson (sin texturas, solo geometría y color por vértice)
colmap poisson_mesher \
--input_path "$base_dir/dense/fused.ply" \
--output_path "$base_dir/dense/meshed-poisson.ply"
echo "Reconstrucción completa en:"
echo " - Sparse: $base_dir/sparse/0"
echo " - Densa: $base_dir/dense/fused.ply"
echo " - Malla: $base_dir/dense/meshed-poisson.ply"
# 5. Convierte el modelo a formato MVS (para usar en OpenMVS u otros)
colmap model_converter \
--input_path "$base_dir/dense/sparse" \
--output_path "$base_dir/dense/model" \
--output_type NVM
echo "Modelo MVS generado en $base_dir/dense/model.mvs"
echo "Ahora puedes texturizar con OpenMVS (DensifyPointCloud, ReconstructMesh, TextureMesh)."
Parte II - Blender, limpieza y renderización
Si has llegado hasta aquí habiendo construido tu propio mesh de alguna localización concreta ya tienes lo más importante hecho. En esta segunda parte verás algunos aspectos importantes para poder utilizar este modelo de forma más precisa. Qué se hará aquí:
- Limpiar un mesh.
- Posicionar y escalar un mesh.
- Ajustar la iluminación de forma real con el addon Sun Position.
Blender - Importar y limpiar
La carpeta texturing del proyecto de Meshroom contiene el archivo .obj
con las texturas ya asociadas como podrás ver dentro del archivo. Este archivo de texturar, sin entrar en detalles, determina que partes de la o las fotografías se asignan a cada una de las caras o conjuntos de caras del mesh. Estos dos archivos (.obj
y texture_1001.exr
) iran de la mano y, al menos en Blender, no tendrás que hacer nada extra para importarlos de forma conectada. Simplemente, no los cambies de sitio uno respecto del otro.
Imporarás el modelo .obj y si muestras las texturas verás algo así.
A continuación, creo que es importante limpiar el modelo ya que hay muchas partes, especialmente esas zonas de agua en constante movimiento, donde el programa hace…lo que puede. Para esto, símplemnete colócate en vista superior (7 numpad
), activa la edición (TAB
) y activa la transparencia
. De esta forma no de dejarás vértices atrás.
Blender - Iluminación Sun Position
Ahora el tema está en posicionar el modelo y las luces de forma que encajen con las imágenes tomadas en la realidad. Esto está pensando en la integración fotorrealista. Si tu objetivo no es este y solo quieres trastear o limpiar un modelo para llevártelo a cualquier otro lado, quizá esto no sea tan relevante para ti. Para mí, por mi trabajo, sí lo es, y necesito muchas veces que los modelos estén “mallados”.
Para entender detalles extra de la herramienta puedes pasarte por este sitio.
Antes de entrar en los detalles de cómo funcionaría la luz con Sun Position, te recomiendo que te pases por la web de SunCalcwww.suncalc.com. También por este post en el que analizo el efecto solar sobre fotografías 360 (aprovecho la autopromoción :-). En resumen, tienes que saber más o menos cual es la dirección que tendría el sol a la hora de la captura. Sabiendo la fecha concreta sabrías también la altura relativa. Si todo esto te suena a chino, no te preocupes, porque Sun Position
lo calcula todo por ti.
Vamos al grano. En Blender, para ajustar las sombras correctamente, solo tienes que:
- Activar el Addon Sun Position.
- Ajustar fecha y hora a las de la toma
- Cambiar el World y conectar un nuevo nodo sky texture.
- Ajustar la rotación del modelo para encajar las sombras.
Si ya has llegado hasta algo así, dos sombras, casi idénticas pero no exactas estás a punto de conseguirlo. Si tu posicionamiento solar es exacto, entonces, lo que falla es la rotación de tu modelo. Por lo tanto, ponte en vista superior y rota (R) el modelo hasta que las sombras estén perfectamnete alineadas.
Para posicionamiento exacto de elementos (georreferenciación) y otro tipo de trabajos de precisión, pásate por las muchas entradas del blog al respecto. Si tienes más dudas sobre algún proyecto propio concreto, no dudes en contactar.
Blender - Resultado
Cuando hayas ajustado todo y te hayas “peleado” lo suficiente podrán tener una recreación exacta del lugar y podrías tener un buen rudimento para crear tu gemelo digital, incorporar el modelo a otro proyecto, venderlo, analizarlo, etc. Habrás llegado a algo así. Insisto, todos los detalles los tendrás en los vídeos que acompañan este post.
Espero que hayas apreciado el esfuerzo en todo esto. Podrías apoyarme de muchas formas: contratándome, contactándome o símplemente compartiéndolo.