Digi3D.NET siempre ha podido cargar archivos JPEG en la ventana de dibujo, nunca en la ventana fotogramétrica. La causas de no añadir esa posibilidad eran las siguientes:
Las cámaras fotogramétricas clásicas (las de avión, no las de drone) guardan las imágenes en formato TIFF de forma nativa. Ninguna guarda archivos JPEG.
La velocidad de descompresión del formato JPEG no es muy rápida.
JPEG no está pensado para imágenes enormes (más de 10000×10000 píxeles, que es lo habitual en imágenes fotogramétricas), para este tipo de imágenes hay otros formatos que sí que soporta Digi3D.NET en la ventana fotogramétrica, como ECW, MrSID, etc. que son muy rápidos y tienen un ratio de compresión mucho mejor y con menos pérdida que JPEG.
JPEG no admite niveles piramidales mas allá del 16, y con imágenes tan grandes, ese nivel piramidal es muy corto, no podrías llegar a ver la imagen completa al hacer un zoom extendido.
Pero nos guste o no estamos en la era de los drones y todo ha cambiado.
Ahora se vuela con cámaras «de juguete» que de forma nativa almacenan archivos .JPG.
Las imágenes ya no son tan grandes y si que podemos verlas completas en el nivel piramidal 16.
Así que hemos decidido añadir carga de archivos JPEG en la ventana fotogramétrica, de manera que ahora la ventana fotogramétrica admite los siguientes formatos de imagen:
Ayer mismo publicamos una entrada en la que se anunciaba la posibilidad de cargar archivos .PRJ de Inpho con parámetros RPC de satélites, pero el vídeo tenía un truco para evitar que Digi3D.NET solicite el Sistema de Referencia de Coordenadas (SRC a partir de ahora) vertical.
El sensor satelital de Digi3D.NET es un sensor 3D, de modo que requiere que le proporcionemos tres coordenadas: X, Y, Z o Longitud, Latitud, Altitud. Además, Digi3D.NET necesita saber el SRC de estas coordenadas.
Si los parámetros RPC se han obtenido de cualquiera de los formatos que soportaba la extensión hasta ayer (antes de añadir la posibilidad de obtenerlos de archivos .PRJ de Inpho), se suponía que el SRC era el EPSG:4979, que el SRC geográfico 3D (lo que significa que la coordenada Z es elipsoidal) con nombre WGS 84. No lo confundas son el mucho más famoso EPSG:4326 con el que comparte nombre: este otro es 2D, y únicamente puede formar parte de un SRC compuesto, y en los SRC compuestos no podemos especificar una coordenada Z elipsoidal, tiene que ser ortométrica si o si.
Cuando ayer implementamos la posibilidad de cargar archivos .PRJ hicimos que el SRC asociado al sensor satelital ya no sea siempre el EPSG:4979, sino que sea el que viene indicado en el archivo .PRJ. El problema es que los SRC que aparecen en los archivos .PRJ son 2D y no 3D.
A continuación tienes un recorte de un archivo .PRJ con las orientaciones en geográficas:
$PROJECT 7.0.0
# generated using Version 7.0.1.49528 (64bit), build #36 of 2015-10-13 09:38
$PROJECT_NAME : new_project
$USER_ID : Jose Manuel
$STARTING_DATE : mar ene 12 12:44:00 2016
$LAST_CHANGE : Tue Jan 12 13:22:21 2016
$IMAGE_TYPE : Satellite
$REFRACT_CORR_DEFAULT : off
$CURV_CORR_DEFAULT : off
$COORDINATE_SYSTEM :
GEOGCS["WGS 84",
DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG",
"7030"]],
AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],
UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],
AUTHORITY["EPSG","4326"]]
$LINEAR_UNITS_OF_OBJECT : m
$LINEAR_UNITS_OF_IMAGE : pixel
$ANGULAR_UNITS : deg
$REPORT_LOGFILE : C:\Users\Jose Manuel\new_report.log
$END
Como puedes ver, el SRC proporcionado es el EPSG:4326. A simple vista se ve que es 2D, porque los SRC que se definen como GEOGCS son 2D, así de sencillo.
Lo mismo ocurre con un archivo .PRJ con las coordenadas en UTM como puedes ver a continuación:
$PROJECT 7.0.0
# generated using Version 7.0.1.49528 (64bit), build #36 of 2015-10-13 09:43
$PROJECT_NAME : new_project
$USER_ID : Jose Manuel
$STARTING_DATE : mié nov 18 14:03:18 2015
$LAST_CHANGE : Tue Dec 15 14:09:15 2015
$IMAGE_TYPE : Satellite
$STD_DEV_OBJECT_POINTS : 0.200000
$STD_DEV_OBJECT_Z_POINTS : 0.400000
$STD_DEV_IMAGE_POINTS : 0.500000
$STD_DEV_IMAGE_GC_POINTS : 0.500000
$SDS_OBJ_GROUP_XY : -1.000000 -1.000000 -1.000000 -1.000000
$SDS_OBJ_GROUP_Z : -1.000000 -1.000000 -1.000000 -1.000000
$REFRACT_CORR_DEFAULT : off
$CURV_CORR_DEFAULT : off
$COORDINATE_SYSTEM :
PROJCS["WGS 84 / UTM zone 18S",
GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,
AUTHORITY["EPSG","7030"]],
AUTHORITY["EPSG","6326"]],
PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],
UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],
AUTHORITY["EPSG","4326"]],
UNIT["metre",1,AUTHORITY["EPSG","9001"]],
PROJECTION["Transverse_Mercator"],
PARAMETER["latitude_of_origin",0],
PARAMETER["central_meridian",-75],18S
PARAMETER["scale_factor",0.9996],
PARAMETER["false_easting",500000],
PARAMETER["false_northing",10000000],
AUTHORITY["EPSG","32718"],
AXIS["Easting",EAST],
AXIS["Northing",NORTH]]
$LINEAR_UNITS_OF_OBJECT : m
$LINEAR_UNITS_OF_IMAGE : pixel
$ANGULAR_UNITS : deg
$REPORT_LOGFILE : C:\Users\Jose Manuel\new_report.log
$END
Este sistema también es 2D, porque los proyectados son siempre 2D.
Si intentamos cargar un archivo de estos, Digi3D.NET va a preguntarnos por el SRC de la componente vertical mostrando el siguiente cuadro de diálogo:
y esto lo va a hacer cada vez que carguemos el modelo.
Si queremos evitar que suceda esto, podemos modificar las cadenas WKT que aparecen en los archivos .PRJ y poner una que proporcione información del SRC vertical.
Para ello seguiremos los siguientes pasos:
Seleccionamos la opción del menú Herramientas/Sistema de referencia de coordenadas…
Seleccionamos el SRC que nos interese.
Pulsamos el botón Copiar para que se copie la cadena WKT al portapapeles.
Abrimos el archivo .PRJ con nuestro editor de textos favorito y modificamos la cadena WKT que aparece ahí por la que tenemos en el portapapeles.
Con esto habremos conseguido que Digi3D.NET no nos pregunte cada vez por el SRC vertical del modelo.
Además esto es fundamental si queremos trabajar con coordenadas Z elipsoidales, en cuyo caso tendremos que seleccionar como el SRC Geográfico 3D WGS 84, porque como he indicado antes, no podemos asignar un SRC elipsoidal a un SRC compuesto.
Puedes ver un vídeo en el que explico todo esto a continuación:
Hemos realizado dos mejoras en el cuadro de diálogo de selección de Sistema de Referencia de Coordenadas en Digi3D.NET:
A partir de ahora, podemos seleccionar el orden de los ejes en los sistemas de coordenadas horizontales que forman parte de los sistema de referencia de coordenadas compuestos Proyectado + Vertical.
Ahora podemos almacenar los sistemas de referencia de coordenadas en el portapapeles de Windows.
Hasta ahora únicamente podíamos seleccionar el orden de los ejes en los sistemas Geográfico 3D y en Geográfico + Vertical. Ahora podemos también seleccionar el orden de los ejes en Proyectado + Vertical.
Podemos seleccionar una de las siguientes opciones:
Estándar (se obtendrá el orden de los ejes de la base de datos EPSG).
Este, Norte (se forzará a que el primer eje sea el que apunte a Este y el segundo el que apunta a Norte).
Norte, Este (se forzará a que el primer eje sea el que apunta a Norte y el segundo el que apunta a Este).
Para hacer que se copie la cadena WKT al portapapeles, tan solo tenemos que pulsar el botón Copiar que aparece en las distintas páginas del cuadro de diálogo.
Acabamos de añadir a Digi3D.NET la carga nativa de archivos de proyecto de Inpho (*.prj) con polinomios RPC para imágenes satelitales.
De esta manera, Digi3D.NET puede trabajar con aerotriangulaciones calculadas con Inpho de forma completamente transparente para el usuario.
Este importador de orientaciones se une a los ya existentes en Digi3D.NET, de modo que ya se pueden cargar sin necesidad de tener que utilizar ningún importador orientaciones de los siguientes programas:
Debido a la incorporación del modelo de corrección de distorsiones en cámaras calibradas con Pix4D, PhotoScan y con OpenCV, hemos realizado una serie de cambios en el concepto de cámara en Digi3D.NET.
Los cambios realizados son internos y hemos mantenido compatibilidad hacia atrás, de manera que las cámaras creadas a día de hoy se seguirán comportando de la misma manera.
Un restituidor digital como Digi3D.NET básicamente muestra imágenes centrando un determinado pixel de estas imágenes en el centro de la ventana fotogramétrica. Cuando mueves el dispositivo de entrada (manivelas, topomouse, ratón, etc.) se incrementan o decrementan valores a las Coordenadas Terreno y el sensor correspondiente se encarga de transformar dichas Coordenadas Terreno a Coordenadas Pixel en las que se tendrá que centrar cada imagen mostrada en la Ventana Fotogramétrica, de modo que la responsabilidad de transformar de Coordenadas Terreno a Coordenadas Pixel recae en los sensores (que en Digi3D.NET están implementados como extensiones).
Cada sensor (ADS, Satelital, Cámaras Cónicas, etc.) pasa por una serie de cálculos (específicos del modelo matemático del sensor) para cumplir esa misión: Transformar de Coordenadas Terreno a Coordenadas Pixel.
Los cambios que hemos introducido aquí se aplican al Sensor Cónico (el de cámaras pinhole), el resto de sensores no se han tocado.
Veamos cómo se comportaba hasta hoy este sensor para transformar de Coordenadas Terreno a Coordenadas Pixel:
La Orientación Exterior tenía como parámetros de entrada Coordenadas Terreno (Xt, Yt, Zt) y como salida proporcionaba Coordenadas Foto (Xfo, Yfo). Para conseguir esto, la Orientación Exterior tenía que conocer con qué cámara estamos trabajando, pues en el cálculo para obtener Coordenadas Foto interviene la Focal de la cámara. Esto como verás más adelante lo hemos cambiado: ahora la Orientación Exterior es agnóstica en lo referente a la cámara con la que se está trabajando y por lo tanto no tiene conocimiento de que existe una cámara.
La misión de la Cámara era transformar las Coordenadas Foto en Coordenadas Fiducial (Xfi, Yfi) corrigiendo las distorsiones de la lente si era necesario.
La misión de la Orientación Interna era transformar de Coordenadas Fiducial a Coordenadas Pixel (Xp, Yp).
Las correcciones de distorsión se realizaban en el paso de Coordenadas Foto a Coordenadas Fiducial únicamente. Además, puedes ver que teníamos que tener si o si una orientación interna.
Resulta que las distorsiones en Pix4D, PhotoScan y las calibraciones obtenidas mediante cualquier programa que utilice la librería de visión artificial OpenCV no corrigen las distorsiones en el sistema foto, sino que se corrigen en el Sistema Cámara Proyectado. Además, no es necesaria una orientación interna pues el modelo matemático para estas cámaras transforma directamente a coordenadas pixel.
Veamos cómo se comporta el sensor cónico de Digi3D.NET para transformar de Coordenadas Terreno a Coordenadas Pixel una vez realizados los cambios que presentamos hoy:
Ahora la orientación exterior no devuelve Coordenadas Foto (Xfo, Yfo), sino que devuelve Coordenadas en el Sistema Cámara (Xcam, Ycam, Zcam). La misión de las Cámaras ahora es convertir esas Coordenadas en el Sistema Cámara a Coordenadas Pixel (Xp, Yp).
Estudiemos ahora cómo transforma la cámara de Coordenadas en el Sistema Cámara a Coordenadas Pixel:
Lo primero que hacemos es convertir de Coordenadas en el Sistema Cámara a Coordenadas Proyectadas en el Sistema Cámara (dividiendo tanto la componente X como la Y por la Z).
Luego transformamos de Coordenadas Proyectadas en el Sistema Cámara a Coordenadas Foto. Las implementaciones de Pix4D, PhotoScan y OpenCV corrigen las distorsiones en este paso. En esta fase se tiene en cuenta la focal (o mejor dicho, las focales de la cámara, porque ahora se pueden introducir dos focales si es necesario (si la cámara está calibrada en píxeles y el sensor es barato, es posible que el ancho del pixel no coincida con el alto del pixel, por lo tanto obtenemos dos focales distintas).
Continuamos transformando de Foto a Fiducial. Es en esta fase donde Digi3D.NET calculaba las distorsiones. Las cámaras Pix4D, PhotoScan y OpenCV básicamente suman aquí las coordenadas del punto principal.
Y por último se transforman las Coordenadas Fiducial a Coordenadas Pixel. Si la cámara es analógica, aquí es donde se tiene en cuenta la orientación interna, y si no, pues básicamente se multiplican las Coordenadas Fiducial por el tamaño del pixel y se les suma la coordenada del pixel central de la imagen (que es el 0,0 en el sistema fiducial).
Digi3D.NET ahora carga de forma nativa archivos de Pix4D (en breve de PhotoScan y de OpenCV si es que existe algún formato estandarizado para OpenCV, lo tengo que estudiar), de modo que no tienes que hacer nada más que cargar el archivo de cámara correspondiente y Digi3D.NET se encarga de todo, tal y como puedes ver en la entrada del blog Carga nativa de archivos de calibración de cámaras de Pix4D, sin embargo, hemos modificado también los archivos de cámara de Digi3D.NET para que puedas crear un archivo de cámara en formato Digi3D.NET y que funcione igual que el de Pix4D por ejemplo.
Veamos a continuación cómo han quedado esos parámetros:
Variable
Valor
Valor por defecto
Descripción
Focal
Si la focal tiene las mismas dimensiones en X y en Y, un único valor con el valor de la focal.
Si la focal tiene distintas dimensiones en X y en Y, dos valores: uno para la focal en X y otro para la focal en Y.
N/A
Focal calibrada de la cámara. Las unidades de este valor definen las unidades del resto de valores en el archivo de cámara, lo que quiere indicar que si ponemos este valor en milímetros, las unidades del resto de variables deberán estar en milímetros. De puede introducir aquí un valor en cualquier unidad, con la condición de que el resto de variables utilicen la misma unidad.
TipoCorreccion
CamaraAFoto
FotoAFiducial
FotoAFiducial
Indica en que paso se va a realizar la corrección de distorsiones de la cámara. Por defecto este valor es CamaraAFoto para mantener compatibilidad hacia atrás.
TipoDistorsionTangencial
No.
Si no se quiere aplicar distorsión tangencial.
Brown.
Si se quiere aplicar la siguiente fórmula:∆x = P1*(r2 + 2*x2)+2*P2*x*y
∆y = 2*P1*x*y + P2*
(r2 + 2*y2)
OpenCV.
Si se quiere aplicar la siguiente fórmula:∆x = 2*P1*x*y + P2*(r2 + 2*x2)
∆y = 2*P2*x*y + P1*(r2 + 2*y2)
Si no se especifica esta variable ni las variables P1 y P2, el valor por defecto es No.
Si no se especifica esta variable y en el archivo de cámara aparecen valores para las variables P1 y P2, por compatibilidad hacia atrás el valor por defecto es Brown.
Indica el tipo de corrección tangencial a aplicar. Estas distorsiones aparecen por una mala alineación entre la lente y el sensor.
TipoDesortogonalidad
No.
Si no se desea aplicar desortogonalidad.
Fraser.
Si se desea aplicar desortogonalidad en el eje de la X mediante la fórmula:∆x = B1*x + B2*y
Si no se especifica
esta variable ni las variables B1 y B2, el valor por defecto es No.
Si no se especifica esta variable pero si se especifican las variables B1 y B2, el valor por defecto es Fraser
Indica el tipo de desortogonalidad (por una mala fabricación del sensor CCD en el que puede que los píxeles no tengan el mismo ancho que alto o que la matriz de píxeles no esté perfectamente alineada.
Te muestro a continuación el código fuente de la función que calcula la corrección por distorsión para que quede claro cómo se calculan las distorsiones en Digi3D.NET (está programado en C++, pero aunque no entiendas de programación creo que haces un mínimo esfuerzo por entenderlo lo vas a ver claro):
De esta manera puedes ver cómo intervienen todos los parámetros del archivo de cámara.
Vemos ahora un caso práctico: Vamos a crear un archivo de cámara en formato Digi3D.NET que simule el siguiente archivo de cámara de Pix4D:
Pix4D camera calibration file 0
#Focal Length mm assuming a sensor width of 23.64864599999999938973x15.76576400000000077739mm
F 25.21219253120580461314
#Principal Point mm
Px 11.78574296804639587322
Py 7.57715224585386515344
#Symmetrical Lens Distortion Coeffs
K1 0.00086121816472929343
K2 0.02791840536682562574
K3 -0.03806069473095977096
#Tangential Lens Distortion Coeffs
T1 -0.00621590311996760014
T2 -0.00051873958437360630
Puedes comprobar que aparece (como comentario) el tamaño del sensor en milímetros. No aparece por ningún sitio el tamaño del pixel, ni el tamaño de las imágenes.
Si te fijas en el archivo de calibración se indica que el ancho del sensor es mayor que el alto del sensor, lo que significa que la cámara se ha calibrado en horizontal y las fotos obtenidas con esta cámara deberían ir siempre en horizontal (desactivar la opción de rotado automático), y así habría que cargarlas en Digi3D.NET.
Esta cámara en particular crea imágenes de 6000×4000 píxeles, de modo que el tamaño de píxel en horizontal y en vertical se puede deducir fácilmente dividiendo el ancho del sensor por el número de píxeles en horizontal por un lado y el alto del sensor por el número de píxeles en vertical de la imagen dando los siguientes resultados
Continuamos con el punto principal. El punto principal en Pix4D se da con respecto a la esquina superior izquierda de la imagen, y no con respecto al centro fiducial como estamos acostumbrados, de modo que tenemos que hacer una simple resta (coordenadas que aparecen en el archivo de Pix4D menos coordenadas del centro fiducial de la cámara) para transformar ese punto principal a un punto principal con respecto al centro fiducial que es como lo requiere Digi3D.NET. Los ejes X e Y crecen de forma distinta, por lo tanto verás que en la Y la operación se hace al revés.
Y el centro fiducial es muy sencillo: o dividimos entre dos el ancho y alto del sensor por un lado, o dividimos entre dos el tamaño de la imagen (el resultado nos dará en píxeles obviamente) y multiplicamos el valor por el tamaño de pixel calculado anteriormente. Voy a utilizar una fórmula para la X y otra para la Y, así las tienes las dos:
Si estudiamos las fórmulas utilizadas por Pix4D comprobaremos que éste realiza la corrección de distorsión en el paso de Coordenadas Cámara Proyectadas a Coordenadas Focal, y que además el polinomio utilizado para las distorsiones radiales es K1_R2_K2_R4, además se utiliza como tipo de distorsión tangencial el método de OpenCV y que no se tiene en cuenta la desortogonalidad, de modo que el archivo de cámara queda de la siguiente manera:
Acabamos de implementar la primera novedad de la versión Beta 2016 de Digi3D.NET: Carga nativa de archivos de calibración de cámaras de Pix4D.
Si procesas un proyecto con Pix4D, éste crea un archivo de calibración de cámara cuyo nombre sigue el siguiente patrón: nombre_del_proyecto_pix4d_calibrated_internal_camera_parameters.cam. y dentro del archivo aparecen los parámetros de calibración de cámara.
Digi3D.NET ahora carga de forma nativa estos archivos e implementa el modelo matemático para corregir distorsiones con los parámetros especificados en el archivo. De esta manera puedes trabajar con cámaras no métricas utilizando el modelo preciso de corrección de distorsiones de Pix4D.
Puedes ver un vídeo mostrando esta característica en acción:
Acabamos de añadir una nueva funcionalidad a Digi3D.NET: hacer que memorice los parámetros del panel Propiedades de visualización de la ventana fotogramétrica.
A partir de ahora, cuando cambies algún valor en los controles de este panel, se memorizarán los parámetros y no tendrás que abrirlo otra vez a menos que quieras cambiarlos.
En el siguiente vídeo puedes ver en funcionamiento esta nueva funcionalidad.
¿Querías epipolares para mejorar las imágenes tomadas por drones?
Pues aquí tienes la solución: Con Digi3D.NET puedes calcular tres tipos de soluciones distintas para adaptar las imágenes y que restituirlas sea lo más cómo posible.
A partir de ahora en el menú Ventana fotogramétrica/Transformación de imágenes tiene tres opciones:
Epipolar (solución que modifica menos la foto izquierda).
Epipolar (solución que modifica menos la foto derecha).
Epipolar (solución que busca la mayor verticalidad).
Puedes ver esta nueva característica en el siguiente vídeo:
Llegó el día en el que Digi3D.NET puede realizar transformaciones de imágenes por hardware.
Hasta hoy (debido a la gran cantidad de usuarios con tarjetas gráficas con un núcleo como la nVidia Quadro FX1400) la aplicación realizaba las transformaciones geométricas por software.
Esta operación se realizaba utilizando todos los núcleos del ordenador para intentar hacerla lo más rápido posible, pero en la práctica tardaba un poco, por lo tanto decidimos en su momento cachear las teselas de las imágenes transformadas en la carpeta %TEMP% del ordenador.
Esto hacía que el espacio libre del disco duro fuera disminuyendo considerablemente hasta agotarlo (momento en el cual había que utilizar la herramienta de liberación de espacio de Windows o herramientas de terceros como CCleaner.
No podíamos continuar toda la vida soportando la tarjeta gráfica nVidia Quadro FX 1400, y ha llegado el momento de decirle adiós..
Publicamos hoy la nueva versión de Digi3D.NET con transformaciones en la tarjeta. Esta versión requiere tarjetas gráficas con más de un núcleo. A partir de ahora, mientras mejor sea nuestra tarjeta gráfica, mejor rendimiento tendrá Digi3D.NET.
Con este cambio hacemos que el programa no sea compatible con ordenadores antiguos (hace un año Microsoft dejó de soportar Windows XP, y el 99% de los ordenadores equipados con una Quadro FX 1400 tienen Windows XP), pero el programa gana muchísimo en especificaciones.
Hemos realizado los siguientes cambios:
Las transformaciones (rotar en kappa, epipolares, etc) son instantáneas y sin consumir ni un solo byte en el disco duro. Ahora al programa le cuesta lo mismo mostrar las imágenes transformadas u originales.
Ahora podemos activar y desactivar (viene activado por defecto) la opción de interpolar bilinealmente los píxeles a la hora de visualizar las imágenes. Esto hace que los píxeles de la imagen dejen de apreciarse al hacer zooms de acercar.
Ahora el programa memoriza las transformaciones de cada una de las imágenes cuando cerramos la ventana fotogramétrica, de modo que si abrimos un modelo y ordenamos que se calcule su epipolar, al volver a abrir ese modelo en particular, las imágenes ya estarán orientadas con la epipolar.
Nuevas opciones para calcular epipolares (la que menos transforma la imagen izquierda, la que menos transforma la imagen derecha y la que conserva la mayor verticalidad).
Se ha eliminado la opción de Método de Brillo/Contraste por software. Ahora es siempre por hardware.
Se han realizado mejoras a la hora de proyectar las geometrías del archivo de dibujo en la ventana fotogramétrica. Ahora no es necesario mover la ventana fotogramétrica para que aparezcan las geometrías.
Puedes ver esta nueva funcionalidad en el siguiente vídeo