Download Desarrollo de una librería para acceder a ArUco desde Java

Document related concepts
no text concepts found
Transcript
UNIVERSIDAD DE CÓRDOBA
E SCUELA P OLITÉCNICA
SUPERIOR
Ingeniería en Informática
PROYECTO DE FIN DE CARRERA
Desarrollo de una librería para
acceder a ArUco desde Java
M ANUAL T ÉCNICO
Autor: José Carlos Garrido Pérez
Director: Prof. Rafael Muñoz Salinas
Córdoba, 8 de septiembre de 2014
UNIVERSIDAD DE CÓRDOBA
E SCUELA P OLITÉCNICA
SUPERIOR
Ingeniería en Informática
PROYECTO DE FIN DE CARRERA
Desarrollo de una librería para
acceder a ArUco desde Java
M ANUAL T ÉCNICO
Autor: José Carlos Garrido Pérez
Director: Prof. Rafael Muñoz Salinas
Córdoba, 8 de septiembre de 2014
Prof. Rafael Muñoz Salinas, Profesor Titular de Universidad del área de Conocimiento de Ciencias de la Computación e Inteligencia Artificial y adscrito al Departamento
de Informática y Análisis Numérico de la Universidad de Córdoba,
INFORMA
Que el presente Proyecto de Fin de Carrera de Ingeniería en Informática, titulado
Desarrollo de una librería para acceder a ArUco desde Java, ha sido realizado, bajo
su dirección, por José Carlos Garrido Pérez, reuniendo, a su juicio, las condiciones
exigidas en este tipo de trabajos.
Y para que conste, firma el presente informe en Córdoba, a día 8 de septiembre
de 2014
EL DIRECTOR
EL ALUMNO
Rafael Muñoz Salinas
José Carlos Garrido Pérez
A mi hermano y a mis padres
Índice de contenidos
Índice de contenidos
I
Índice de tablas
V
Índice de figuras
VII
1. Introducción y objetivos
1
1.1. Presentación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1.2. Problema real . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
1.3. Problema técnico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
1.3.1. Funcionamiento
. . . . . . . . . . . . . . . . . . . . . . . . . .
3
1.3.2. Entorno . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
1.3.2.1.
Interfaz con el usuario . . . . . . . . . . . . . . . . . .
4
1.3.2.2.
Entorno de programación . . . . . . . . . . . . . . . .
4
1.3.2.3.
Ambiente de ejecución . . . . . . . . . . . . . . . . .
4
1.3.2.4.
Vida esperada . . . . . . . . . . . . . . . . . . . . . .
4
1.3.2.5.
Ciclo de mantenimiento . . . . . . . . . . . . . . . . .
4
1.3.2.6.
Competencia . . . . . . . . . . . . . . . . . . . . . . .
5
1.3.2.7.
Aspecto externo . . . . . . . . . . . . . . . . . . . . .
5
1.3.3. Calidad y fiabilidad . . . . . . . . . . . . . . . . . . . . . . . . .
5
1.3.4. Programa de tareas . . . . . . . . . . . . . . . . . . . . . . . . .
5
1.3.5. Pruebas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
1.3.6. Seguridad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
1.4. Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
1.4.1. Objetivo principal . . . . . . . . . . . . . . . . . . . . . . . . .
7
1.4.2. Objetivos secundarios . . . . . . . . . . . . . . . . . . . . . . .
7
2. Antecedentes
9
2.1. Aplicaciones de Realidad Aumentada . . . . . . . . . . . . . . . . . . .
9
2.2. Visión Artificial: OpenCV . . . . . . . . . . . . . . . . . . . . . . . . .
13
2.3. Realidad Aumentada: librerías existentes . . . . . . . . . . . . . . . . . .
14
I
Índice de Contenidos
2.4. ArUco: visión general . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
2.4.1. Clase Board . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
2.4.2. Clase BoardConfiguration . . . . . . . . . . . . . . . . . . . . .
17
2.4.3. Clase BoardDetector . . . . . . . . . . . . . . . . . . . . . . . .
17
2.4.4. Clase CameraParameters . . . . . . . . . . . . . . . . . . . . . .
17
2.4.5. Clase CvDrawingUtils . . . . . . . . . . . . . . . . . . . . . . .
17
2.4.6. Clase FiducidalMarkers . . . . . . . . . . . . . . . . . . . . . .
18
2.4.7. Clase Marker . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
2.4.8. Clase MarkerCandidate . . . . . . . . . . . . . . . . . . . . . . .
18
2.4.9. Clase MarkerDetector . . . . . . . . . . . . . . . . . . . . . . .
18
2.4.10. Estructura MarkerInfo . . . . . . . . . . . . . . . . . . . . . . .
18
2.5. Programas de prueba de la librería ArUco . . . . . . . . . . . . . . . . .
18
2.5.1. arucoBoardPix2meters . . . . . . . . . . . . . . . . . . . . . . .
19
2.5.2. arucoCreateBoard . . . . . . . . . . . . . . . . . . . . . . . . .
19
2.5.3. arucoCreateMarker . . . . . . . . . . . . . . . . . . . . . . . . .
19
2.5.4. arucoSelectoptimalmarkers . . . . . . . . . . . . . . . . . . . . .
19
2.5.5. arucoSimple . . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
2.5.6. arucoSimpleBoard . . . . . . . . . . . . . . . . . . . . . . . . .
19
2.5.7. arucoTest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
2.5.8. arucoTestBoard . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
2.5.9. arucoTestBoardGl . . . . . . . . . . . . . . . . . . . . . . . . .
20
2.6. Librerías basadas en ArUco . . . . . . . . . . . . . . . . . . . . . . . . .
20
2.6.1. js-aruco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
2.7. Otros proyectos fin de carrera . . . . . . . . . . . . . . . . . . . . . . . .
20
2.7.1. Simulador gráfico de operaciones sobre ficheros . . . . . . . . . .
20
2.8. Justificación del proyecto . . . . . . . . . . . . . . . . . . . . . . . . . .
21
3. Restricciones y recursos
23
3.1. Factores iniciales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
3.2. Factores estratégicos . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
3.2.1. Entorno de desarrollo: NetBeans . . . . . . . . . . . . . . . . . .
24
3.2.2. Modo de acceso a las funciones de ArUco: JNI . . . . . . . . . .
24
3.3. Recursos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
25
3.3.1. Recursos de hardware . . . . . . . . . . . . . . . . . . . . . . .
25
3.3.1.1.
Recursos de hardware para el desarrollo . . . . . . . .
25
3.3.1.2.
Recursos de hardware para uso del programa . . . . . .
25
3.3.2. Recursos de software . . . . . . . . . . . . . . . . . . . . . . . .
25
3.3.3. Recursos humanos . . . . . . . . . . . . . . . . . . . . . . . . .
26
II
Índice de Contenidos
4. Especificación de requisitos
27
4.1. Requisitos funcionales . . . . . . . . . . . . . . . . . . . . . . . . . . .
5. Especificación del modelo de clases
27
29
5.1. Análisis de clases Java . . . . . . . . . . . . . . . . . . . . . . . . . . .
29
5.1.1. Clase Board . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
30
5.1.2. Clase BoardConfiguration . . . . . . . . . . . . . . . . . . . . .
32
5.1.3. Clase BoardDetector . . . . . . . . . . . . . . . . . . . . . . . .
35
5.1.4. Clase CameraParameters . . . . . . . . . . . . . . . . . . . . . .
38
5.1.5. Clase CvDrawingUtils . . . . . . . . . . . . . . . . . . . . . . .
41
5.1.6. Clase FiducidalMarkers . . . . . . . . . . . . . . . . . . . . . .
43
5.1.7. Clase Marker . . . . . . . . . . . . . . . . . . . . . . . . . . . .
45
5.1.8. Clase MarkerDetector . . . . . . . . . . . . . . . . . . . . . . .
49
5.1.9. Clase MarkerInfo . . . . . . . . . . . . . . . . . . . . . . . . . .
54
5.2. Análisis de los ficheros C++ del “wrapper” . . . . . . . . . . . . . . . .
55
5.2.1. Handle.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
56
5.2.2. JBoard.cpp y JBoard.h . . . . . . . . . . . . . . . . . . . . . . .
57
5.2.3. JBoardConfiguration.cpp y JBoardConfiguration.h . . . . . . . .
58
5.2.4. JBoardDetector.cpp y JBoardDetector.h . . . . . . . . . . . . . .
59
5.2.5. JCameraParameters.cpp y JCameraParameters.h . . . . . . . . .
60
5.2.6. JCvDrawingUtils.cpp y JCvDrawingUtils.h . . . . . . . . . . . .
62
5.2.7. JFiducidalMarkers.cpp y JFiducidalMarkers.h . . . . . . . . . . .
63
5.2.8. JMarker.cpp y JMarker.h . . . . . . . . . . . . . . . . . . . . . .
63
5.2.9. JMarkerDetector.cpp y JMarkerDetector.h . . . . . . . . . . . . .
65
5.2.10. JMarkerInfo.cpp y JMarkerInfo.h . . . . . . . . . . . . . . . . .
66
5.3. Análisis de los programas Java de ejemplo . . . . . . . . . . . . . . . . .
67
5.3.1. arucoCreateBoard . . . . . . . . . . . . . . . . . . . . . . . . .
67
5.3.2. arucoCreateMarker . . . . . . . . . . . . . . . . . . . . . . . . .
68
5.3.3. arucoSimple . . . . . . . . . . . . . . . . . . . . . . . . . . . .
69
5.3.4. arucoSimpleBoard . . . . . . . . . . . . . . . . . . . . . . . . .
70
6. Diagramas de secuencia
73
6.1. Creación de un objeto . . . . . . . . . . . . . . . . . . . . . . . . . . . .
73
6.2. Llamada a un método con modificación de parámetros . . . . . . . . . .
74
6.3. Llamada a un método que escribe en disco . . . . . . . . . . . . . . . . .
75
6.4. Llamada a un método que lee desde el disco . . . . . . . . . . . . . . . .
76
7. Diagrama de paquetes
79
7.1. Diagrama general de paquetes . . . . . . . . . . . . . . . . . . . . . . .
III
81
Índice de Contenidos
8. Pruebas
8.1. Clases de Java . . . . . . . . . . . . . . . . . . . . . . .
8.2. “Wrapper” en C++ . . . . . . . . . . . . . . . . . . . .
8.3. Programas de prueba . . . . . . . . . . . . . . . . . . .
8.4. Pruebas de funcionamiento en varios sistemas operativos
.
.
.
.
83
84
87
89
89
9. Conclusiones y futuras mejoras
9.1. Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9.2. Futuras mejoras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
91
91
92
Bibliografía
93
IV
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Índice de tablas
2.1. Comparativa entre los antecedentes y el proyecto . . . . . . . . . . . . .
V
21
Índice de figuras
1.1. Ejemplo de funcionamiento de ArUco . . . . . . . . . . . . . . . . . . .
2
1.2. Logotipo de la librería de visión artificial OpenCV . . . . . . . . . . . .
2
1.3. Planificación temporal del proyecto fin de carrera . . . . . . . . . . . . .
6
2.1. Captura de pantalla de learnAR . . . . . . . . . . . . . . . . . . . . . . .
10
2.2. Captura de pantalla de Google Sky Map . . . . . . . . . . . . . . . . . .
10
2.3. Captura de pantalla de BlippAR . . . . . . . . . . . . . . . . . . . . . .
11
2.4. Captura de pantalla de Ingress . . . . . . . . . . . . . . . . . . . . . . .
12
2.5. Fotografía de un teléfono móvil ejecutando Word Lens . . . . . . . . . .
13
2.6. Coche autónomo Stanley . . . . . . . . . . . . . . . . . . . . . . . . . .
14
2.7. Logotipo de la librería de Realidad Aumentada ARLab . . . . . . . . . .
15
2.8. Ejemplo de un marcador de la librería de Realidad Aumentada GRATF . .
16
2.9. Tablero de marcadores de ArUco . . . . . . . . . . . . . . . . . . . . . .
17
2.10. Tutorial de GraFich . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21
5.1. Diagrama de clases de Board . . . . . . . . . . . . . . . . . . . . . . . .
32
5.2. Diagrama de clases de BoardConfiguration . . . . . . . . . . . . . . . .
35
5.3. Diagrama de clases de BoardDetector . . . . . . . . . . . . . . . . . . .
38
5.4. Diagrama de clases de CameraParameters . . . . . . . . . . . . . . . . .
41
5.5. Diagrama de clases de CvDrawingUtils . . . . . . . . . . . . . . . . . .
42
5.6. Diagrama de clases de Marker . . . . . . . . . . . . . . . . . . . . . . .
49
5.7. Diagrama de clases de MarkerDetector . . . . . . . . . . . . . . . . . . .
54
5.8. Diagrama de clases de MarkerInfo . . . . . . . . . . . . . . . . . . . . .
55
5.9. Imagen con el tablero resultado de arucoCreateBoard . . . . . . . . . . .
68
5.10. Marcador con el identificador 23 creado por arucoCreateMarker . . . . .
69
5.11. Imagen resultado de ejecutar arucoSimple . . . . . . . . . . . . . . . . .
70
5.12. Imagen resultado de ejecutar arucoSimpleBoard . . . . . . . . . . . . . .
71
6.1. Diagrama de secuencia del constructor de MarkerDetector . . . . . . . .
74
6.2. Diagrama de secuencia de la función detect de MarkerDetector . . . . . .
75
6.3. Diagrama de secuencia de la función saveToFile de Board . . . . . . . .
76
6.4. Diagrama de secuencia de la función readFromFile de Board . . . . . . .
77
VII
Índice de Figuras
7.1. Diagrama de paquetes de la librería . . . . . . . . . . . . . . . . . . . . .
VIII
81
Capítulo 1
Introducción y objetivos
1.1.
Presentación
El termino Realidad Aumentada, como suele ocurrir en ingeniería, tiene diferentes
definiciones. Algunas de ellas entienden la Realidad Aumentada como un caso particular
de Realidad Virtual, mientras que otras entienden que es justo lo contrario. Sin embargo,
es importante notar que, al contrario que ocurre en la Realidad Virtual, el entorno no es
completamente suprimido, sino que tiene un papel muy importante en la aplicación. De
hecho, es complementado con la información virtual[1]. Si se sigue con la comparación,
puede observarse fácilmente que es más complicado controlar un entorno real que un
entorno completamente sintético (como es el caso de la Realidad Virtual).
De manera general, puede entenderse que en la Realidad Aumentada se integra el entorno con la información sintética. Ha de existir una relación entre estos dos “mundos”
que, normalmente, es de tipo espacial. Para poder observar la información virtual sobre
el entorno real hemos de usar un expositor (por ejemplo una pantalla) y un software que
interprete los patrones o coordenadas del mundo real para poder situar en él la información virtual. Para localizar la escena en la que se encuentra el usuario puede utilizarse
una cámara o un sensor GPS. Entre las numerosas aplicaciones de la realidad aumentada
se encuentran la educación, accesibilidad o el ocio. Con aplicaciones que pueden desde
traducir carteles a nuestro idioma hasta crear un mundo virtual “superpuesto” con el real.
En el capítulo siguiente se comentarán algunos de estos ejemplos más en detalle.
Una vez se ha expuesto lo que es la Realidad Aumentada y se han mostrado algunos
ejemplos de su posible uso, se puede entender mejor el sentido de ArUco[7]. Dentro
de la Universidad de Córdoba se ha desarrollado esta librería que se presenta como una
librería de Realidad Aumentada minimalista basada en OpenCV[8] y cuyas principales
funcionalidades son la detección de marcadores y tableros de marcadores con una línea
de código en C++. Cuenta con la posibilidad de utilizar hasta 1024 marcadores distintos.
Lógicamente, también permite la creación de estos marcadores y tableros.
1
Capítulo 1. Introducción y objetivos
Además, la librería cuenta con varios ejemplos para que los usuarios menos expertos
puedan aprender a trabajar con ella. La aplicación anteriormente comentada, learnAR,
utiliza un sistema basado en marcadores como el que se puede crear usando ArUco, por
lo que aplicaciones similares podrían ser desarrolladas usando la librería cordobesa. A
continuación, se muestra una imagen en la que se puede apreciar un tablero con varios
marcadores que han sido detectados mediante el uso de ArUco:
Figura 1.1: Ejemplo de funcionamiento de ArUco
Esta librería ha sido desarrollada en C++ utilizando OpenCV y puede ser utilizada
solamente en programas desarrollados en ese lenguaje. OpenCV es una librería de visión
artificial bajo licencia BSD. En los últimos años, los sistemas de visión artificial están
desarrollándose a gran velocidad y con aplicaciones tan variadas e interesantes como el
reconocimiento facial, el reconocimiento óptico de caracteres, la búsqueda en imágenes,
los coches autónomos, la robótica, etc. La visión artificial es un campo que permite a un
computador adquirir, procesar y analizar imágenes con el objetivo de que “entienda” las
imágenes que se le están proporcionando.
Figura 1.2: Logotipo de la librería de visión artificial OpenCV
2
Capítulo 1. Introducción y objetivos
El lenguaje de programación Java[9] es un lenguaje de programación orientado a objetos, cuya sintaxis está basada en C y C++. Este lenguaje es normalmente interpretado,
aunque también puede ser compilado. En el caso de la interpretación, Java es una de las
alternativas multi-plataforma más extendidas hasta ahora. Además, permite la creación de
“applets” que pueden ser integrados en páginas web, por lo que supuso una “revolución”
en Internet ya que hasta su aparición sólo se podía ver en internet el contenido generado
por HTML, el cual es un lenguaje bastante pobre en lo que a cálculo se refiere y que sólo
está pensado para dar formato al texto e imágenes que vemos en una web, así como para
enlazar unas páginas con otras.
Por estos factores se encuentra una necesidad de poder acceder a la librería ArUco
desde el lenguaje de programación Java, con el objetivo de llegar a un mayor número de
programadores y usuarios, contar con programas con una mayor portabilidad y poder ser
utilizados en “applets” en internet. Existen diversas formas de acceder a código nativo
desde Java siendo JNI una de las más utilizadas y documentadas en la actualidad, por lo
que se tiene en cuenta esta tecnología para realizar este proyecto.
1.2.
Problema real
El problema real que se desea resolver con el desarrollo del presente proyecto de
fin de carrera es el siguiente: la librería ArUco goza de popularidad en el mundo de la
informática y se está utilizando con lenguajes como C y C++. Sin embargo, el lenguaje
Java es muy utilizado en todo el mundo y tiene la gran ventaja de ser multiplataforma, por
lo que se estima necesario la creación de un wrapper para poder acceder a las funciones
de ArUco desde código escrito en Java.
Además de realizar el wrapper se entiende como necesaria la creación de algunos
programas de ejemplo cuyo objetivo será tanto didáctico como demostrativo del funcionamiento de la librería.
1.3.
Problema técnico
1.3.1.
Funcionamiento
La librería ha de ofrecer las siguientes posibilidades:
Creación de marcadores
Creación de tableros
Detección de marcadores
Detección de tableros
3
Capítulo 1. Introducción y objetivos
Funciones que permitan dibujar señales que demuestren el reconocimiento de los
marcadores y tableros, tales como sus bordes, identificadores, ejes tridimensionales,
etc.
Utilidades que demuestren el funcionamiento y uso de las funciones anteriormente
comentadas
Ser utilizada en programas realizados con lenguaje Java
La ejecución de las funciones ha de realizarse en lenguaje nativo
1.3.2.
Entorno
1.3.2.1.
Interfaz con el usuario
Dado que esta librería está dirigida a profesionales del mundo de la informática que
ya han de contar con unos conocimientos previos la interfaz con el usuario será lo más
parecida a la librería ArUco posible.
1.3.2.2.
Entorno de programación
El programa va a ser realizado en el entorno de programación NetBeans en su versión
7.3.1, que es de gran utilidad, dadas las herramientas de las que provee al programador,
tales como depurador de código, realce de sintaxis, fácil navegación, etc.
1.3.2.3.
Ambiente de ejecución
Al ser una librería desarrollada en lenguaje Java se espera que sea ejecutada en cualquier máquina que cuente con la Máquina Virtual de Java SE.
1.3.2.4.
Vida esperada
Se espera que cuente con una vida esperada que vaya desde media a larga aunque,
lógicamente, nuestro objetivo sería que la librería tuviera una vida tan larga como la utilización de técnicas de Realidad Aumentada. Sin embargo, con el avance de la informática,
es lógico pensar que estas técnicas mejorarán o se crearán otras nuevas y que estos futuros
cambios deberían ser incluidos en nuestra librería para que siguiera siendo utilizada. Por
otra parte, el uso y la prueba de la librería pondrán de manifiesto necesidades de mejora
que tendrán que ser resueltas en el futuro.
1.3.2.5.
Ciclo de mantenimiento
La librería que se pretende desarrollar será fruto de un Proyecto Fin de Carrera y, por
tanto, su autor no será responsable de su mantenimiento en el futuro. Sin embargo, se va
4
Capítulo 1. Introducción y objetivos
a utilizar un diseño de clases y elaborar una documentación que facilitará revisiones y
ampliaciones en el futuro.
1.3.2.6.
Competencia
En el capítulo Antecedentes, se nombran algunas de las librerías de realidad aumentada existentes en la actualidad. Cabe resaltar que pocas pueden utilizarse con el lenguaje
Java sin ser de pago.
1.3.2.7.
Aspecto externo
El soporte utilizado para el transporte y distribución del software será CD-R. Este
soporte contendrá instrucciones para su instalación, uso, funcionamiento, ejecución, etc.
Por supuesto, también contendrá la librería y los programas de ejemplo. Además, se podrá
descargar un paquete desde internet con el mismo contenido.
1.3.3.
Calidad y fiabilidad
Es muy importante maximizar la calidad de nuestra librería, porque esta característica
está muy demandada hoy en día. Por esta razón, vamos a utilizar herramientas para la
creación del software que ya están contrastadas a nivel mundial, tales como NetBeans
y la Máquina Virtual de Java. En cuanto a la fiabilidad, será maximizada gracias a las
pruebas a las que será sometida la librería para intentar minimizar la cantidad de errores
que puedan ocurrir por haber tenido fallos en el diseño, la planificación o la codificación.
1.3.4.
Programa de tareas
La estimación de tiempos para las tareas es la siguiente:
Estudio del problema: aunque durante todo el proyecto se continuará con el estudio
del problema y los lenguajes utilizados se estima que habría que dedicar unas dos
semanas al inicio del proyecto para poder comenzar a trabajar.
Análisis y diseño: una vez realizado el estudio del problema se estima que habría
que dedicar unas tres semanas a tareas de análisis y diseño.
Implementación: se estima que esta fase puede durar unas doce semanas, realizando
tareas de las dos siguientes fases también.
Pruebas: aunque se irán realizando pruebas a medida que se realice la implementación, se estima que deberían dedicarse unas dos semanas a las pruebas.
5
Capítulo 1. Introducción y objetivos
Documentación: se irá realizando documentación durante todo el proyecto pero se
dedicarán unas dos semanas al final a la realización de esta tarea mientras se realizan
las últimas pruebas.
Teniendo en cuenta que algunas de las actividades pueden intercalarse se considera
que la duración del proyecto puede ser cercana a las 18 semanas si se entiende que se
tendrá una dedicación total al mismo. En el siguiente diagrama se muestra la planificación
temporal:
Figura 1.3: Planificación temporal del proyecto fin de carrera
1.3.5.
Pruebas
Se deberá realizar una fase de pruebas, entre las que se encuentran las siguientes:
Pruebas de unidad: pruebas de las clases por separado.
Pruebas de integración: pruebas que recaerán sobre la unión de las distintas clases
de la aplicación.
Pruebas del software: pruebas de funcionamiento de la librería una vez terminada.
Pruebas del sistema: se probará la comunicación y cohesión de la librería con el
soporte de hardware y el sistema operativo.
La descripción de cada prueba deberá incluir:
El objetivo de la prueba.
El problema detectado, si lo hay.
La solución adoptada, en su caso.
El capítulo de Pruebas informará sobre las pruebas realizadas a la librería informática
desarrollada.
6
Capítulo 1. Introducción y objetivos
1.3.6.
Seguridad
Se ha de garantizar la seguridad, tanto sobre el hardware en el que se ejecute la librería,
como sobre el software (Sistema Operativo y otros programas) que se encuentre instalado
en él. La seguridad es un aspecto muy importante hoy en día. Se intentará controlar lo
máximo posible las operaciones que puedan suponer un problema para la seguridad del
sistema informático en el que se ejecute nuestra librería. Algunas de estas operaciones
son: las lecturas o escrituras en el disco duro, el acceso a memoria, las violaciones de
segmento, etc. La librería se diseñará y codificará teniendo en cuenta que debe controlar
estas operaciones para que no afecten a la estabilidad del sistema.
En cuanto a la licencia del producto, el software que se desarrollará se establece como
una librería totalmente libre de distribución, copia y uso, debido a su carácter estrictamente académico; es por eso que carece de cualquier ánimo de lucro o carácter privativo,
no existiendo protección contra su libre distribución. Para evitar cualquier acción malintencionada ligada con la copia o la reproducción total o parcial, así como cualquier remuneración económica por su distribución, la aplicación se atiene a la licencia GPL de
GNU.
1.4.
Objetivos
1.4.1.
Objetivo principal
El objetivo principal del presente proyecto de fin de carrera es realizar un wrapper
mediante JNI que permita utilizar las funciones de la librería ArUco desde Java.
1.4.2.
Objetivos secundarios
El objetivo principal del proyecto se puede descomponer en los siguientes objetivos
secundarios:
Realizar una librería con las siguientes características:
• Posibilidad de ser utilizada en Java.
• Posibilidad de ofrecer las mismas funcionalidades que ArUco, siendo las más
importantes:
◦ Creación de marcadores
◦ Creación de tableros
◦ Detección de marcadores
◦ Detección de tableros
7
Capítulo 1. Introducción y objetivos
◦ Funciones que permitan dibujar señales que demuestren el reconocimiento de los marcadores y tableros, tales como sus bordes, identificadores,
ejes tridimensionales, etc.
• La ejecución del código debe realizarse en lenguaje nativo, directamente en la
propia ArUco.
• La librería ha de venir acompañada con varios ejemplos que muestren su utilidad y funcionamiento, con el objetivo de que puedan ser utilizados con una
función didáctica.
• Como resultado final debe obtenerse tanto una librería para sistemas Linux
como para sistemas Windows.
8
Capítulo 2
Antecedentes
2.1.
Aplicaciones de Realidad Aumentada
Para tomar mayor consciencia de la Realidad Aumentada y las aplicaciones que tiene
se han descargado y ejecutado algunas aplicaciones de diferentes ámbitos. Ejemplos de
ello son las siguientes:
Educación: añadir información virtual a una escena real abre muchas posibilidades
en cuanto al aprendizaje. Existen ya ejemplos bastante interesantes de ello como
los que se detallan a continuación:
• learnAR[2]: es una herramienta de aprendizaje que utiliza la realidad aumentada para convertir la experiencia de aprendizaje en interactiva. Contiene diversos paquetes que van desde los idiomas hasta la geometría, pasando por la
biología o la química. Esta aplicación utiliza la detección de marcadores para mostrar los elementos virtuales en pantalla. En la siguiente imagen puede
apreciarse cómo detecta un marcador para mostrar, sobre una imagen real, los
órganos de manera virtual:
9
Capítulo 2. Antecedentes
Figura 2.1: Captura de pantalla de learnAR
• Google Sky Map[3]: con esta aplicación gratuita se pueden obtener conocimientos de astronomía. Permite conocer el nombre de estrellas, planetas y
constelaciones, además de ayudar a buscar en el cielo las estrellas o planetas
que nos interesen gracias a su función de búsqueda, que sepuede apreciar en
la siguiente imagen:
Figura 2.2: Captura de pantalla de Google Sky Map
Publicidad: es un campo en el que se están produciendo muchos desarrollos. Ya
existen aplicaciones capaces de mostrar un trailer de una película simplemente si se
10
Capítulo 2. Antecedentes
enfoca un cartel de la misma con la cámara del móvil o mostrar un modelo 3D de
un reloj y permitir colocarlo virtualmente en la muñeca del usuario si se enfoca un
anuncio del mismo. Algunos ejemplos de este tipo de aplicaciones son:
• blippAR [4]: esta aplicación está disponible para Android, iOS y Windows
Phone. Su objetivo es el de ofrecer contenido adicional y exclusivo cuando
se enfocan con la cámara determinados objetos que pueden ir desde carteles
promocionales hasta productos reales. En la captura siguiente se muestra la
detección de una botella de ketchup de una marca determinada y la adición de
contenido virtual, en este caso, un libro de recetas:
Figura 2.3: Captura de pantalla de BlippAR
Ocio: la industria del ocio en la informática está creciendo muchísimo en los últimos años, generando más ingresos que industrias como el cine. Aparecen nuevas oportunidades para jugar y divertirse gracias a la realidad aumentada. Algunos
ejemplos de juegos actuales son los siguientes:
11
Capítulo 2. Antecedentes
• Ingress[5]: en este juego creado por Google se hace uso de la realidad aumentada mediante posicionamiento GPS. Los jugadores pueden elegir entre
dos facciones y han de moverse a localizaciones reales donde se encuentran
“portales” virtuales que deben controlar. A continuación puede observarse una
captura de pantalla de este juego en la que se observa un portal en la plaza de
toros de Córdoba:
Figura 2.4: Captura de pantalla de Ingress
Accesibilidad: gracias a la información adicional que ofrece la realidad aumentada
se pueden crear utilidades que permitan mejorar la accesibilidad en los entornos en
los que sea necesario. Ejemplos de este tipo de aplicación de la Realidad Aumentada
son:
• Word Lens[6]: esta aplicación permite traducir carteles de unos idiomas a
otros. Es especialmente útil si se viaja a una zona sin conocer el idioma y
cuenta con idiomas como inglés, italiano, alemán, portugués, ruso y español.
Necesita buena iluminación y no detecta texto manuscrito o muy estilizado. A
12
Capítulo 2. Antecedentes
continuación, puede observarse un ejemplo de su funcionamiento:
Figura 2.5: Fotografía de un teléfono móvil ejecutando Word Lens
2.2.
Visión Artificial: OpenCV
Para poder añadir información virtual en un entorno real se ha de identificar de alguna manera la situación espacial del entorno. Aunque existen librerías y aplicaciones
que utilizan el posicionamiento GPS en este proyecto se tiene interés por las aplicaciones de Realidad Aumentada que utilizan marcadores. Por esta razón, para poder añadir
información virtual sobre los marcadores primero hay que detectarlos.
El objetivo de usar una librería de Visión Artificial no es otro que el de poder detectar
los elementos gráficos (en este caso marcadores y tableros) que nos interesan. Por esta razón, la librería ArUco utiliza funciones de OpenCV para adquirir y procesar las imágenes
que recibe, con el objetivo de identificar los marcadores que estas imágenes contengan.
OpenCV está liberada bajo licencia BSD por lo que es libre tanto para uso académico
como comercial. Tiene interfaces en C++, C, Python y Java (lo cual es interesante para
este proyecto) y está soportado en sistemas Windows, Linux, Mac OS, iOS y Android.
Esta librería es ampliamente utilizada en el mundo de la Visión Artificial y cuenta
con gran cantidad de documentación (libros, tutoriales, guías de uso, documentación de
13
Capítulo 2. Antecedentes
la API, etc). Además de la Realidad Aumentada, esta y otras librerías de Realidad Aumentada tienen áreas de aplicación tales como las siguientes:
Sistemas de reconocimiento facial
Interacción hombre-máquina
Robótica
Identificación de objetos
Segmentación y reconocimiento de imágenes
Comprensión y seguimiento de movimiento
A continuación, se muestra una imagen del vehículo Stanley1 que es un coche autónomo creado por la Universidad de Stanford que ganó la competición DARPA Grand
Challenge de vehículos autónomos en 2005. Este coche utilizaba OpenCV para sus labores de Visión Artificial.
Figura 2.6: Coche autónomo Stanley
2.3.
Realidad Aumentada: librerías existentes
Como ya se comentó en la introducción, la Realidad Aumentada permite combinar
tanto la información real del entorno como información virtual mediante distintos sistemas tales como reconocimiento de patrones e imágenes o posicionamiento GPS.
1 “Stanley2”.
Licensed under Public domain via Wikimedia Commons - http://commons.
wikimedia.org/wiki/File:Stanley2.JPG\#mediaviewer/File:Stanley2.JPG
14
Capítulo 2. Antecedentes
Para poder realizar aplicaciones que utilicen estas posibilidades con un objetivo concreto existen distintas librerías que los programadores pueden utilizar. Algunas de estas
librerías se detallan a continuación:
ARToolKit[10]: es una librería de Realidad Aumentada mediante patrones. Permite
posicionar y orientar la cámara con respecto a los marcadores y posicionar objetos
3D sobre los mismos. El lenguaje que se ha de usar con esta libería es C, aunque
también permite otros lenguajes como Java o Matlab. Aunque esta librería está
disponible para Java, la mentablemente está algo desactualizada ya que su última
versión es para Windows XP. Su licencia es GNU/GPL.
ARLab[11]: es un SDK de Realidad Aumentada que ofrece opciones muy diversas
tales como Realidad Aumentada mediante geolocalización, reconocimiento y seguimiento de imágenes, seguimiento de objetos, botones virtuales y un motor 3D.
Es de pago y permite desarrollos tanto para Android como para iOS.
Figura 2.7: Logotipo de la librería de Realidad Aumentada ARLab
droidAR[12]: es un marco de trabajo para utilizar realidad aumentada en Android.
Las posibilidades que ofrecen son tanto la detección de patrones como el uso de
geolocalización. Inicialmente fue desarrollado por Simon Heinen en 2010 y ahora
es desarrollado por la comunidad y está liberado bajo licencia GNU GPL v3.
GRATF[13]: su objetivo es el de ofrecer una librería que haga reconocimiento y
estimación de la posición de marcadores dentro de imágenes o vídeos. El lenguaje
de programación de esta librería es C#. A continuación se muestra un marcador de
esta librería.
15
Capítulo 2. Antecedentes
Figura 2.8: Ejemplo de un marcador de la librería de Realidad Aumentada GRATF
ArUco[7]: una librería de Realidad Aumentada minimalista basada en OpenCV
y cuyas principales funcionalidades son la detección de marcadores y tableros de
marcadores con una línea de código en C++. Cuenta con la posibilidad de utilizar
hasta 1024 marcadores distintos. Lógicamente, también permite la creación de estos
marcadores y tableros. El lenguaje de esta librería es C++.
2.4.
ArUco: visión general
Ya que la librería de este Proyecto Fin de Carrera accederá a la de ArUco vamos a
comentar brevemente sus distintas clases.
Clase Board (definida en board.h)
Clase BoardConfiguration (definida en board.h)
Clase BoardDetector (definida en boarddetector.h)
Clase CameraParameters (definida en cameraparameters.h)
Clase CvDrawingUtils (definida en cvdrawingutils.h)
Clase FiducidalMarkers (definida en arucofidmarkers.h)
Clase Marker (definida en markers.h)
Clase MarkerCandidate (definida en markerdetector.h)
Clase MarkerDetector (definida en markerdetector.h)
Estructura MarkerInfo (definida en board.h)
16
Capítulo 2. Antecedentes
2.4.1.
Clase Board
La clase Board representa un tablero con varios marcadores. Un tablero contiene varios marcadores para que sean detectados de manera más robusta. Esta clase hereda de la
clase vector cuyos elementos son de tipo Marker. A continuación, puede observarse un
tablero de marcadores:
Figura 2.9: Tablero de marcadores de ArUco
2.4.2.
Clase BoardConfiguration
Esta clase, que es amiga de la clase Board, hereda de la clase vector de elementos
MarkerInfo. Guarda la configuración de un tablero.
2.4.3.
Clase BoardDetector
Esta clase sirve para detectar los tableros de ArUco. Cuenta con la función detect que
puede detectar el tablero que se encuentre en la imagen que se le pasa como parámetro.
2.4.4.
Clase CameraParameters
Representa la clase en la que se guardan los parámetros de la cámara. Estos parámetros
son la matriz de la cámara, el coeficiente de distorsión y el tamaño de la imagen.
2.4.5.
Clase CvDrawingUtils
Son un conjunto de funciones para dibujar sobre las imágenes mediante OpenCV.
Permite dibujar ejes y cubos en tres dimensiones sobre los tableros y marcadores.
17
Capítulo 2. Antecedentes
2.4.6.
Clase FiducidalMarkers
En esta clase se encuentran diversos métodos para crear imágenes con marcadores y
tableros.
2.4.7.
Clase Marker
Esta clase representa un marcador. Es un vector de las cuatro esquinas del marcador
(puntos Point2f de OpenCV).
2.4.8.
Clase MarkerCandidate
Esta clase representa un candidato a ser marcador y hereda de Marker.
2.4.9.
Clase MarkerDetector
Es la clase principal para la detección de marcadores. Su método más importante es
detect, que recibe entre sus parámetros una imagen de tipo Mat de OpenCV y devuelve
un vector con los marcadores encontrados en ella.
2.4.10.
Estructura MarkerInfo
Esta estructura contiene la representación 3D de un marcador. Hereda de la clase
vector de puntos tridimensionales de OpenCV Point3f.
2.5.
Programas de prueba de la librería ArUco
La librería ArUco cuenta con unos programas (cuyo código incluye) para poder observar y entender mejor el funcionamiento de la librería, además de comprobar la correcta
instalación de todos sus elementos. Algunas de estas utilidades son las siguientes:
arucoBoardPix2meters
arucoCreateBoard
arucoCreateMarker
arucoSelectoptimalmarkers
arucoSimple
arucoSimpleBoard
arucoTest
18
Capítulo 2. Antecedentes
arucoTestBoard
arucoTestBoardGl
2.5.1.
arucoBoardPix2meters
Este programa convierte un fichero que contenga una configuración de tablero (BoardConfiguration expresado en píxeles en otro expresado en metros.
2.5.2.
arucoCreateBoard
Esta utilidad crea una imagen con un tablero cuyo aspecto viene dado por los parámetros que se le indican por línea de comandos.
2.5.3.
arucoCreateMarker
Con esta aplicación se puede crear un marcador cuyo aspecto viene dado por los parámetros que se le indican por línea de comandos.
2.5.4.
arucoSelectoptimalmarkers
El objetivo de este programa es seleccionar los n mejores marcadores en base a la
distancia Hamming entre sí. Posteriormente, los guarda en una imagen.
2.5.5.
arucoSimple
Este programa realiza la detección de marcadores en una imagen o en un vídeo que
recibe como entrada. Para cada marcador, dibuja sus bordes y los muestra por pantalla. En
caso de haber información de 3D (parámetros de la cámara) dibuja un cubo 3D en cada
marcador.
2.5.6.
arucoSimpleBoard
Esta aplicación es similar a la anterior pero, además de detectar los marcadores, detecta el tablero que los contiene.
2.5.7.
arucoTest
Este programa detecta en tiempo real los marcadores que encuentra en un vídeo o a
través de la cámara web del ordenador.
19
Capítulo 2. Antecedentes
2.5.8.
arucoTestBoard
Este programa detecta en tiempo real los marcadores y el tablero que encuentra en un
vídeo o a través de la cámara web del ordenador.
2.5.9.
arucoTestBoardGl
Este programa detecta en tiempo real los marcadores y el tablero que encuentra en un
vídeo o a través de la cámara web del ordenador. Utiliza OpenGL para dibujar.
2.6.
Librerías basadas en ArUco
2.6.1.
js-aruco
Js-aruco[14] es una librería de Javascript para aplicaciones de realidad aumentada
basada totalmente en la librería ArUco. Es de código abierto y realizado por Juan Mellado
en el año 2011. Ofrece acceso a la webcam mediante Flash y detección de marcadores,
además de estimación de la pose en tres dimensiones. No permite la creación y detección
de tableros.
2.7.
Otros proyectos fin de carrera
2.7.1.
Simulador gráfico de operaciones sobre ficheros
Autor: José Carlos Garrido Pérez
Director: Dr. Nicolás Luis Fernández García
Presentado en: diciembre de 2011
Descripción: al igual que el presente proyecto, utiliza el lenguaje Java dado que su
objetivo era poder ser ejecutado tanto en Linux como en Windows. Se ha utilizado
como guía para algunas partes de la documentación por ser del mismo autor que
el presente proyecto. Es una aplicación con el objetivo de mostrar de manera gráfica y didáctica a los alumnos el funcionamiento de las distintas organizaciones de
ficheros (apilo, indexada, árboles, hashing, etc.).
La aplicación resultante de este proyecto se denomina GraFich y se puede observar la
apariencia del tutorial de estructuras de ficheros a continuación:
20
Capítulo 2. Antecedentes
Figura 2.10: Tutorial de GraFich
2.8.
Justificación del proyecto
Como se ha mostrado anteriormente, existen pocas alternativas en cuanto a librerías
de Realidad Aumentada no privativas que puedan ser usadas en Java. Además, la librería
ArUco ya cuenta con una cantidad de usuarios importante y se considera necesario intentar aumentar este número de usuarios ofreciendo la alternativa de programar en Java
sus aplicaciones con ArUco. Además, se desea que esta librería funcione en sistemas tanto Linux como Windows (en versiones recientes como Windows 7), por lo que no se ha
encontrado librería que cumpla con todos los requisitos. A continuación, se muestra un
cuadro con las necesidades que se pretenden cubrir:
Características
Creación de marcadores
Creación de tableros
Detección de marcadores
Detección de tableros
Programación en Java
Licencia libre
Ejec. en Linux y Windows rec.
ARToolKit
X
X
Librería
ARLab DroidAR
X
X
X
X
X
GRATF
X
X
X
X
X
Tabla 2.1: Comparativa entre los antecedentes y el proyecto
21
Proyecto
X
X
X
X
X
X
X
Capítulo 3
Restricciones y recursos
Para desarrollar la aplicación planteada, se van a tener en cuenta una serie de restricciones que nos harán tomar decisiones para llegar a desarrollar un programa de la calidad
esperada para un proyecto fin de carrera, acorde con las necesidades de los usuarios.
Se consideran dos tipos de factores en las restricciones:
Factores iniciales
Factores estratégicos
3.1.
Factores iniciales
Para el desarrollo del proyecto se consierarán los siguientes factores dato:
Utilización de la librería ArUco: la definición del proyecto hace referencia a la
utilización de esta librería para la detección de marcadores y tableros.
Utilización del lenguaje de programación Java: la definición del proyecto hace referencia a la utilización de este lenguaje de programación. El objetivo es poder
ampliar el número de usuarios gracias a la popularidad de Java y también poder
realizar una librería que funcione tanto en sistemas Linux como Windows.
3.2.
Factores estratégicos
A lo largo del proceso de desarrollo de este proyecto se han planteado diferentes
alternativas que nos han hecho tomar decisiones con el objeto de seleccionar las opciones
que mejor se adapten a los objetivos. Estas decisiones conforman los factores estratégicos
del proyecto que se describen a continuación:
Entorno de desarrollo: NetBeans
Modo de acceso a las funciones de ArUco: JNI
23
Capítulo 3. Restricciones y recursos
3.2.1.
Entorno de desarrollo: NetBeans
Las dos alternativas más importantes que se han barajado en la elección para el entorno
de desarrollo son las siguientes:
NetBeans: es un entorno de desarrollo multiplataforma cuyo código ha sido escrito
en Java. Es ampliamente utilizado para desarrollar programas en Java. Este proyecto
de código abierto fue fundado por Sun Microsystems en el año 2000. Cuenta con
diferentes módulos que pueden añadirse para programar en otros lenguajes o tener
características especiales.
Eclipse: al igual que NetBeans es un entorno de desarrollo multiplataforma y de
código abierto. Eclipse contiene un editor de texto avanzado, su propio depurador
de código y un intérprete propio de lenguaje Java.
Ambos entornos de programación cuentan con las siguientes ventajas:
Resaltado de sintaxis del lenguaje Java con diferentes colores según si el texto es un
tipo de variable, clase, cadena de texto, etc., lo que es muy útil para evitar errores
al escribir el código.
Un mecanismo mediante el cual, al escribir el nombre de una clase, puedes ver una
lista de los métodos que contiene, de manera que ayuda al programador a llamar a
uno de ellos.
Permite ejecutar applets sin necesidad de utilizar un navegador externo.
Un mecanismo de gestión de variables que revisa el ámbito de cada una, su valor
predeterminado, o las referencias a la misma antes y después de su declaración.
Después de este análisis y algunas pruebas, se ha decidido que el entorno de desarrollo
a utilizar sea NetBeans debido a que se ha encontrado más facilidad para utilizar JNI en
este sistema.
3.2.2.
Modo de acceso a las funciones de ArUco: JNI
Para poder realizar llamadas al código nativo de la librería existían las siguientes alternativas:
Volver a escribir la librería: esta opción alargaría la duración del proyecto y no se
tendría garantía de poder conseguir un resultado mejor. Además, las funciones de
ArUco en C++ ya han sido utilizadas, probadas y depuradas por muchos programadores por lo que usar el código nativo se ha considerado una opción interesante.
24
Capítulo 3. Restricciones y recursos
JNA: esta opción es más simple que JNI y funciona bien para C. Sin embargo, según
el estudio realizado se dificulta el uso de clases C++ con este sistema, cosa que sí
que permite JNI.
JNI: su manejo es algo más complejo que JNA pero ofrece buenas soluciones para
mapear las clases y según los articulos consultados realiza una gestión de memoria
más eficiente.
3.3.
Recursos
3.3.1.
Recursos de hardware
3.3.1.1.
Recursos de hardware para el desarrollo
Ordenador personal portátil Sony Vaio VCPEH2M0E:
• Chipset de la placa base: Intel HM65 Express
• CPU Intel Core i5-2430M
• Memoria 4 GB DDR3 1333 MHz
• Disco Duro 750GB SATA 5400 RPM
• Pantalla VAIO Display 15,5"Panorámica (16:9) WXGA de 1366 x 768
• VGA NVIDIA GeForce 410M GPU con 1 GB VRAM
Impresora láser Xerox Phaser 6000
3.3.1.2.
Recursos de hardware para uso del programa
Los requisitos que se establecen como mínimos y necesarios para que el programa
funcione, son los requisitos mínimos declarados por Sun Microsystems para que la Máquina Virtual de Java pueda funcionar correctamente.
3.3.2.
Recursos de software
Los programas que se han elegido para llevar a cabo este proyecto son:
Windows 7 Ultimate
Ubuntu 14.04
Netbeans: entorno de desarrollo que se utilizará para programar la aplicación
Máquina virtual de Java: versión de Java 1.7.0_55.
Kile 2.1.3: entorno del lenguaje LATEXpara la realización de los manuales.
25
Capítulo 3. Restricciones y recursos
3.3.3.
Recursos humanos
Dirección del proyecto: don Rafael Muñoz Salinas
Diseño y desarrollo: José Carlos Garrido Pérez
26
Capítulo 4
Especificación de requisitos
4.1.
Requisitos funcionales
Los requisitos funcionales representan todos los servicios que el sistema deberá proporcionar al usuario, además de cómo se comporta el sistema en cada una de las acciones
llevadas a cabo para rendir esos servicios. Los requisitos funcionales están denotados por
las letras RF, seguidas de un guión y un número de requisito que lo clasificará como único
en el sistema. Para la librería que se desea desarrollar, son los siguientes:
RF-1: Ha de poder ser utilizado en programas desarrollados en lenguaje Java.
RF-2: Ha de poder ser utilizado tanto en Linux como en Windows.
RF-3: La ejecución de las funciones ha de realizarse, siempre que sea posible, en la librería
ArUco (código nativo).
RF-4: Ha de permitir la creación de marcadores.
RF-5: Ha de permitir la detección de marcadores.
RF-6: Ha de permitir la creación de tableros.
RF-7: Ha de permitir la detección de tableros.
RF-8: Una vez detectados los marcadores ha de permitir que se dibujen sus bordes y se
muestre su identificador en las imágenes.
RF-9: Una vez detectados los marcadores ha de permitir dibujar los ejes de la escena sobre
ellos y un cubo en 3 dimensiones si se cuenta con la información necesaria.
RF-10: Una vez detectado el tablero ha de permitir dibujar los ejes de la escena sobre él y
un cubo en 3 dimensiones si se cuenta con la información necesaria.
27
Capítulo 4. Especificación de requisitos
RF-11: Ha de venir acompañado con algunas utilidades que demuestren el funcionamiento
de la librería y tengan un objetivo didáctico.
RF-12: Ha de venir acompañado de los archivos de ayuda necesarios para hacer accesible
su instalación y utilización a los programadores que quieran usarlo.
28
Capítulo 5
Especificación del modelo de clases
En este capítulo se va a especificar el modelo de clases de la librería en tres partes:
Análisis de clases Java: que son las clases que los programadores van a tener que
usar en su código y que están realizadas en el lenguaje de programación Java.
Análisis de los ficheros C++ del “wrapper”: donde se encuentran las funciones de
C++ que serán llamadas desde Java y que transformarán tanto los parámetros como
los resultados a tipos que el lenguaje que corresponda pueda procesar.
Análisis de los programas Java de ejemplo: con la librería se muestran algunos programas de ejemplo para poder entender mejor cómo funciona. También son analizados en este capítulo.
5.1.
Análisis de clases Java
Como se ha comentado se va a mostrar toda la información necsaria para poder utilizar
las clases Java de la librería que es objeto del presente proyecto fin de carrera. Estas clases
son listadas a continuación:
Clase Board
Clase BoardConfiguration
Clase BoardDetector
Clase CameraParameters
Clase CvDrawingUtils
Clase FiducidalMarkers
Clase Marker
29
Capítulo 5. Especificación del modelo de clases
Clase MarkerDetector
Clase MarkerInfo
5.1.1.
Clase Board
La clase Board representa un tablero con varios marcadores. Un tablero contiene varios marcadores para que sean detectados de manera más robusta. Esta clase cuenta con
el siguiente atributo privado:
nativeHandle: es un atributo de tipo long donde se guardará la dirección de memoria
del objeto Board ArUco que se cree y se asocie con este objeto Java.
Además, cuenta con la declaración de las siguientes funciones nativas privadas que tendrán que definirse en el fichero JBoard.cpp del wrapper de C++:
JBoard: llamará al constructor vacío de la clase Board de Aruco.
JBoard: llamará al constructor de copia de la clase Board de Aruco.
JsaveToFile: que llamará a la función saveToFile de la clase Board de Aruco.
JreadFromFile: que llamará a la función readFromFile de la clase Board de Aruco.
JglGetModelViewMatrix: que llamará a la función glGetModelViewMatrix de la
clase Board de Aruco. Eleva una excepción si los parámetros extrínsecos de la
cámara no son válidos.
JOgreGetPoseParameters: que llamará a la función OgreGetPoseParameters de la
clase Board de Aruco. Eleva una excepción si los parámetros extrínsecos de la
cámara no son válidos.
JgetRvec: que sirve para devolver una referencia al atributo Rvec de la clase Board
de Aruco. Recibe la referencia de un objeto de tipo Mat creado en Java para guardar
ahí la referencia al objeto Rvec de ArUco.
JgetTvec: que sirve para devolver una referencia al atributo Tvec de la clase Board
de Aruco. Recibe la referencia de un objeto de tipo Mat creado en Java para guardar
ahí la referencia al objeto Tvec de ArUco.
JgetBoardConf: que sirve para devolver el objeto conf de tipo BoardConfiguration
que es un atributo de la clase Board de Aruco.
Jget: que sirve para devolver un objeto Marker que se encuentra en el vector de
marcadores que es Board en la posición que se le pasa como parámetro.
30
Capítulo 5. Especificación del modelo de clases
Jsize: que sirve para devolver un entero con el tamaño del vector de marcadores que
es Board haciendo uso de la función Board.size() heredada de la clase vector.
Los métodos públicos de la clase Board son los siguientes:
Board: constructor vacío de la clase que, crea el objeto Board de Java, así como el
de ArUco y los enlaza escribiendo la dirección del segundo en nativeHandle. Todo
esto se hace mediante la llamada a la función de código nativo JBoard.
Board: constructor de copia de la clase. Recibe como parámetro un objeto de tipo
Board y crea otra instancia que es copia de la anterior. Hace uso de la función nativa
de constructor de copia JBoard.
glGetModelViewMatrix: esta función recibe como parámetro un vector cuyos elementos son de tipo double. Este vector, denominado modelview_matrix será pasado
como parámetro a la función nativa JglGetModelViewMatrix que se encargará de
rellenarlo. En caso de que haya algún problema en la obtención de estos datos se
elevará una excepción.
OgreGetPoseParameters: esta función recibe y rellena (haciendo uso de la función
nativa JOgreGetPoseParameters los siguientes parámetros:
• position: vector de elementos de tipo double.
• orientation: vector de elementos de tipo double.
En caso de que haya algún problema en la obtención de estos datos se elevará una
excepción.
saveToFile: esta función recibe un parámetro de tipo String de Java llamado filePath y lo pasa como parámetro a la función nativa JsaveToFile. El resultado de esta
llamada es que se grabará en el fichero indicado por filePath los datos correspondientes al tablero desde el que se llame. En caso de que haya algún problema con la
creación del fichero, lanzará una excepción informando de este hecho.
readFromFile: esta función recibe un parámetro de tipo String de Java llamado filePath y lo pasa como parámetro a la función nativa JreadFromFile. El resultado
de esta llamada es que se leerá el fichero indicado por filePath cargando los datos
correspondientes en el tablero desde el que se llame. En caso de que haya algún
problema con la lectura del fichero, lanzará una excepción informando de este hecho.
getRvec: esta función devuelve un objeto de tipo Mat de OpenCV que contiene el
vector de rotación Rvec del tablero desde el que se llame. Para ello, hace uso de la
31
Capítulo 5. Especificación del modelo de clases
función nativa JgetRvec a la que, mediante la función de Mat getNativeObjAddr se
le pasa la dirección nativa del objeto Mat en la que se enlazará con Rvec.
getTvec: esta función devuelve un objeto de tipo Mat de OpenCV que contiene el
vector de traslación Tvec del tablero desde el que se llame. Para ello, hace uso de la
función nativa JgetRvec a la que, mediante la función de Mat getNativeObjAddr se
le pasa la dirección nativa del objeto Mat en la que se enlazará con Tvec.
getBoardConf: esta función devuelve un objeto del tipo BoardConfiguration que se
recibe haciendo una llamada a la función nativa JgetBoardConf. Este objeto conf
es un atributo de los objetos Board de ArUco.
get: esta función devuelve un objeto de tipo Marker que se encuentra en la posición
dada por el parámetro pos que es de tipo entero dentro del vector de marcadores
que es la clase de ArUco Board. Para obtener este objeto realiza una llamada a la
función nativa Jget.
size: esta función devuelve un entero con el tamaño del vector de marcadores que
es la clase Board de ArUco. Para obtener este dato realiza una llamada a la función
nativa Jsize.
El diagrama de esta clase es el siguiente:
Figura 5.1: Diagrama de clases de Board
5.1.2.
Clase BoardConfiguration
Esta clase, cuya clase equivalente en Aruco es amiga de la clase Board y hereda de la
clase vector de elementos MarkerInfo, contiene la configuración del tablero. Cuenta con
el siguiente atributo privado:
32
Capítulo 5. Especificación del modelo de clases
nativeHandle: es un atributo de tipo long donde se guardará la dirección de memoria
del objeto BoardConfiguration ArUco que se cree y se asocie con este objeto Java.
Además, cuenta con la declaración de las siguientes funciones nativas privadas que tendrán que definirse en el fichero JBoardConfiguration.cpp del wrapper de C++:
JBoardConfiguration: llamará al constructor vacío de la clase BoardConfiguration
de Aruco.
JBoardConfiguration: llamará al constructor de copia de la clase BoardConfiguration de Aruco.
JsaveToFile: que llamará a la función saveToFile de la clase BoardConfiguration de
Aruco.
JreadFromFile: que llamará a la función readFromFile de la clase BoardConfiguration de Aruco.
JisExpressedInMeters: que llamará a la función isExpressedInMeters de la clase
BoardConfiguration de Aruco.
JisExpressedInPixels: que llamará a la función isExpressedInPixels de la clase BoardConfiguration de Aruco.
JgetIndexOfMarkerId: que llamará a la función getIndexOfMarkerId de la clase
BoardConfiguration de Aruco.
JgetIdList: que llamará a la función getIdList de la clase BoardConfiguration de
Aruco.
JgetMarkerInfo: que llamará a la función getMarkerInfo de la clase BoardConfiguration de Aruco.
JgetMInfoType: que sirve para devolver un entero con el valor del atributo público
mInfoType del objeto BoardConfiguration de Aruco.
Jget: que sirve para devolver un objeto MarkerInfo que se encuentra en el vector de
objetos MarkerInfo que es BoardConfiguration en la posición que se le pasa como
parámetro.
Jsize: que sirve para devolver un entero con el tamaño del vector de objetos MarkerInfo que es BoardConfiguration.
Sus métodos públicos son los siguientes:
33
Capítulo 5. Especificación del modelo de clases
BoardConfiguration: constructor vacío de la clase que, crea el objeto BoardConfiguration de Java, así como el de ArUco y los enlaza escribiendo la dirección del
segundo en nativeHandle. Todo esto se hace mediante la llamada a la función de
código nativo JBoard.
BoardConfiguration: constructor de copia de la clase. Recibe como parámetro un
objeto de tipo BoardConfiguration y crea otra instancia que es copia de la anterior.
Hace uso de la función nativa de constructor de copia JBoardConfiguration.
saveToFile: esta función recibe un parámetro de tipo String de Java llamado filePath y lo pasa como parámetro a la función nativa JsaveToFile. El resultado de esta
llamada es que se grabará en el fichero indicado por filePath los datos correspondientes al tablero desde el que se llame. En caso de que haya algún problema con la
creación del fichero, lanzará una excepción informando de este hecho.
readFromFile: esta función recibe un parámetro de tipo String de Java llamado filePath y lo pasa como parámetro a la función nativa JreadFromFile. El resultado
de esta llamada es que se leerá el fichero indicado por filePath cargando los datos
correspondientes en el tablero desde el que se llame. En caso de que haya algún
problema con la lectura del fichero, lanzará una excepción informando de este hecho.
isExpressedInMeters: es una función booleana que devolverá True si el tablero está
expresado en metros.
isExpressedInPixels: es una función booleana que devolverá True si el tablero está
expresado en píxeles.
getIndexOfMarkerId: recibe como parámetro el entero que indica el id de un marcador y devuelve un entero que indica el índice de ese marcador en el tablero (si
está en él).
getIdList: recibe como parámetro un ArrayList de enteros en el que se guardarán
los identificadores de los marcadores del tablero. Como parámetro opcional puede
recibir una variable booleana denominada “append” que, en caso de ser verdadera
hace que los identificadores se añadan al final del ArrayList.
getMarkerInfo: devuelve la información de el marcador cuyo id se le pasa como
parámetro. Esta información se encuentra en un objeto del tipo MarkerInfo. En
caso de que el identificador que se le pasa como parámetro no se encuentre en el
vector, se elevará una excepción.
34
Capítulo 5. Especificación del modelo de clases
getMInfoType: devuelve un entero con el valor del atributo público mInfoType del
objeto de Aruco. Si los datos extán en píxeles, devolverá un 0, si están en meetros,
un 1 y, si no está definido un -1.
get: devuelve el objeto de tipo MarkerInfo que se encuentre en la posición que
indica el entero que se le pasa como parámetro.
size: devuelve el número de objetos MarkerInfo que contiene.
El diagrama de esta clase es el siguiente:
Figura 5.2: Diagrama de clases de BoardConfiguration
5.1.3.
Clase BoardDetector
Esta clase sirve para detectar tableros de ArUco y cuenta con el siguiente atributo
privado:
nativeHandle: es un atributo de tipo long donde se guardará la dirección de memoria
del objeto BoardDetector ArUco que se cree y se asocie con este objeto Java.
Además, cuenta con la declaración de las siguientes funciones nativas privadas que
tendrán que definirse en el fichero JBoardDetector.cpp del wrapper de C++:
JBoardDetector: llamará al constructor vacío de la clase BoardDetector de Aruco.
Jdetect: que llamará a la función detect de la clase BoardDetector de Aruco.
JgetDetectedBoard: que llamará a la función getDetectedBoard de la clase BoardDetector de Aruco.
35
Capítulo 5. Especificación del modelo de clases
JgetMarkerDetector: que llamará a la función getMarkerDetector de la clase BoardDetector de Aruco.
JgetDetectedMarkers: que llamará a la función getDetectedMarkers de la clase
BoardDetector de Aruco.
JsetYPerpendicular: que llamará a la función setYPerpendicular de la clase BoardDetector de Aruco.
Jdetect: que llamará a la función detect de la clase BoardDetector de Aruco en la
versión que solamente recibe una imagen Mat como parámetro.
Jdetect: que llamará a la función detect de la clase BoardDetector de Aruco en la
versión alternativa basada en marcadores que ya han sido detectados.
JsetParams: que llamará a la función setParams de la clase BoardDetector de Aruco
en la versión que solamente recibe un objeto del tipo BoardConfiguration como
parámetro.
JsetParams: que llamará a la función setParams de la clase BoardDetector de Aruco
en la versión que recibe, además de un objeto del tipo BoardConfiguration, los
parámetros de la cámara y el tamaño del lado de los marcadores como parámetros.
Los métodos públicos de la clase BoardDetector son:
BoardDetector: constructor vacío de la clase que, crea el objeto BoardDetector de
Java, así como el de ArUco y los enlaza escribiendo la dirección del segundo en
nativeHandle. Todo esto se hace mediante la llamada a la función de código nativo
JBoardDetector.
detect: recibe una imagen y detecta los marcadores existentes en ella para después
buscar el tablero indicado cuando se usó setParams. El valor devuelto es un flotante
que indica la probabilidad de haber encontrado el marcador. Su parámetro es:
• im: imagen con el formato Mat de OpenCV.
En caso de que se produzca algún error, eleva una excepción.
getDetectedBoard: devuelve un objeto de tipo Board con el tablero detectado.
getMarkerDetector: devuelve un objeto de tipo MarkerDetector con el detector de
marcadores interno.
getDetectedMarkers: devuelve un ArrayList con los objetos Marker detectados.
36
Capítulo 5. Especificación del modelo de clases
setYPerpendicular: por defecto, el eje Y está configurado para apuntar hacia arriba.
Si se marca como falso será el Z el que apunte hacia arriba.
detect (método alternativo): basado en marcadores que ya ha sido detectados. Recibe los siguientes parámetros:
• detectedMarkers: que es el resultado que provee MarkerDetector.
• BConf: el tablero cuya presencia queremos comprobar.
• Bdetected: la información de salida del tablero detectado.
• camMatrix: matriz de la cámara con los datos intrínsecos. Es opcional, si no
se indica se usará una matriz nueva.
• distCoeff: coeficientes de distorsión de la cámara. Es opcional, si no se indica
se usará una matriz nueva.
• markerSizeMeters: tamaño de los lados del marcador expresado en metros. Es
opcional, si no se indica se usará el valor -1.
En caso de que se produzca algún error, eleva una excepción.
detect: mismo método que el anterior pero que utiliza el objeto de tipo CameraParameters en lugar de las matrices de distorsión y cámara por separado.
• detectedMarkers: que es el resultado que provee MarkerDetector.
• BConf: el tablero cuya presencia queremos comprobar.
• Bdetected: la información de salida del tablero detectado.
• CP: de tipo CameraParameters.
• markerSizeMeters: tamaño de los lados del marcador expresado en metros. Es
opcional, si no se indica se usará el valor -1.
setParams: esta función ha de usarse si se planea realizar también detección de
marcadores con esta clase. Su parámetro es:
• bc: referencia a un objeto del tipo BoardConfiguration.
setParams: esta función ha de usarse si se planea realizar también detección de
marcadores con esta clase.
• bc: referencia a un objeto de tipo BoardConfiguration.
• cp: referencia a un objeto de tipo CameraParameters.
• markerSizeMeters: variable real (que por defecto tiene su valor a -1).
37
Capítulo 5. Especificación del modelo de clases
El diagrama de esta clase es el siguiente:
Figura 5.3: Diagrama de clases de BoardDetector
5.1.4.
Clase CameraParameters
Representa la clase en la que se guardan los parámetros de la cámara.
Esta clase cuenta con el siguiente atributo privado:
nativeHandle: es un atributo de tipo long donde se guardará la dirección de memoria
del objeto CameraParameters ArUco que se cree y se asocie con este objeto Java.
Además, cuenta con la declaración de las siguientes funciones nativas privadas que
tendrán que definirse en el fichero JCameraParameters.cpp del wrapper de C++:
JCameraParameters: llamará al constructor vacío de la clase CameraParameters de
Aruco.
JCameraParameters: llamará al constructor de copia de la clase CameraParameters
de Aruco.
JCameraParameters: llamará al constructor parametrizado de la clase CameraParameters de Aruco.
JreadFromFile: que llamará a la función readFromFile de la clase CameraParameters de Aruco.
JisValid: que llamará a la función isValid de la clase CameraParameters de Aruco.
JsetParams: que llamará a la función setParams de la clase CameraParameters de
Aruco.
JsaveToFile: que llamará a la función saveToFile de la clase CameraParameters de
Aruco.
38
Capítulo 5. Especificación del modelo de clases
JreadFromXMLFile: que llamará a la función readFromXMLFile de la clase CameraParameters de Aruco.
Jresize: que llamará a la función isValid de la clase CameraParameters de Aruco.
JglGetProjectionMatrix: que llamará a la función glGetProjectionMatrix de la clase
CameraParameters de Aruco.
JOgreGetProjectionMatrix: que llamará a la función OgreGetProjectionMatrix de
la clase CameraParameters de Aruco.
JgetCameraLocation: que llamará a la función getCameraLocation de la clase CameraParameters de Aruco.
JgetCameraMatrix: que sirve para devolver un objeto de tipo Mat con el valor del
atributo público CameraMatrix del objeto CameraParameters de Aruco.
JgetDistorsion: que sirve para devolver un objeto de tipo Mat con el valor del atributo público Distorsion del objeto CameraParameters de Aruco.
JgetCamSizeWidth: que obtendrá la anchura de la imagen proveniente del objeto
de tipo Size con el valor del atributo público CamSize.width del objeto CameraParameters de Aruco.
JgetCamSizeHeight: que obtendrá la altura de la imagen proveniente del objeto de
tipo Size con el valor del atributo público CamSize.height del objeto CameraParameters de Aruco.
Los métodos públicos de la clase CameraParameters son:
CameraParameters: constructor vacío de la clase que, crea el objeto CameraParameters de Java, así como el de ArUco y los enlaza escribiendo la dirección del
segundo en nativeHandle. Todo esto se hace mediante la llamada a la función de
código nativo JCameraParameters.
CameraParameters: constructor de copia de la clase. Recibe como parámetro un
objeto de tipo CameraParameters y crea otra instancia que es copia de la anterior.
Hace uso de la función nativa de constructor de copia JCameraParameters.
CameraParameters: constructor parametrizado de la clase. Recibe como parámetros
dos objetos de tipo Mat con la matriz de la cámara y el coeficiente de distorsión,
además de un objeto de tipo Size con el tamaño de la imagen.
getCameraLocation: devuelve la posición de la cámara en el sistema referencial
dado por los vectores de rotación y translación pasados como parámetros. Los dos
39
Capítulo 5. Especificación del modelo de clases
vectores de entrada son del tipo Mat de OpenCV y el punto de salida es del tipo
Point3 también de OpenCV.
setParams: función que fija los parámetros de la cámara. Recibe como parámetros
dos objetos de tipo Mat con la matriz de la cámara y el coeficiente de distorsión,
además de un objeto de tipo Size con el tamaño de la imagen.
isValid: función de tipo booleano que devuelve verdadero si el objeto es válido y
falso en caso contrario.
readFromFile: lee los parámetros de la cámara desde un fichero. Recibe como parámetro la ruta hasta el fichero. En caso de no poder leer el fichero, lanza una excepción.
saveToFile: guarda los parámetros de la cámara en un fichero. Recibe como parámetro la ruta hasta el fichero (String) y un booleano opcional (por defecto con valor
verdadero) que indica si el fichero se desea guardar como XML o no. En caso de no
poder escribir en el fichero, lanza una excepción.
readFromXMLFile: lee los parámetros de la cámara desde un fichero YAML generado con la utilidad método de calibrado de OpenCV 2.2. En caso de no poder leer
el fichero, lanza una excepción.
resize: recibe una variable de tipo Size de OpenCV para ajustar el parámetro de
tamaño de la imagen indicado. Si los parámetros de la cámara no son válidos a la
hora de redimensionar, elevará una excepción.
glGetProjectionMatrix: dados los parámetros intrínsecos de la cámara, devuelve la
matriz GL_MODELVIEW para OpenGL. Los parámetros que recibe son los siguientes:
• orgImgSize: tamaño de la imagen original. Es un objeto de tipo Size de OpenCV.
• size: tamaño de la imagen o ventana donde se va a renderizar (que puede ser
diferente de la imagen real de la cámara). Es un objeto de tipo Size de OpenCV.
• proj_matrix: matriz de 16 reales la proyección de salida para OpenGL. Es un
vector de variables de tipo double.
• gnear,gfar: rango de renderización visible. Son variables de tipo double.
• invert: indica si la matriz de proyección de salida tiene que producir una imagen horizontalmente invertida porque los datos de la imagen no han sido almacenados en el orden de glDrawPixels de abajo hacia arriba. Es de tipo booleano.
40
Capítulo 5. Especificación del modelo de clases
En caso de que los parámetros extrínsecos no sean correctos, lanza una excepción.
OgreGetProjectionMatrix: configura la cámara para un proyecto de Ogre. Tiene
los mismos argumentos que glGetProjectionMatrix. En caso de que los parámetros
extrínsecos no sean correctos, lanza una excepción.
getCameraMatrix: función que devuelve un objeto de tipo Mat de OpenCV con la
matriz de la cámara.
getDistorsion: función que devuelve un objeto de tipo Mat de OpenCV con la matriz
de distorsión.
getCamSize: que devuelve un objeto de tipo Size con el tamaño de la imagen.
El diagrama de esta clase es el siguiente:
Figura 5.4: Diagrama de clases de CameraParameters
5.1.5.
Clase CvDrawingUtils
Es un conjunto de funciones para dibujar imágenes que utiliza OpenCV.
Esta clase cuenta con el siguiente atributo privado:
nativeHandle: es un atributo de tipo long donde se guardará la dirección de memoria
del objeto CvDrawingUtils ArUco que se cree y se asocie con este objeto Java.
Además, cuenta con la declaración de las siguientes funciones nativas privadas que
tendrán que definirse en el fichero JCvDrawingUtils.cpp del wrapper de C++:
JCvDrawingUtils: llamará al constructor vacío de la clase CvDrawingUtils de Aruco.
Jdraw3dAxis: que llamará a la función draw3dAxis de la clase CvDrawingUtils de
Aruco en la versión que recibe un marcador.
41
Capítulo 5. Especificación del modelo de clases
Jdraw3dCube: que llamará a la función draw3dCube de la clase CvDrawingUtils
de Aruco en la versión que recibe un marcador.
Jdraw3dAxis: que llamará a la función draw3dAxis de la clase CvDrawingUtils de
Aruco en la versión que recibe un tablero.
Jdraw3dCube: que llamará a la función draw3dCube de la clase CvDrawingUtils
de Aruco en la versión que recibe un tablero.
Los métodos públicos de la clase CvDrawingUtils son:
CvDrawingUtils: constructor vacío de la clase que, crea el objeto CvDrawingUtils
de Java, así como el de ArUco y los enlaza escribiendo la dirección del segundo en
nativeHandle. Todo esto se hace mediante la llamada a la función de código nativo
JCvDrawingUtils.
draw3dAxis: esta función recibe como parámetros una imagen de tipo Mat, un objeto de tipo Marker y otro de tipo CameraParameters. Su cometido es el de dibujar
en la imagen los ejes tridimensionales de la escena sobre el marcador que recibe.
draw3dCube: esta función recibe como parámetros una imagen de tipo Mat, un
objeto de tipo Marker y otro de tipo CameraParameters. Su cometido es el de
dibujar en la imagen un cubo tridimensional sobre el marcador que recibe.
draw3dAxis: esta función recibe como parámetros una imagen de tipo Mat, un objeto de tipo Board y otro de tipo CameraParameters. Su cometido es el de dibujar
en la imagen los ejes tridimensionales de la escena sobre el tablero que recibe.
draw3dCube: esta función recibe como parámetros una imagen de tipo Mat, un
objeto de tipo Board y otro de tipo CameraParameters. Su cometido es el de dibujar
en la imagen un cubo tridimensional sobre el tablero que recibe.
El diagrama de esta clase es el siguiente:
Figura 5.5: Diagrama de clases de CvDrawingUtils
42
Capítulo 5. Especificación del modelo de clases
5.1.6.
Clase FiducidalMarkers
En esta clase se encuentran diversos métodos para crear imágenes con marcadores y
tableros.
Posee la declaración de las siguientes funciones nativas privadas que tendrán que definirse en el fichero JFiducidalMarkers.cpp del wrapper de C++:
JcreateMarkerImage: que llamará a la función createMarkerImage de la clase FiducidalMarkers de Aruco.
Jdetect: que llamará a la función Jdetect de la clase FiducidalMarkers de Aruco.
JgetMarkerMat: que llamará a la función JgetMarkerMat de la clase FiducidalMarkers de Aruco.
JcreateBoardImage: que llamará a la función JcreateBoardImage de la clase FiducidalMarkers de Aruco.
JcreateBoardImage_ChessBoard: que llamará a la función JcreateBoardImage_ChessBoard
de la clase FiducidalMarkers de Aruco.
JcreateBoardImage_Frame: que llamará a la función JcreateBoardImage_Frame de
la clase FiducidalMarkers de Aruco.
Los métodos públicos de la clase FiducidalMarkers son:
createMarkerImage: crea un marcador con el identificador especificado utilizando
una versión modificada del código hamming. Hay dos tipos de marcadores:
• Marcadores de 10 bits: sus identificadores están en el intervalo 0-1023.
• Marcadores de 3 bits: utilizados en aplicaciones que necesitan menos marcadores que han de ser pequeños. Sus identificadores se encuentran en el intervalo 2000-2006.
Los parámetros que recibe son:
• id: de tipo entero, indica el identificador del marcador que estamos creando.
• size: de tipo entero, indica el tamaño del lado del marcador en píxeles.
En caso de que el id indicado no sea válido, elevará una excepción.
detect: detecta marcadores de ArUco de 10 bits. Recibe la imagen en la que se
encuentran los marcadores (tipo Mat de OpenCV) y un entero con el número de
rotaciones de 90 grados necesarias para situar el marcador en la posición correcta.
Devolverá un -1 si la imagen que se le pasa no es un marcador válido y su identificador en caso de que sí lo sea (valor entero).
43
Capítulo 5. Especificación del modelo de clases
getMarkerMat: es similar a createMarkerImage pero en lugar de devolver una imagen visible, devuelve una matriz binaria 8UC1 con la información del marcador
cuyo identificador se le pasa como parámetro. En caso de que este identificador
contenga un valor incorrecto, elevará una excepción.
createBoardImage: crea una imagen imprimible del tablero. Recibe los siguientes
parámetros:
• gridSize: de tipo Size de OpenCV que indica el número de marcadores que
habrá en el eje X y en el eje Y.
• MarkerSize: de tipo un entero que contiene el tamaño del lado de los marcadores en píxeles.
• MarkerDistance: de tipo entero que contiene la distancia entre marcadores en
píxeles.
• TInfo: que es un objeto de tipo BoardConfiguration en el que se escribirá la
configuración del tablero creado.
• excludedIds: que es un ArrayList de enteros con los identificadores que no se
desea que aparezcan en el tablero. Este parámetro es opcional.
createBoardImage_ChessBoard: crea una imagen imprimible del tablero de forma
similar al aspecto de un tablero de ajedrez. Sus parámetros son:
• gridSize: de tipo Size de OpenCV que indica el número de marcadores que
habrá en el eje X y en el eje Y.
• MarkerSize: de tipo un entero que contiene el tamaño del lado de los marcadores en píxeles.
• TInfo: que es un objeto de tipo BoardConfiguration en el que se escribirá la
configuración del tablero creado.
• setDataCentered: es un parámetro de tipo booleano que indica si el centro se
sitúa en el centro del tablero. En caso de que se ponga como falso el centro
se sitúa en la esquina superior izquierda. Es un parámetro opcional que por
defecto está a valor verdadero.
• excludedIds: que es un ArrayList de enteros con los identificadores que no se
desea que aparezcan en el tablero. Este parámetro es opcional.
createBoardImage_Frame: crea una imagen imprimible del tablero con marco. Sus
parámetros son:
• gridSize: de tipo Size de OpenCV que indica el número de marcadores que
habrá en el eje X y en el eje Y.
44
Capítulo 5. Especificación del modelo de clases
• MarkerSize: de tipo un entero que contiene el tamaño del lado de los marcadores en píxeles.
• TInfo: que es un objeto de tipo BoardConfiguration en el que se escribirá la
configuración del tablero creado.
• setDataCentered: es un parámetro de tipo booleano que indica si el centro se
sitúa en el centro del tablero. En caso de que se ponga como falso el centro
se sitúa en la esquina superior izquierda. Es un parámetro opcional que por
defecto está a valor verdadero.
• excludedIds: que es un ArrayList de enteros con los identificadores que no se
desea que aparezcan en el tablero. Este parámetro es opcional.
5.1.7.
Clase Marker
Esta clase representa un marcador. En la clase C++ subyacente hereda de un vector
con las cuatro esquinas del marcador (puntos Point2f ).
Cuenta con el siguiente atributo privado:
nativeHandle: es un atributo de tipo long donde se guardará la dirección de memoria
del objeto Marker ArUco que se cree y se asocie con este objeto Java.
Además, cuenta con la declaración de las siguientes funciones nativas privadas que
tendrán que definirse en el fichero JMarker.cpp del wrapper de C++:
JMarker: llamará al constructor vacío de la clase Marker de Aruco.
JMarker: llamará al constructor de copia de la clase Marker de Aruco.
JMarker: llamará al constructor parametrizado de la clase Marker de Aruco.
JisValid: que llamará a la función isValid de la clase Marker de Aruco.
Jdraw: que llamará a la función draw de la clase Marker de Aruco.
JglGetModelViewMatrix: que llamará a la función glGetModelViewMatrix de la
clase Marker de Aruco.
JgetArea: que llamará a la función getArea de la clase Marker de Aruco.
JgetPerimeter: que llamará a la función getPerimeter de la clase Marker de Aruco.
JgetCenter: que llamará a la función getCenter de la clase Marker de Aruco.
JcalculateExtrinsics: que llamará a la función calculateExtrinsics de la clase Marker
de Aruco recibiendo un flotante (“markerSize”), un objeto de tipo CameraParameters (“CP”) y el booleano (“setYPerpendicular”).
45
Capítulo 5. Especificación del modelo de clases
JcalculateExtrinsics: que llamará a la función calculateExtrinsics de la clase Marker
de Aruco recibiendo un flotante (“markerSize”), la dirección de memoria de un
objeto de tipo Mat (“cameraMatrix”), la dirección de memoria de otro objeto de
tipo Mat (“distCoeff”) y el booleano (“setYPerpendicular”).
JOgreGetPoseParameters: que llamará a la función OgreGetPoseParameters de la
clase Marker de Aruco.
JgetRvec: devuelve, en el objeto que se le pasa como parámetro, la matriz de rotación Rvec que es un atributo público del objeto Marker de Aruco.
JgetTvec: devuelve, en el objeto que se le pasa como parámetro, la matriz de traslación Tvec que es un atributo público del objeto Marker de Aruco.
JgetId: devuelve un entero con el valor del atributo público id del objeto Marker de
Aruco.
JgetSSize: devuelve un flotante con el valor del atributo público ssize del objeto
Marker de Aruco.
JlessThan: que llamará al operador < de la clase Marker de Aruco.
JtoString: que llamará al operador << de la clase Marker de Aruco.
Jsize: dado que dentro de Aruco Marker hereda de vector cuyos elementos son
Point2f de OpenCV se estima interesante ofrecer la función size() de la clase vector)
que es llamada mediante Jsize().
Jget: dado que dentro de Aruco Marker hereda de vector cuyos elementos son
Point2f de OpenCV se estima interesante ofrecer la posibilidad de obtener los elementos del vector usando esta función.
Los métodos públicos de la clase Marker son:
Marker: constructor vacío de la clase que, crea el objeto Marker de Java, así como
el de ArUco y los enlaza escribiendo la dirección del segundo en nativeHandle.
Todo esto se hace mediante la llamada a la función de código nativo JMarker.
Marker: constructor de copia de la clase. Recibe como parámetro un objeto de tipo
Marker y crea otra instancia que es copia de la anterior. Hace uso de la función
nativa de constructor de copia JMarker.
Marker: constructor parametrizado que recibe un ArrayList que ha de contener cuatro objetos de tipo Point de OpenCV con las coordnadas de los puntos de las esquinas del marcador. Además, puede recibir un entero que contiene el identificador del
marcador (en caso de que no se pase el entero, se utilizará el valor -1).
46
Capítulo 5. Especificación del modelo de clases
isValid: es un método de tipo boleano que devuelve verdadero si el marcador es
válido y falso en caso contrario.
draw: recibe una imagen en la que dibuja líneas que delimitan al marcador detectado. Sus parámetros son:
• img: es la imagen en la que se desea dibujar el marcador. Es del tipo Mat de
OpenCV.
• color: es una variable del tipo Scalar de OpenCV que contiene el valor del
color de las líneas que delimitarán el marcador.
• lineWidth: es un entero que indica anchura de la línea en píxeles. En caso de
no seleccionarse ningún valor se utilizará el valor 1 por defecto.
• writeId: variable booleana que, en caso de estar a valor verdadero, indica que
se escriba el id del marcador detectado. Su valor por defecto es verdadero.
calculateExtrinsics: calcula los valores de Rvec y Tvec con respecto de la cámara.
Los parámetros de esta función son:
• markerSize: tamaño del lado del marcador expresado en metros. Es una variable de tipo flotante.
• CP: parámetros de la cámara. Es un objeto del tipo CameraParameters.
• setYPerperdicular: en caso de ser verdadero, el eje Y será perpendicular a la
superficie. En caso contrario lo será el eje Z. Este parámetro es opcional y su
valor por defecto es verdadero.
Si los parámetros de la cámara, el marcador o su tamaño no son válidos elevará una
excepción.
calculateExtrinsics: calcula los valores de Rvec y Tvec con respecto de la cámara.
Los parámetros de esta función son:
• markerSize: tamaño del lado del marcador expresado en metros. Es una variable de tipo flotante.
• CameraMatrix: matriz con los parámetros de la cámara (fx,fy,cx,cy). Es del
tipo Mat de OpenCV.
• Distorsion: matriz con los parámetros de distorsión (k1,k2,p1,p2). Es del tipo Mat de OpenCV. Este parámetro es opcional, en caso de no indicarse se
utilizará una matriz vacía.
• setYPerperdicular: en caso de ser verdadero, el eje Y será perpendicular a la
superficie. En caso contrario lo será el eje Z. Este parámetro es opcional y su
valor por defecto es verdadero.
47
Capítulo 5. Especificación del modelo de clases
Si los parámetros de la cámara, el marcador o su tamaño no son válidos elevará una
excepción.
glGetModelViewMatrix: dados los parámetros de la cámara extrínsecos devuelve
la matriz GL_MODELVIEW para OpenGL. Recibe como parámetro:
• modelview_matrix: matriz de doble precisión en la que se guardará la matriz
GL_MODELVIEW.
En caso de que los parámetros extrínsecos no sean correctos, lanza una excepción.
OgreGetPoseParameters: devuelve el vector de posición y el cuaternión de orientación para un nodo de escena Ogre o para una entidad. Recibe los siguientes parámetros:
• position: vector de tres reales.
• orientation: vector de cuatro reales.
En caso de que los parámetros extrínsecos no sean correctos, lanza una excepción.
getCenter: devuelve el centroide del marcador. El tipo dvuelto es Point de OpenCV.
getPerimeter: devuelve un flotante que contiene el perímetro del marcador.
getArea: devuelve un flotante que contiene el área del marcador.
getId: devuelve un entero con el valor del identificador del marcador en cuestión.
getSSize: devuelve un valor real que contiene el tamaño de los lados del marcador
en metros.
getTvec: devuelve la matriz de traslación con respecto de la cámara. Utiliza el tipo
de dato Mat de OpenCV.
getRvec: devuelve la matriz de rotación con respecto de la cámara. Utiliza el tipo
de dato Mat de OpenCV.
lessThan: devuelve un booleano que será verdadero si el identificador del marcador
desde el que se llama es menor que el del que se le pasa como parámetro y falso en
caso contrario.
toString: devuelve una cadena con el identificador del marcador, las coordenadas
de sus esquinas y los valores de Rvec y Tvec.
size: devuelve un entero con la cantidad de puntos (deben ser 4) que tiene guardados
este marcador.
48
Capítulo 5. Especificación del modelo de clases
get: devuelve la esquina del marcador (un punto Point de OpenCV) que ocupa la
posición que se le indique en el entero que se le pasa como parámetro.
El diagrama de esta clase es el siguiente:
Figura 5.6: Diagrama de clases de Marker
5.1.8.
Clase MarkerDetector
Es la clase principal para realizar las acciones de detección de marcadores.
Esta clase cuenta con el siguiente atributo privado:
nativeHandle: es un atributo de tipo long donde se guardará la dirección de memoria
del objeto MarkerDetector ArUco que se cree y se asocie con este objeto Java.
Además, cuenta con la declaración de las siguientes funciones nativas privadas que
tendrán que definirse en el fichero JMarkerDetector.cpp del wrapper de C++:
JMarkerDetector: llamará al constructor vacío de la clase MarkerDetector de Aruco.
JMarkerDetector: llamará al constructor de copia de la clase MarkerDetector de
Aruco.
Jdetect: que llamará a la función detect de la clase MarkerDetector de Aruco.
49
Capítulo 5. Especificación del modelo de clases
Jdetect: que llamará a la función detect de la clase MarkerDetector de Aruco.
JgetDesiredSpeed: que llamará a la función getDesiredSpeed de la clase MarkerDetector de Aruco.
JsetDesiredSpeed: que llamará a la función setDesiredSpeed de la clase MarkerDetector de Aruco.
JsetThresholdMethod: que llamará a la función setThresholdMethod de la clase
MarkerDetector de Aruco.
JgetThresholdMethod: que llamará a la función getThresholdMethod de la clase
MarkerDetector de Aruco.
JsetThresholdParams: que llamará a la función setThresholdParams de la clase
MarkerDetector de Aruco.
JgetThresholdParam1: que llamará a la función getThresholdParams de la clase
MarkerDetector de Aruco y obtendra el primero de los dos parámetros.
JgetThresholdParam2: que llamará a la función getThresholdParams de la clase
MarkerDetector de Aruco y obtendra el segundo de los dos parámetros.
JgetThresholdedImage: que llamará a la función getThresholdedImage de la clase
MarkerDetector de Aruco.
JsetCornerRefinementMethod: que llamará a la función setCornerRefinementMethod de la clase MarkerDetector de Aruco.
JgetCornerRefinementMethod: que llamará a la función getCornerRefinementMethod de la clase MarkerDetector de Aruco.
JsetMinMaxSize: que llamará a la función setMinMaxSize de la clase MarkerDetector de Aruco.
JgetMinSize: que llamará a la función getMinMaxSize de la clase MarkerDetector
de Aruco y obtendrá el valor del mínimo.
JgetMaxSize: que llamará a la función getMinMaxSize de la clase MarkerDetector
de Aruco y obtendrá el valor del máximo.
JenableErosion: que llamará a la función enableErosion de la clase MarkerDetector
de Aruco.
JpyrDown: que llamará a la función pyrDown de la clase MarkerDetector de Aruco.
50
Capítulo 5. Especificación del modelo de clases
Esta clase cuenta con dos enumeraciones públicas (“enum” en Java), son las siguientes:
ThresholdMethods: en la que se encuentran los siguientes tipos de umbral:
• FIXED_THRES
• ADPT_THRES
• CANNY
CornerRefinementMethod: en la que se encuentran los siguientes tipos de refinado
de las esquinas:
• NONE
• HARRIS
• SUBPIX
• LINES
Los métodos públicos de la clase MarkerDetector son:
MarkerDetector: constructor vacío de la clase que, crea el objeto MarkerDetector
de Java, así como el de ArUco y los enlaza escribiendo la dirección del segundo en
nativeHandle. Todo esto se hace mediante la llamada a la función de código nativo
JMarkerDetector.
MarkerDetector: constructor de copia de la clase. Recibe como parámetro un objeto
de tipo MarkerDetector y crea otra instancia que es copia de la anterior. Hace uso
de la función nativa de constructor de copia JMarkerDetector.
detect: este método detecta marcadores en la imagen que recibe como parámetro. Si
se le pasa información sobre los parámetros de la cámara y el tamaño del marcador,
entonces, se detectarán los valores extrínsecos de los marcadores. Sus parámetros
son:
• input: imagen de entrada en color. Es del tipo Mat de OpenCV.
• detectedMarkers: ArrayList de objetos de tipo Marker que dará como salida
los marcadores detectados.
• camMatrix: información intrínseca de la cámara. Es del tipo Mat de OpenCV.
• distCoeff: coeficiente de distorsión de la cámara. Si no se incluye se asume
que no hay distorsión en la cámara. Es del tipo Mat de OpenCV.
• markerSizeMeters: flotante que contiene tamaño del lado del marcador expresado en metros.
51
Capítulo 5. Especificación del modelo de clases
• setYPerperdicular: booleano que si tiene valor verdadero el eje Y será perpendicular a la superficie. De otro modo, lo será el eje Z.
Si se produce algún error en la detección, elevará una excepción.
detect: es el mismo método anterior pero con los parámetros que pueden leerse a
continuación:
• img: imagen de entrada en color. Es del tipo Mat de OpenCV.
• detectedMarkers: ArrayList de objetos de tipo Marker que dará como salida
los marcadores detectados.
• camParam: parámetros de la cámara. Es un objeto del tipo CameraParameters.
• markerSizeMeters: flotante que contiene tamaño del lado del marcador expresado en metros.
• setYPerperdicular: booleano que si tiene valor verdadero el eje Y será perpendicular a la superficie. De otro modo, lo será el eje Z.
Si se produce algún error en la detección, elevará una excepción.
setCornerRefinementMethod: que recibe como parámetro un valor del tipo CornerRefinementMethod y lo fija los como método de refinado de las esquinas.
getCornerRefinementMethod: que devuelve el valor de tipo CornerRefinementMethod que esté fijado como método de refinado de las esquinas.
setThresholdMethod: que recibe como parámetro un valor del tipo ThresholdMethods y lo fija como método de umbral.
getThresholdMethod: que devuelve el valor de tipo ThresholdMethods que esté fijado como método de umbral.
setThresholdParams: fija los parámetros del método de umbral. Actualmente se está
utilizando el método “adaptiveThreshold” de OpenCV. Los parámetros son:
• param1: “blockSize” (tamaño de bloque) del vecindario de píxeles que es usado para calcular un valor umbral para el pixel. Es de tipo double.
• param2: la constante extraída de la media o la media ponderada. Es de tipo
double.
getThresholdParam1: devuelve el primero de los dos parámetros comentados anteriormente.
getThresholdParam2: devuelve el segundo de los dos parámetros comentados anteriormente.
52
Capítulo 5. Especificación del modelo de clases
getThresholdedImage: devuelve una referencia a la imagen interna a la que se le
ha realizado el umbral. Utilizado para visualización y para ajustar manualmente los
parámetros. El valor devuelto es de tipo Mat de OpenCV.
setDesiredSpeed: recibe un parámetro de tipo entero que especifica la velocidad
requerida para los procesos internos. Si se necesita una velocidad máxima (con
el coste de un porcentaje de detección menor) se ha de usar el valor 3. Si, por el
contrario, se necesita un mayor porcentaje de detección, se ha de usar el valor cero.
getDesiredSpeed: devuelve un entero especificando la velocidad requerida para los
procesos internos.
setMinMaxSize: especifica el tamaño mínimo y máximo de los marcadores en forma de fracción del tamaño de imagen. Por tamaño se entiende el máximo de filas o
columnas. Los dos parámetros de tipo real que recibe son:
• min: es el mínimo tamaño de los marcadores. Si no se indica su valor será
0.03.
• max: es el máximo tamaño de los marcadores. Si no se indica su valor será
0.5.
Si alguno de los dos valores no se encuentra entre 0 y 1 elevará una excepción.
getMinSize: devuelve el tamaño mínimo de los marcadores en forma de fracción
del tamaño de imagen.
getMaxSize: devuelve el tamaño máximo de los marcadores en forma de fracción
del tamaño de imagen.
enableErosion: es una función que recibe una variable booleana que permite activar o desactivar el proceso de erosión que es necesario para los tableros de tipo
“chessboard”. Por defecto la erosión está activada.
pyrDown: usa una versión más pequeña de la imagen de entrada para detección de
marcadores. Si el marcador es lo suficientemente pequeño, se puede utilizar una
imagen más pequeña para realizar la detección sin una reducción en la precisión
apreciable. Internamente, se está realizando una operación de tipo pyrdown. Como
parámetro recibe un entero sin signo que indica el número de veces que el tamaño
de imagen es dividido por dos.
El diagrama de esta clase es el siguiente:
53
Capítulo 5. Especificación del modelo de clases
Figura 5.7: Diagrama de clases de MarkerDetector
5.1.9.
Clase MarkerInfo
Esta clase contiene la representación 3D de un marcador. En su estructura C++ subyacente hereda de la clase vector de puntos tridimensionales de OpenCV Point3f.
Cuenta con las siguientes declaraciones de funciones nativas que se definirán en el
fichero JMarkerInfo.cpp del wrapper de C++.
JMarkerInfo: llamará al constructor vacío de la estructura MarkerInfo de Aruco.
JMarkerInfo: llamará al constructor de copia de la estructura MarkerInfo de Aruco.
JMarkerInfo: llamará al constructor parametrizado de la estructura MarkerInfo de
Aruco.
JgetId: devuelve un entero con el valor del atributo público id de la estructura MarkerInfo de Aruco.
Jsize: llamará a la función size() del vector de puntos de OpenCV.
Jget: que sirve para devolver un objeto Point3 que se encuentra en el vector de
marcadores que es MarkerInfo en la posición que se le pasa como parámetro.
Los métodos públicos de la clase MarkerInfo son:
MarkerInfo: constructor vacío de la clase que, crea el objeto MarkerInfo de Java, así
como la estructura de ArUco y los enlaza escribiendo la dirección del segundo en
nativeHandle. Todo esto se hace mediante la llamada a la función de código nativo
JMarkerInfo.
54
Capítulo 5. Especificación del modelo de clases
MarkerInfo: constructor de copia de la clase. Recibe como parámetro un objeto de
tipo MarkerInfo y crea otra instancia que es copia de la anterior. Hace uso de la
función nativa de constructor de copia JMarkerInfo.
MarkerInfo: constructor parametrizado de la clase. Recibe como parámetro un entero con el identificador del marcador.
getId: devuelve un entero con el valor de la variable id de la estructura MarkerInfo
de Aruco.
size: este método devuelve un entero con el tamaño del vector de puntos que es la
estructura MarkerInfo de ArUco. Para obtener este dato realiza una llamada a la
función nativa Jsize.
get: este método devuelve el objeto del tipo Point3 de OpenCV que se encuentre en
la posición del vector que se le indica como parámetro.
El diagrama de esta clase es el siguiente:
Figura 5.8: Diagrama de clases de MarkerInfo
5.2.
Análisis de los ficheros C++ del “wrapper”
Las clases Java llamarán a funciones de la librería ArUco mediante JNI. Para poder
transformar los parámetros tanto de entrada como de salida se han creado los ficheros del
“wrapper”. Estos ficheros son los siguientes:
Handle.h
JBoard.cpp y JBoard.h
55
Capítulo 5. Especificación del modelo de clases
JBoardConfiguration.cpp y JBoardConfiguration.h
JBoardDetector.cpp y JBoardDetector.h
JCameraParameters.cpp y JCameraParameters.h
JCvDrawingUtils.cpp y JCvDrawingUtils.h
JFiducidalMarkers.cpp y JFiducidalMarkers.h
JMarker.cpp y JMarker.h
JMarkerDetector.cpp y JMarkerDetector.h
JMarkerInfo.cpp y JMarkerInfo.h
Todos los nombres de funciones que no están en “Handle.h” comienzan con el prefijo
Java_wrapper_NombreClase debido a que JNI genera estos nombres de manera automática. Por claridad, se van a omitir estos prefijos.
5.2.1.
Handle.h
Este fichero es de suma importancia para poder enlazar los objetos Java con sus objetos de la librería ArUco subyacentes. Como ya se ha explicado previamente, cada instancia en la parte Java tiene una variable privada de tipo long llamada nativeHandle. Dentro
de este fichero se encuentran las funciones responsables de obtener y modificar esos valores para que cada instancia de la parte Java pueda hacer llamadas a su correspondiente
objeto en la parte de C++. Sus funciones son las siguientes:
getHandleField: sirve para obtener el identificador del atributo nativeHandle del
objeto jobject que se le pasa como parámetro. Esto servirá para poder leer o modificar este atributo en el objeto Java desde la parte nativa como veremos en las dos
siguientes funciones.
getHandle: obtiene el valor del campo nativeHandle del objeto jobject que se le
pasa como parámetro y lo convierte a un puntero del tipo C++ que sea necesario.
Mediante este puntero, se podrá acceder a los atributos y métodos del objeto de
ArUco.
setHandle: realiza la función inversa a getHandle. Recibe un puntero C++ como
parámetro y guarda su dirección de memoria en la variable nativeHandle del objeto Java. De este modo, quedarán los dos objetos enlazados para cuando se quiera
acceder al objeto de ArUco.
56
Capítulo 5. Especificación del modelo de clases
newJavaException: esta función sirve para elevar una excepción desde ArUco hasta
el código Java. Recibe la referencia a la clase Java de la excepción (por ejemplo “java/lang/Exception”) y el texto que se desea mostrar en la excepción. Esta función
lanza la excepción en Java con esos valores.
5.2.2.
JBoard.cpp y JBoard.h
Estos ficheros son los responsables de llamar a las funciones de la clase Board. Transforman los parámetros de entrada de manera adecuada para que puedan ser manejados en
C++ y los de salida para que puedan ser utilizados en Java. El contenido de JBoard.h es
generado automáticamente por la utilidad javah. Este fichero contiene las cabeceras de
todas las funciones que se indicaron como native en la clase Board de Java. En el fichero
JBoard.cpp se desarrollan estas funciones, que son las siguientes:
JBoard__: llamada desde el constructor vacío de la clase Board de Java. Crea un
objeto de tipo Board en ArUco y guarda su dirección de memoria en el atributo
nativeHandle del correspondiente objeto Board de la parte Java.
JBoard__Lwrapper_Board_2: constructor de copia de la clase Board. Recibe como parámetro un objeto Board de Java del que extrae su objeto ArUco y crea un
nuevo objeto Board usando el constructor de copia de ArUco. Después, guarda la
referencia del nuevo objeto en el de Java utilizando su atributo nativeHandle.
JsaveToFile: función que sirve para llamar al método saveToFile de la clase Board
de ArUco. Recibe una cadena de Java como parámetro y la convierte en una cadena
legible para el objeto de C++. En caso de que haya algún problema con la ruta en
la que se desea crear el archivo, elevará una excepción a Java.
JreadFromFile: función que sirve para llamar al método readFromFile de la clase
Board de ArUco. Recibe una cadena de Java como parámetro y la convierte en una
cadena legible para el objeto de C++. En caso de que haya algún problema con la
ruta en la que se ha de encontrar el archivo, elevará una excepción a Java.
JglGetModelViewMatrix: recibe un vector de 16 elementos llamado modelview_matrix
y lo rellena llamando a la función glGetModelViewMatrix de la clase Board.
JOgreGetPoseParameters: recibe dos vectores (position de 3 elementos de tipo double y orientation de 4 elementos de tipo double) y los rellena llamando a la función
OgreGetPoseParameters de la clase Board.
JgetRvec: como el atributo Rvec de tipo Mat de OpenCV es público, mediante esta
función se devuelve a Java si se desea acceder a él. El objeto de tipo Mat es creado
57
Capítulo 5. Especificación del modelo de clases
por la función de Java y se le pasa a esta función su dirección de memoria, en la
que se escribe la dirección de memoria de Rvec.
JgetTvec: como el atributo Tvec de tipo Mat de OpenCV es público, mediante esta
función se devuelve a Java si se desea acceder a él. El objeto de tipo Mat es creado
por la función de Java y se le pasa a esta función su dirección de memoria, en la
que se escribe la dirección de memoria de Tvec.
JgetBoardConf: como el atributo conf de tipo BoardConfiguration es público, mediante esta función se devuelve a Java. Creando un objeto Java de tipo BoardConfiguration y enlazándolo con el correspondiente objeto conf.
Jget: ya que Board hereda de vector <Marker>, esta función permite usar el operador [] del vector. Recibe un entero con la posición del vector que se desea devolver
y retorna el objeto Java de la clase Marker que corresponde a ese marcador.
Jsize: dado que Board hereda de vector <Marker>, esta función permite llamar a
la función size() del vector. Devuelve un entero con el tamaño del vector de marcadores.
5.2.3.
JBoardConfiguration.cpp y JBoardConfiguration.h
JBoardConfiguration__: llamada desde el constructor vacío de la clase BoardConfiguration de Java. Crea un objeto de tipo BoardConfiguration en ArUco y guarda
su dirección de memoria en el atributo nativeHandle del correspondiente objeto
BoardConfiguration de la parte Java.
JBoardConfiguration__Lwrapper_BoardConfiguration_2: constructor de copia de
la clase BoardConfiguration. Recibe como parámetro un objeto BoardConfiguration de Java del que extrae su objeto ArUco y crea un nuevo objeto BoardConfiguration usando el constructor de copia de ArUco. Después, guarda la referencia del
nuevo objeto en el de Java utilizando su atributo nativeHandle.
JsaveToFile: función que sirve para llamar al método saveToFile de la clase BoardConfiguration de ArUco. Recibe una cadena de Java como parámetro y la convierte
en una cadena legible para el objeto de C++. En caso de que haya algún problema
con la ruta en la que se desea crear el archivo, elevará una excepción a Java.
JreadFromFile: función que sirve para llamar al método readFromFile de la clase
BoardConfiguration de ArUco. Recibe una cadena de Java como parámetro y la
convierte en una cadena legible para el objeto de C++. En caso de que haya algún
problema con la ruta en la que se ha de encontrar el archivo, elevará una excepción
a Java.
58
Capítulo 5. Especificación del modelo de clases
JisExpressedInMeters: función que sirve para llamar al método isExpressedInMeters de la clase BoardConfiguration de ArUco. Devuelve un valor booleano a Java.
JisExpressedInPixels: función que sirve para llamar al método isExpressedInPixels
de la clase BoardConfiguration de ArUco. Devuelve un valor booleano a Java.
JgetIndexOfMarkerId: función que sirve para llamar al método getIndexOfMarkerId de la clase BoardConfiguration de ArUco. Recibe un entero con el identificador
del marcador en cuestión y devuelve otro entero con su índice.
JgetIdList: función que sirve para llamar al método getIdList de la clase BoardConfiguration de ArUco. Recibe un objeto que contiene un ArrayList de Java en el que
se van a incluir los identificadores de dotos los marcadores contenidos en el tablero.
Además contiene una variable booleana que indica si los valores se añadirán al final
o no. Se ocupa de introducir los identificadores en el ArrayList.
Jsize: dado que BoardConfiguration hereda de vector <MarkerInfo>, esta función
permite llamar a la función size() del vector. Devuelve un entero con el tamaño del
vector de objetos de tipo MarkerInfo.
JgetMarkerInfo: función que sirve para llamar al método getMarkerInfo de la clase
BoardConfiguration de ArUco. Recibe un entero con el identificador del objeto
MarkerInfo en cuestión y devuelve otro entero con su índice.
JgetMInfoType: como el atributo mInfoType de tipo entero es público, mediante
esta función se devuelve a Java.
Jget: dado que BoardConfiguration hereda de vector <MarkerInfo>, esta función
permite llamar a la función get() del vector. Devuelve el objeto de tipo MarkerInfo
que ocupe la posición que se le pasa como parámetro.
5.2.4.
JBoardDetector.cpp y JBoardDetector.h
JBoardDetector: llamada desde el constructor vacío de la clase BoardDetector de
Java. Crea un objeto de tipo BoardDetector en ArUco y guarda su dirección de
memoria en el atributo nativeHandle del correspondiente objeto BoardDetector de
la parte Java.
Jdetect__J: función que sirve para llamar al método detect de la clase BoardDetector de ArUco. Recibe como parámetro la dirección de un objeto Mat que contiene
la imagen en la que se ha de dtectar el tablero.
59
Capítulo 5. Especificación del modelo de clases
JgetDetectedBoard: función que sirve para llamar al método getDetectedBoard de
la clase BoardDetector de ArUco y devuelve un objeto Java de tipo Board con el
tablero detectado.
JgetMarkerDetector: función que sirve para llamar al método getMarkerDetector
de la clase BoardDetector de ArUco y devuelve un objeto Java de tipo M con el
tablero detectado.
JgetDetectedMarkers: función que sirve para llamar al método getDetectedMarkers
de la clase BoardDetector de ArUco. Recibe un ArrayList de marcadores de Java y
lo rellena con los resultados de la llamada a getDetectedMarkers.
JsetYPerpendicular: función que sirve para llamar al método setYPerpendicular de
la clase BoardDetector de ArUco. Recibe un parámetro booleano que utiliza en la
llamada a la función.
Jdetect__Ljava_util_ArrayList_2Lwrapper_BoardConfiguration_2Lwrapper_Board_2Lwrapper_CameraParameters_2F: función que sirve para llamar al método detect de la clase BoardDetector de ArUco.
Jdetect__Ljava_util_ArrayList_2Lwrapper_BoardConfiguration_2Lwrapper_Board_2JJF: función que sirve para llamar al método detect de la clase
BoardDetector de ArUco.
JsetParams__Lwrapper_BoardConfiguration_2Lwrapper_CameraParameters_2F: función que sirve para llamar al método setParams de la clase BoardDetector de ArUco. Recibe un objeto de Java del tipo BoardConfiguration, otro del tipo CameraParameters y un flotante que utiliza en la llamada a la función correspondiente.
JsetParams__Lwrapper_BoardConfiguration_2: función que sirve para llamar al
método setParams de la clase BoardDetector de ArUco. Recibe un objeto de Java
del tipo BoardConfiguration que utiliza en la llamada a la función correspondiente.
5.2.5.
JCameraParameters.cpp y JCameraParameters.h
JCameraParameters__: llamada desde el constructor vacío de la clase CameraParameters de Java. Crea un objeto de tipo CameraParameters en ArUco y guarda
su dirección de memoria en el atributo nativeHandle del correspondiente objeto
CameraParameters de la parte Java.
JCameraParameters__Lwrapper_CameraParameters_2: constructor de copia de la
clase CameraParameters. Recibe como parámetro un objeto CameraParameters de
60
Capítulo 5. Especificación del modelo de clases
Java del que extrae su objeto ArUco y crea un nuevo objeto CameraParameters
usando el constructor de copia de ArUco. Después, guarda la referencia del nuevo
objeto en el de Java utilizando su atributo nativeHandle.
JCameraParameters__JJDD: constructor parametrizado de CameraParameters que
recibe las matrices de la cámara y de distorsión, además del ancho y el alto de la
imagen.
JreadFromFile: función que sirve para llamar al método readFromFile de la clase
CameraParameters de ArUco. Recibe una cadena de Java como parámetro y la
convierte en una cadena legible para el objeto de C++. En caso de que haya algún
problema con la ruta en la que se ha de encontrar el archivo, elevará una excepción
a Java.
JisValid: función que sirve para llamar al método isValid de la clase CameraParameters de ArUco. Devuelve una variable booleana con el resultado de la llamada a
la función.
JsetParams: función que sirve para llamar al método setParams de la clase CameraParameters de ArUco.
JsaveToFile: función que sirve para llamar al método saveToFile de la clase CameraParameters de ArUco. Recibe una cadena de Java como parámetro y la convierte
en una cadena legible para el objeto de C++. En caso de que haya algún problema
con la ruta en la que se desea crear el archivo, elevará una excepción a Java.
JreadFromXMLFile: función que sirve para llamar al método readFromXMLFile de
la clase CameraParameters de ArUco. Recibe una cadena de Java como parámetro
y la convierte en una cadena legible para el objeto de C++. En caso de que haya
algún problema con la ruta en la que se desea crear el archivo, elevará una excepción
a Java.
Jresize: función que sirve para llamar al método resize de la clase CameraParameters de ArUco. Recibe dos parámetros de tipo double con la altura y la anchura.
JglGetProjectionMatrix: función que sirve para llamar al método glGetProjectionMatrix de la clase CameraParameters de ArUco.
JOgreGetProjectionMatrix: función que sirve para llamar al método OgreGetProjectionMatrix de la clase CameraParameters de ArUco.
JgetCameraLocation: función que sirve para llamar al método getCameraLocation
de la clase CameraParameters de ArUco. Recibe las direcciones de los dos objetos
61
Capítulo 5. Especificación del modelo de clases
Mat en los que se encuentran los vectores de rotación y traslación y devuelve un
objeto de la clase Point de OpenCV en Java con la posición de la cámara.
JgetCameraMatrix: como el atributo CameraMatrix de tipo Mat de OpenCV es
público, mediante esta función se devuelve a Java si se desea acceder a él. El objeto
de tipo Mat es creado por la función de Java y se le pasa a esta función su dirección
de memoria, en la que se escribe la dirección de memoria de CameraMatrix.
JgetDistorsion: como el atributo Distorsion de tipo Mat de OpenCV es público,
mediante esta función se devuelve a Java si se desea acceder a él. El objeto de tipo
Mat es creado por la función de Java y se le pasa a esta función su dirección de
memoria, en la que se escribe la dirección de memoria de Distorsion.
JgetCamSizeWidth: como el atributo CamSize de tipo Size de OpenCV es público,
mediante esta función se devuelve a Java el valor de la anchura (de tipo double) si
se desea acceder a él.
JgetCamSizeHeight: como el atributo CamSize de tipo Size de OpenCV es público,
mediante esta función se devuelve a Java el valor de la altura (de tipo double) si se
desea acceder a él.
5.2.6.
JCvDrawingUtils.cpp y JCvDrawingUtils.h
JCvDrawingUtils: llamada desde el constructor vacío de la clase CvDrawingUtils
de Java. Crea un objeto de tipo CvDrawingUtils en ArUco y guarda su dirección de
memoria en el atributo nativeHandle del correspondiente objeto CvDrawingUtils
de la parte Java.
Jdraw3dAxis__JLwrapper_Marker_2Lwrapper_CameraParameters_2: función que
sirve para llamar al método draw3dAxis de la clase CvDrawingUtils de ArUco.
Recibe un parámetro con la dirección del objeto Mat que contiene la imagen a
modificar, el objeto Java con el marcador y el objeto de tipo CameraParameters
que serán utilizados en la llamada a la función ArUco.
Jdraw3dCube__JLwrapper_Marker_2Lwrapper_CameraParameters_2: función que
sirve para llamar al método draw3dCube de la clase CvDrawingUtils de ArUco.
Recibe un parámetro con la dirección del objeto Mat que contiene la imagen a modificar, el objeto Java con el marcador y el objeto de tipo CameraParameters que
serán utilizados en la llamada a la función ArUco.
Jdraw3dAxis__JLwrapper_Board_2Lwrapper_CameraParameters_2: función que sirve para llamar al método draw3dAxis de la clase CvDrawingUtils de ArUco. Recibe
un parámetro con la dirección del objeto Mat que contiene la imagen a modificar,
62
Capítulo 5. Especificación del modelo de clases
el objeto Java con el tablero y el objeto de tipo CameraParameters que serán utilizados en la llamada a la función ArUco.
Jdraw3dCube__JLwrapper_Board_2Lwrapper_CameraParameters_2: función que
sirve para llamar al método draw3dAxis de la clase CvDrawingUtils de ArUco.
Recibe un parámetro con la dirección del objeto Mat que contiene la imagen a
modificar, el objeto Java con el tablero y el objeto de tipo CameraParameters que
serán utilizados en la llamada a la función ArUco.
5.2.7.
JFiducidalMarkers.cpp y JFiducidalMarkers.h
JcreateMarkerImage: función que sirve para llamar al método createMarkerImage
de la clase FiducidalMarkers de ArUco.
Jdetect: función que sirve para llamar al método detect de la clase FiducidalMarkers
de ArUco.
JgetMarkerMat: función que sirve para llamar al método getMarkerMat de la clase
FiducidalMarkers de ArUco.
JcreateBoardImage: función que sirve para llamar al método createBoardImage de
la clase FiducidalMarkers de ArUco.
JcreateBoardImage_1ChessBoard: función que sirve para llamar al método createBoardImage_ChessBoard de la clase FiducidalMarkers de ArUco.
JcreateBoardImage_1Frame: función que sirve para llamar al método createBoardImage_Frame de la clase FiducidalMarkers de ArUco.
5.2.8.
JMarker.cpp y JMarker.h
JMarker__: llamada desde el constructor vacío de la clase Marker de Java. Crea un
objeto de tipo Marker en ArUco y guarda su dirección de memoria en el atributo
nativeHandle del correspondiente objeto Marker de la parte Java.
JMarker__Lwrapper_Marker_2: constructor de copia de la clase Marker. Recibe
como parámetro un objeto Marker de Java del que extrae su objeto ArUco y crea
un nuevo objeto Marker usando el constructor de copia de ArUco. Después, guarda
la referencia del nuevo objeto en el de Java utilizando su atributo nativeHandle.
JMarker__Ljava_util_ArrayList_2I: constructor parametrizado de la clase que recibe el ArrayList que contiene las coordenadas de los puntos de las esquinas del
marcador
63
Capítulo 5. Especificación del modelo de clases
JisValid: función que sirve para llamar al método isValid de la clase Marker de
ArUco. Devuelve una variable booleana con el resultado de la llamada a la función.
Jdraw: función que sirve para llamar al método draw de la clase Marker de ArUco.
JglGetModelViewMatrix: función que sirve para llamar al método glGetModelViewMatrix de la clase Marker de ArUco.
JgetArea: función que sirve para llamar al método getArea de la clase Marker de
ArUco.
JgetPerimeter: función que sirve para llamar al método getPerimeter de la clase
Marker de ArUco.
JgetCenter: función que sirve para llamar al método getCenter de la clase Marker
de ArUco.
JcalculateExtrinsics__FLwrapper_CameraParameters_2Z: función que sirve para
llamar al método calculateExtrinsics de la clase Marker de ArUco.
JcalculateExtrinsics__FJJZ: función que sirve para llamar al método calculateExtrinsics de la clase Marker de ArUco.
JOgreGetPoseParameters: función que sirve para llamar al método OgreGetPoseParameters de la clase Marker de ArUco.
JgetRvec: como el atributo Rvec de tipo Mat de OpenCV es público, mediante esta
función se devuelve a Java si se desea acceder a él. El objeto de tipo Mat es creado
por la función de Java y se le pasa a esta función su dirección de memoria, en la
que se escribe la dirección de memoria de Rvec.
JgetTvec: como el atributo Tvec de tipo Mat de OpenCV es público, mediante esta
función se devuelve a Java si se desea acceder a él. El objeto de tipo Mat es creado
por la función de Java y se le pasa a esta función su dirección de memoria, en la
que se escribe la dirección de memoria de Tvec.
JgetId: como el atributo id de tipo entero es público, mediante esta función se devuelve a Java si se desea acceder a él.
JgetSSize: como el atributo ssize de tipo float es público, mediante esta función se
devuelve a Java si se desea acceder a él.
JlessThan: recibe un objeto de tipo Marker como parámetro y lo compara con el
objeto desde el que se llama utilizando el operador “menor que”. Si el objeto desde
el que se llama es menor, devuelve verdadero, en caso contrario, devuelve falso.
64
Capítulo 5. Especificación del modelo de clases
JtoString: devuelve una cadena de Java con el texto que retornaría el objeto ArUco
al utilizar el operador << de la clase Marker de Aruco.
Jsize: dado que Marker hereda de vector <Point2f>, esta función permite llamar a
la función size() del vector. Devuelve un entero con el tamaño del vector.
Jget: dado que Marker hereda de vector <Point2f>, esta función permite llamar a
la función get() del vector. Devuelve el objeto de tipo Point de OpenCV de Java que
ocupe la posición que se le pasa como parámetro.
5.2.9.
JMarkerDetector.cpp y JMarkerDetector.h
JMarkerDetector__: llamada desde el constructor vacío de la clase MarkerDetector
de Java. Crea un objeto de tipo MarkerDetector en ArUco y guarda su dirección de
memoria en el atributo nativeHandle del correspondiente objeto MarkerDetector
de la parte Java.
JMarkerDetector__Lwrapper_MarkerDetector_2: constructor de copia de la clase
MarkerDetector. Recibe como parámetro un objeto MarkerDetector de Java del
que extrae su objeto ArUco y crea un nuevo objeto MarkerDetector usando el constructor de copia de ArUco. Después, guarda la referencia del nuevo objeto en el de
Java utilizando su atributo nativeHandle.
Jdetect__JLjava_util_ArrayList_2JJFZ: función que sirve para llamar al método detect de la clase MarkerDetectorde ArUco.
Jdetect__JLjava_util_ArrayList_2Lwrapper_CameraParameters_2FZ:
JgetDesiredSpeed: función que sirve para llamar al método OgreGetPoseParameters de la clase MarkerDetector de ArUco.
JsetDesiredSpeed: función que sirve para llamar al método setDesiredSpeed de la
clase MarkerDetector de ArUco.
JsetThresholdMethod: función que sirve para llamar al método setThresholdMethod
de la clase MarkerDetector de ArUco.
JgetThresholdMethod: función que sirve para llamar al método getThresholdMethod de la clase MarkerDetector de ArUco.
JsetThresholdParams: función que sirve para llamar al método setThresholdParams
de la clase MarkerDetector de ArUco.
JgetThresholdParam1: función que sirve para llamar al método getThresholdParam1 de la clase MarkerDetector de ArUco.
65
Capítulo 5. Especificación del modelo de clases
JgetThresholdParam2: función que sirve para llamar al método getThresholdParam2 de la clase MarkerDetector de ArUco.
JgetThresholdedImage: función que sirve para llamar al método getThresholdedImage de la clase MarkerDetector de ArUco.
JsetCornerRefinementMethod: función que sirve para llamar al método setCornerRefinementMethod de la clase MarkerDetector de ArUco.
JgetCornerRefinementMethod: función que sirve para llamar al método getCornerRefinementMethod de la clase MarkerDetector de ArUco.
JsetMinMaxSize: función que sirve para llamar al método setMinMaxSize de la
clase MarkerDetector de ArUco.
JgetMinSize: función que sirve para llamar al método getMinSize de la clase MarkerDetector de ArUco.
JgetMaxSize: función que sirve para llamar al método getMaxSize de la clase MarkerDetector de ArUco.
JenableErosion: función que sirve para llamar al método enableErosion de la clase
MarkerDetector de ArUco.
JpyrDown: función que sirve para llamar al método pyrDown de la clase MarkerDetector de ArUco.
5.2.10.
JMarkerInfo.cpp y JMarkerInfo.h
JMarkerInfo__: llamada desde el constructor vacío de la clase MarkerInfo de Java.
Crea un objeto de tipo MarkerInfo en ArUco y guarda su dirección de memoria en
el atributo nativeHandle del correspondiente objeto MarkerInfo de la parte Java.
JMarkerInfo__I: constructor parametrizado de MarkerInfo que recibe un entero con
el identificador del marcador que se desea crear.
JMarkerInfo__Lwrapper_MarkerInfo_2: constructor de copia de la clase MarkerInfo. Recibe como parámetro un objeto MarkerInfo de Java del que extrae su objeto
ArUco y crea un nuevo objeto MarkerInfo usando el constructor de copia de ArUco.
Después, guarda la referencia del nuevo objeto en el de Java utilizando su atributo
nativeHandle.
JgetId: función que sirve para llamar al método getId de la clase MarkerInfo de
ArUco. Devuelve el identificador del marcador en cuestión.
66
Capítulo 5. Especificación del modelo de clases
Jsize: dado que MarkerInfo hereda de vector <Point2f>, esta función permite llamar
a la función size() del vector. Devuelve un entero con el tamaño del vector.
Jget: dado que MarkerInfo hereda de vector <Point2f>, esta función permite llamar
a la función get() del vector. Devuelve el objeto de tipo Point de OpenCV de Java
que ocupe la posición que se le pasa como parámetro.
5.3.
Análisis de los programas Java de ejemplo
Con un objetivo tanto didáctico como demostrativo del buen funcionamiento de la
librería se han incluido ciertas aplicaciones de ejemplo que intentan ofrecer las mismas
funcionalidades que las aplicaciones de ejemplo de la librería ArUco original. Estas utilidades son:
arucoCreateBoard
arucoCreateMarker
arucoSimple
arucoSimpleBoard
5.3.1.
arucoCreateBoard
En esta utilidad se hace uso de las clases BoardConfiguration y FiducidalMarkers.
La aplicación crea un tablero con el tamaño que se le pasa como parámetro y lo guarda
en un archivo de imagen. Además, guarda la configuración del tablero en un fichero que
también se le pasa como parámetro. Además, los tableros pueden crearse de tipo panel,
chessboard o frame; según se indique en el quinto parámetro. Utilizando el siguiente
comando llamamdo a arucoCreateBoard:
1
2
arucoCreateBoard 5 : 6 boardImage . png
boardConfiguration . yml 200 0
Se obtiene la siguiente imagen denominada boardImage.png como se ha indicado en la
llamada por línea de comandos:
67
Capítulo 5. Especificación del modelo de clases
Figura 5.9: Imagen con el tablero resultado de arucoCreateBoard
Además, se obtiene el archivo boardConfiguration.yml con la información de configuración del tablero. En él se incluye el número de marcadores, el tipo de tablero que es
y los identificadores y posición de las esquinas de los marcadores en la imagen. No se
incluirá por completo debido a su tamaño, pero el comienzo del fichero es el siguiente:
1
2
3
4
5
6
7
8
9
10
%YAML : 1 . 0
aruco_bc_nmarkers : 30
aruco_bc_mInfoType : 0
aruco_bc_markers :
− { id : 9 3 9 , corners : [ [ −580. , −700. , 0 .
[ −380. , −700. , 0 . ] , [ − 3 8 0 . , −500. , 0 .
[ −580. , −500. , 0 . ] ] }
− { id : 1 1 1 , corners : [ [ −340. , −700. , 0 .
[ −140. , −700. , 0 . ] , [ − 1 4 0 . , −500. , 0 .
[ −340. , −500. , 0 . ] ] }
],
],
],
],
El fichero sigue con los identificadores y la posición de las esquinas de todos y cada
uno de los marcadores que aparecen en el tablero.
5.3.2.
arucoCreateMarker
Esta aplicación utiliza la clase FiducidalMarkers para crear la imagen de un marcador
cuyo identificador se le pasa como parámetro de la línea de comandos al invocar al programa. Además, también se le pasa el nombre del fichero que queremos tener como salida
68
Capítulo 5. Especificación del modelo de clases
y el tamaño en píxeles del lado del marcador. En caso de que se llame a esta utilidad del
siguiente modo en la línea de comandos:
1
arucoCreateMarker 23 marker23 . jpg 50
Se obtendrá como salida el fichero denominado marker23.jpg que contiene la imagen
siguiente:
Figura 5.10: Marcador con el identificador 23 creado por arucoCreateMarker
5.3.3.
arucoSimple
Esta aplicación recibe como parámetro una imagen con un conjunto de marcadores y
haciendo uso de las clases CameraParameters, CvDrawingUtils, MarkerDetector y Marker, detecta los marcadores que contiene la imagen. Además, dibuja un cuadrado en los
bordes de cada marcador, muestra su identificador, y un cubo sobre los mismos. El comando utilizado para ejecutar esta aplicación es el siguiente:
1
2
arucoSimple . / RESULTS / TESTDATA / image−test . png
. / RESULTS / TESTDATA / intrinsics . yml 5 arucoSimple . png
Como resultado, se muestran en pantalla tanto la imagen con los marcadores detectados
como la imagen umbralizada y se guarda la imagen de salida que se muestra a continuación:
69
Capítulo 5. Especificación del modelo de clases
Figura 5.11: Imagen resultado de ejecutar arucoSimple
5.3.4.
arucoSimpleBoard
Esta utilidad utiliza las clases CameraParameters, MarkerDetector, Marker, BoardConfiguration, BoardDetector, CvDrawingUtils y Board. Recibe una imagen que contiene un tablero, además de la configuración del mismo. También puede incluir los parámetros de la cámara, el tamaño del lado de los marcadores y un nombre base de fichero para
la salida. La aplicación detecta los marcadores y el tablero en la imagen, dibuja el borde
de los marcadores y su identificador, y un eje con la posición 3D del tablero.
1
2
3
4
. / RESULTS / TESTDATA / image−test . png
. / RESULTS / TESTDATA / board_pix . yml
. / RESULTS / TESTDATA / intrinsics . yml
5 SimpleBoard . png
Como resultado, se muestran en pantalla tanto la imagen con el tablero y los marcadores
detectados. Aparecen los ejes tanto del tablero como de los marcadores y se guarda la
imagen de salida que se muestra a continuación:
70
Capítulo 5. Especificación del modelo de clases
Figura 5.12: Imagen resultado de ejecutar arucoSimpleBoard
71
Capítulo 6
Diagramas de secuencia
Con estos diagramas de secuencia va a explicarse la forma de proceder de la librería
con respecto a algunas acciones relevantes tales como:
Creación de un objeto
Llamada a un método con modificación de parámetros
Llamada a un método que escribe en disco
Llamada a un método que lee desde el disco
6.1.
Creación de un objeto
En esta sección se va a mostrar cómo se llama al constructor de una clase, en concreto
MarkerDetector y cómo esta llamada es transmitida por las distintas capas de la librería
hasta el código nativo de ArUco. Los pasos son los siguientes:
1. El programador llama desde el programa principal al constructor vacío de MarkerDetector.
2. Este constructor, dentro de la clase Java llama a la función del “wrapper” de C++
JMarkerDetector
3. Dentro de esa función se llama al constructor de MarkerDetector de ArUco.
4. Este constructor crea y devuelve un objeto MarkerDetector de Aruco.
5. La función del “wrapper” de C++ se ocupa de cambiar el atributo de la clase Java
nativeHandle para que contenga la dirección de memoria del objeto ArUco creado.
Esto garantiza que se pueda volver a acceder a ese objeto en concreto desde Java.
6. La función del constructor de Java devuelve el objeto MarkerDetector de Java (que
ya referencia al objeto ArUco) al programa principal
73
Capítulo 6. Diagramas de secuencia
Figura 6.1: Diagrama de secuencia del constructor de MarkerDetector
6.2.
Llamada a un método con modificación de parámetros
A continuación se mostrará cómo, usando el objeto que se ha creado anteriormente, se
realiza una llamada a función. En este caso se va a llamar a la función detect de MarkerDetector que, en la parte Java, recibe un objeto Mat de OpenCV con una imagen en la que
se han de detectar marcadores y un ArrayList de objetos de tipo Marker que se rellenará
con la información de los marcadores detectados. Los pasos que se siguen son:
1. El programador llama desde el programa principal al método detect del objeto MarkerDetector anteriormente creado. Como primer parámeetro le pasa una imagen de
tipo Mat de OpenCV y como segundo parámetro un ArrayList <Marker> en el que
se desean guardar los marcadores que se encuentren.
2. Dentro del método detect de Java se llama a la función nativa del “wrapper” de
C++ JDetect que se encuentra en el fichero JMarkerDetector.cpp. Se le pasa la
dirección del objeto tipo Mat mediante la función getObjectNativeAddr de esa clase
y el objeto ArrayList de Java.
3. En la función del “wrapper” se crea un puntero a Mat para poder acceder a la imagen y un vector de marcadores de ArUco. De este modo se le pasa el contenido del
puntero a Mat y el vector de marcadores al método detect del objeto MarkerDetector asociado al objeto Java que llamó a esta función. Esto se realiza mediante un
acceso a la variable nativeHandle.
74
Capítulo 6. Diagramas de secuencia
4. Dentro de ArUco se ejecuta el método detect y se devuelve el vector de objetos
Marker al “wrapper”.
5. La función del “wrapper” se ocupa de recorrer el vector de objetos Marker y añadirlos al ArrayList de Java.
6. En el programa principal se puede contar, tras la ejecución de este método con el
ArrayList que contiene los objetos Marker de Java.
Figura 6.2: Diagrama de secuencia de la función detect de MarkerDetector
6.3.
Llamada a un método que escribe en disco
En esta sección se podrá observar cómo realiza la escritura en disco desde la librería.
Se va a utilizar como ejemplo la función saveToFile de la clase Board. Los pasos que se
siguen son:
1. Una vez se tiene un objeto de tipo Board creado, el programador llama a su método
saveToFile y le pasa como parámetro una cadena de tipo String de Java con la ruta
donde quiere que se guarde la información del tablero.
2. El método correspondiente de Java llama a la función nativa JsaveToFile del “wrapper” de C++ y le pasa el String.
3. Dentro del “wrapper”, se obtienen los caracteres de la cadena mediante la función
de JNI GetStringUTFChars y se guardan en un char * que ArUco puede procesar.
75
Capítulo 6. Diagramas de secuencia
4. Se realiza la llamada al método saveToFile del objeto Board de ArUco enlazado
con el de Java por medio de nativeHandle. Se le pasa como parámetro el char * ya
citado.
5. El método de ArUco realiza la escritura en disco y, en caso de haber algún problema
de apertura del archivo elevará una excepción que llega a Java.
Figura 6.3: Diagrama de secuencia de la función saveToFile de Board
6.4.
Llamada a un método que lee desde el disco
En esta sección se muestra cómo se realiza la lectura desde disco en la librería. Se
va a utilizar como ejemplo la función readFromFile de la clase Board. Los pasos que se
siguen son:
1. Una vez se tiene un objeto de tipo Board creado, el programador llama a su método
readFromFile y le pasa como parámetro una cadena de tipo String de Java con la
ruta donde se encuentra el fichero que se desea leer.
2. El método correspondiente de Java llama a la función nativa JreadFromFile del
“wrapper” de C++ y le pasa el String.
3. Dentro del “wrapper”, se obtienen los caracteres de la cadena mediante la función
de JNI GetStringUTFChars y se guardan en un char * que ArUco puede procesar.
76
Capítulo 6. Diagramas de secuencia
4. Se realiza la llamada al método readFromFile del objeto Board de ArUco enlazado
con el de Java por medio de nativeHandle. Se le pasa como parámetro el char * ya
citado.
5. El método de ArUco realiza la lectura de disco y, en caso de haber algún problema
de apertura del archivo elevará una excepción que llega a Java. En caso de que todo
vaya bien, el objeto Board de ArUco habrá cargado la nueva información que será
accesible desde Java gracias a la variable nativeHandle.
Figura 6.4: Diagrama de secuencia de la función readFromFile de Board
77
Capítulo 7
Diagrama de paquetes
Debido al tamaño de la librería se va a dividir conceptualmente en los siguientes paquetes:
Clases Java:
• Wrapper: estas son las clases que utilizarán los programadores que hagan uso
de la librería. Tienen los mismos nombres que las clases de ArUco en C++ y
serán cargadas en sus programas. Dentro se encuentran los ficheros:
◦ Board.java
◦ BoardConfiguration.java
◦ BoardDetector.java
◦ CameraParameters.java
◦ CvDrawingUtils.java
◦ FiducidalMarkers.java
◦ Marker.java
◦ MarkerDetector.java
◦ MarkerInfo.java
• Ejemplos: son un conjunto de programas de prueba que permitirán a los desarrolladores hacerse una idea del funcionamiento de la librería. Dentro se encuentran los ficheros:
• arucoCreateBoard.java
• arucoCreateMarker.java
• arucoSimple.java
• arucoSimpleBoard.java
Wrapper C++:
79
Capítulo 7. Diagrama de paquetes
• Handle.h: es el fichero encargado de ofrecer las funciones para mantener la
relación entre los objetos Java y sus objetos ArUco subyacentes.
• Ficheros “wrapper”: son los que se encargan de realizar las transformaciones
de los parámetros de entrada, las llamadas a las funcione ArUco y las transformaciones y devoluciones de los resultados. Dentro se encuentran los ficheros:
◦ JBoard.cpp y JBoard.h
◦ JBoardConfiguration.cpp y JBoardConfiguration.h
◦ JBoardDetector.cpp y JBoardDetector.h
◦ JCameraParameters.cpp y JCameraParameters.h
◦ JCvDrawingUtils.cpp y JCvDrawingUtils.h
◦ JFiducidalMarkers.cpp y JFiducidalMarkers.h
◦ JMarker.cpp y JMarker.h
◦ JMarkerDetector.cpp y JMarkerDetector.h
◦ JMarkerInfo.cpp y JMarkerInfo.h
80
Capítulo 7. Diagrama de paquetes
7.1.
Diagrama general de paquetes
El diagrama de paquetes es el siguiente:
Figura 7.1: Diagrama de paquetes de la librería
81
Capítulo 8
Pruebas
En este capítulo se van a describir las pruebas realizadas a la librería fruto de este
proyecto, para cerciorarse de que su funcionamiento es el correcto, y de que se trata de
una librería robusta y amigable.
Debido a que es imposible comprobar un software por completo, las pruebas han de
hacerse de manera que se comprueben las líneas de programa con más probabilidad de
contener o producir errores, como son: leer variables sin inicializar, controlar la condición
de parada de bucles, comprobar el último y penúltimo valor de una variable que se incrementa o decrementa en un bucle, probar todas las combinaciones de valores de variables
usadas en una condición, etcétera.
Durante el proceso de codificación de la librería, se han ido realizando pruebas “sobre la marcha” para comprobar que cada parte de la misma estaba bien codificada. No
obstante, este método de trabajo no es suficiente para eliminar todos los errores, ya que
algunos han podido ser pasados por alto y otros pueden deberse a la interacción entre unos
módulos y otros.
Por tanto, la división modular para la realización de las pruebas es:
Módulo de “Clases de Java”: donde las funciones a las que se ha prestado mayor
atención han sido a las de creación y detección de marcadores
Módulo de “Wrapper en C++”: donde se ha prestado especial atención a la transformación de los datos desde Java a C++ y viceversa.
Módulo de “Programas de prueba”: donde se ha tenido especial cuidado en la carga
y guardado de ficheros.
Pruebas de funcionamiento en varios sistemas operativos: se han realizado pruebas
en Windows 7, Kubuntu 14.10.
83
Capítulo 8. Pruebas
8.1.
Clases de Java
Se han realizado pruebas sobre cada clase y cada método, comprobando que se reciben
los parámetros correctamente y que se devuelven los valores esperados. Además, se han
realizado los siguientes cambios:
En un principio se utilizaron para los métodos Java parámetros lo más parecidos
posibles a los que recibirían las funciones de C++. Sin embargo, tras realizar las
pruebas se ha estimado conveniente propiciar algunos cambios para obtener como
resultado unos parámetros que sigan más la filosofía de funcionamiento de Java.
Un ejemplo de este hecho es la utilización de la clase “ArrayList” de Java, ya que
se comenzó utilizando vectores de objetos pero se ha estimado más conveniente
utilizar “ArrayList” porque puede ser más cómodo de manejar para los usuarios
que utilizan Java normalmente. Como ejemplo puede observarse la llamada a la
función detect de la clase MarkerDetector en la que se utiliza ArrayList en lugar de
vector:
1
p u b l i c v o i d detect ( Mat input , ArrayList<Marker> ←detectedMarkers ) ;
Posteriormente, en la parte de C++ hace falta crear un vector de marcadores (línea
18) para mandarlo a la función detect (línea 21), después, se utilizan las funciones de JNI para poder llamar al método add de ArrayList y copiar en él los datos
obtenidos de la función (línea 34). El código es el siguiente:
1
2
3
4
JNIEXPORT v o i d JNICALL ←Java_wrapper_MarkerDetector_Jdetect__JLjava_util_ArrayList_2JJFZ←( JNIEnv * env , jobject obj , jlong inputAddr , jobject ←detectedMarkers , jlong camMatrixAddr , jlong distCoeffAddr , ←jfloat markerSizeMeters , jboolean setYPerpendicular ) {
MarkerDetector * inst = getHandle<MarkerDetector > ( env , obj ) ;
/ / use th e Array l i s t
jclass ArrayList_class = env−>FindClass ( " j a v a / u t i l / ←ArrayList " ) ;
5
6
jclass Marker_class = env−>FindClass ( " w r a p p e r / Marker " ) ;
7
8
jmethodID Add_method = env−>GetMethodID ( ArrayList_class , " add←" , " ( L j a v a / l a n g / O b j e c t ; ) Z" ) ;
9
10
jmethodID Marker_Constructor_method = env−>GetMethodID ( ←Marker_class , " < i n i t > " , " ( ) V" ) ;
84
Capítulo 8. Pruebas
jmethodID Marker_Copy_Constructor_method = env−>GetMethodID ( ←Marker_class , " < i n i t > " , " ( L w r a p p e r / Marker ; ) V" ) ;
11
12
13
cv : : Mat * input = ( cv : : Mat * ) inputAddr ;
cv : : Mat * camMatrix = ( cv : : Mat * ) camMatrixAddr ;
cv : : Mat * distCoeff = ( cv : : Mat * ) distCoeffAddr ;
14
15
16
17
std : : vector <Marker> vMarkers ;
18
19
try {
20
inst−>detect ( * input , vMarkers , * camMatrix , * distCoeff , ←markerSizeMeters , setYPerpendicular ) ;
} c a t c h ( cv : : Exception e ) {
newJavaException ( env , " j a v a / l a n g / E x c e p t i o n " , e . what ( ) ) ;
}
jobject newMarkers [ vMarkers . size ( ) ] ;
21
22
23
24
25
26
27
f o r ( i n t i = 0 ; i< vMarkers . size ( ) ; i++) {
Marker * markPtr = &vMarkers [ i ] ;
jobject dummy = env−>NewObject ( Marker_class , ←Marker_Constructor_method ) ;
setHandle ( env , dummy , markPtr ) ;
28
29
30
31
32
newMarkers [ i ] = env−>NewObject ( Marker_class , ←Marker_Copy_Constructor_method , dummy ) ;
env−>CallBooleanMethod ( detectedMarkers , Add_method , ←newMarkers [ i ] ) ;
env−>DeleteLocalRef ( newMarkers [ i ] ) ;
env−>DeleteLocalRef ( dummy ) ;
}
33
34
35
36
37
38
env−>DeleteLocalRef ( ArrayList_class ) ;
env−>DeleteLocalRef ( Marker_class ) ;
39
40
41
42
}
Algunas funciones de ArUco reciben dos parámetros por referencia para ser modificados, se ha estimado oportuno separar esto en dos funciones de Java que no reciben parámetros pero devuelven el valor. Por ejemplo, en la clase MarkerDetector
de ArUco existe la función getMinMaxSize que recibe por referencia dos variables
de tipo flotante para modificarlas. Se ha estimado más acorde con la filosofía de
Java dividir esta función en las dos funciones siguientes:
85
Capítulo 8. Pruebas
1
2
p u b l i c f l o a t getMinSize ( ) ;
p u b l i c f l o a t getMaxSize ( ) ;
De este modo, el valor será devuelto (y puede ser guardado en una variable) pero se
utiliza un estilo de programación más acorde con la forma de proceder en Java.
Parámetros por defecto: algunas funciones de la librería ArUco permiten usar algunos parámetros con valores por defecto y Java no permite esta funcionalidad.
Al hacer las pruebas y percibirse este hecho se ha intentado “simular” este tipo
de llamadas creando diferentes funciones que incluyen esos valores por defecto.
Por ejemplo, en la clase Marker de ArUco la definición de la función draw es la
siguiente:
v o i d draw ( cv : : Mat &in , cv : : Scalar color , i n t lineWidth=1 ,←b o o l writeId= t r u e ) ;
1
Se ha optado por crear las siguientes tres funciones en Java:
p u b l i c v o i d draw ( Mat img , Scalar color , i n t lineWidth , ←boolean writeId ) {
Jdraw ( img . getNativeObjAddr ( ) , color . val , lineWidth , ←writeId ) ;
1
2
3
}
4
5
6
7
p u b l i c v o i d draw ( Mat img , Scalar color , i n t lineWidth ) {
Jdraw ( img . getNativeObjAddr ( ) , color . val , lineWidth , t r u e ←);
}
8
9
10
11
p u b l i c v o i d draw ( Mat img , Scalar color ) {
Jdraw ( img . getNativeObjAddr ( ) , color . val , 1 , t r u e ) ;
}
De este modo, aunque no se simula totalmente el uso de los parámetros con valores
por defecto, sí que pueden realizarse algunas llamadas a función más cómodas al
programador y que respeten los valores por defecto que se usan en ArUco.
Acceso a los atributos de objetos de ArUco: se han creado funciones “get” y “set”
para poder acceder a los atributos públicos de los objetos de ArUco.
Acceso a las funciones de los vectores: dado que varias clases de ArUco heredan
de la clase vector de C++ se han implementado los métodos “get” y “size” en las
clases Java que las representan.
86
Capítulo 8. Pruebas
8.2.
“Wrapper” en C++
Dentro de esta parte de la librería se han realizado pruebas de funcionamiento sobre
todos sus ficheros y se ha prestado especial atención a los siguientes hechos:
Mantenimiento de la relación entre objetos Java y C++: este punto fue crítico a la
hora de comenzar el proyecto. Se ha utilizado una variable de tipo “long” en los
objetos Java denominada “nativeHandle” en la que se ha guardado la dirección de
memoria de los objetos de C++. De este modo se mantiene una relación entre los
objetos de los dos lenguajes y se evita que los objetos de C++ se “pierdan”. Esta
variable es modificada por las funciones que se encuentran en el fichero “Handle.h”.
Transformación de los parámetros recibidos desde Java a los parámetros que han de
recibir las funciones de ArUco: se ha puesto especial cuidado en que los parámetros
no se modifiquen al cambiar los tipos por aquellos necesarios para ArUco. Algunos
ejemplos son los siguientes:
• Tipos básicos: el paso de tipos básicos es muy simple como enteros, booleanos, flotantes, etc. es bastante sencillo con JNI ya que pueden utilizarse
directamente.
• Tipo Mat de OpenCV: para pasar las imágenes desde Java al “wrapper” de
C++ sin que se tenga que realizar una copia de las mismas en memoria se
investigó el funcionamiento de la clase Mat y se descubrió la existencia de la
función getNativeObjAddr que devuelve la dirección de memoria del objeto
Mat de OpenCV en C++. De este modo, se pasa al lado de C++ solamente la
dirección de memoria. Se puede tomar como ejemplo el método draw de la
clase Marker. En la clase de Java se recibe el objeto de tipo Mat pero, como se
puede observar, a la función JDraw de C++ se le pasa la dirección del objeto
nativo de forma transparente al usuario que llama a draw:
1
2
3
p u b l i c v o i d draw ( Mat img , Scalar color ) {
Jdraw ( img . getNativeObjAddr ( ) , color . val , 1 , t r u e ) ;
}
Posteriormente, cuando la dirección llega a C++ se crea un puntero al objeto
Mat y se le hace apuntar a la dirección que ha sido pasada como parámetro
(línea 3). Después, puede pasarse el contenido de ese puntero a la función
draw de ArUco (línea 10) como se observa a continuación:
87
Capítulo 8. Pruebas
JNIEXPORT v o i d JNICALL Java_wrapper_Marker_Jdraw ( JNIEnv * ←env , jobject obj , jlong img , jdoubleArray color , ←jint lineWidth , jboolean writeId ) {
Marker * m = getHandle<Marker > ( env , obj ) ;
cv : : Mat * inMat = ( cv : : Mat * ) img ;
1
2
3
4
d o u b l e buf [ 4 ] ;
env−>GetDoubleArrayRegion ( color , 0 , 4 , buf ) ;
5
6
7
Scalar scColor = Scalar ( buf [ 0 ] , buf [ 1 ] , buf [ 2 ] , buf [ 3 ] ) ;
8
9
m−>draw ( * inMat , scColor , lineWidth , writeId ) ;
10
11
}
Transformación y devolución de los resultados hacia Java: los valores y tipos devueltos han sido comprobados desde la parte Java de la librería. En el caso de algunos tipos devueltos ha sido más sencillo crear los objetos Java y devolverlos gracias
a las herramientas que ofrece JNI. Algunos ejemplos son los siguientes:
• Tipo Point de OpenCV: para mostrar cómo se ha resuelto la devolución de
datos desde OpenCV se va a mostrar cómo se devuelve un punto en la función
getCenter de la clase Marker. La llamada es la siguiente:
1
2
3
p u b l i c Point getCenter ( ) {
r e t u r n JgetCenter ( ) ;
}
Una vez más, para el usuario de la librería es transparente y solamente sabe
que se devuelve un objeto de tipo Point de OpenCV de Java. Sin embargo,
en el lado de C++ la cosa se complica ya que no se puede devolver un objeto
Point de C++ y esperar que Java lo reconozca como tal. De hecho, la solución
por la que se ha optado es la de crear un objeto Point de C++ para recibir el
resultado de la llamada a ArUco (línea 3), crear el objeto de Java (líneas 5 a 7)
y devolverlo (línea 11). Esto puede hacerse gracias a las funciones que ofrece
JNI. El código es el siguiente:
1
2
3
JNIEXPORT jobject JNICALL Java_wrapper_Marker_JgetCenter ( ←JNIEnv * env , jobject obj ) {
Marker * m = getHandle<Marker > ( env , obj ) ;
Point a = m−>getCenter ( ) ;
4
5
jclass Point_class = env−>FindClass ( " o r g / o p e n c v / c o r e / ←Point " ) ;
88
Capítulo 8. Pruebas
jmethodID constructor = env−>GetMethodID ( Point_class , " <←i n i t > " , " (DD)V" ) ;
jobject returnedPoint = env−>NewObject ( Point_class , ←constructor , ( jdouble ) a . x , ( jdouble ) a . y ) ;
6
7
8
env−>DeleteLocalRef ( Point_class ) ;
9
10
r e t u r n returnedPoint ;
11
12
}
Creación y modificación de objetos Java desde C++: JNI provee de herramientas
que permiten hacer referencia a clases y objetos Java. Dentro de la parte de C++ se
ha puesto especial cuidado a la hora de utilizar estas herramientas.
8.3.
Programas de prueba
Se intentaron realizar programas parecidos a los que se ofrecen con la librería ArUco.
De este modo, podía probarse el correcto funcionamiento de la librería, intentando que
los resultados fueran lo más parecidos posible a los de la librería en código nativo. Se
observaron algunos problemas dependientes de OpenCV debido a que la gestión de vídeo
no está tan depurada en Java como en C++. Por ejemplo, se tuvo que renunciar a la
utilización de VideoCapture porque no permite cargar vídeos. Además, las pruebas con
estos programas fueron de gran utilidad para encontrar errores en las clases Java y en el
código C++.
8.4.
Pruebas de funcionamiento en varios sistemas operativos
Se han realizado pruebas en los siguientes sistemas operativos:
Windows 7
Kubuntu 14.10
Se ha comprobado el correcto funcionamiento de la librería en ambas plataformas.
89
Capítulo 9
Conclusiones y futuras mejoras
9.1.
Conclusiones
La principal conclusión del presente proyecto de fin de carrera es la siguiente: se
ha realizado un wrapper mediante JNI que permite utilizar las funciones de la librería
ArUco desde Java. Los siguientes objetivos planteados al comienzo del proyecto se han
cumplido:
La librería ofrece la posibilidad de ser utilizada en Java.
La librería ofrece las mismas funcionalidades que ArUco, siendo las más importantes:
• Creación de marcadores
• Creación de tableros
• Detección de marcadores
• Detección de tableros
• Funciones que permitan dibujar señales que demuestren el reconocimiento de
los marcadores y tableros, tales como sus bordes, identificadores, ejes tridimensionales, etc.
La ejecución del código se realiza en lenguaje nativo, directamente en la propia
ArUco.
La librería viene acompañada con varios ejemplos que muestran su utilidad y funcionamiento, con el objetivo de que puedan ser utilizados con una función didáctica.
Se ha obtenido tanto una librería para sistemas Linux como para sistemas Windows
91
Capítulo 9. Conclusiones y futuras mejoras
9.2.
Futuras mejoras
Aunque, como se ha visto en el capítulo anterior, la aplicación cumple tanto el objetivo
principal como los secundarios, se estima que hay varias mejoras que podrían ser de
utilidad de cara a mejorar este programa en el futuro.
Las mejoras que se podrían hacer son:
Programar la función setMarkerDetectorFunction: dentro de MarkerDetector, se
encuentra la función setMarkerDetectorFunction que recibe una función como parámetro. Debido a la dificultad para hacer esta llamada desde Java se ha dejado
como futura mejora. Probablemente, el mejor modo de hacer esto sería enviar un
objeto encargado de realizar el proceso.
Ampliar el número de Sistemas Operativos en los que funciona la librería: debido
a la importancia de los dispositivos móviles sería realmente interesante poder conseguir que la librería funcione tanto para Android como para iOS, además de Mac
OS.
Traducción de la documentación a otros idiomas: sería interesante traducir la documentación y ayuda, además del Manual de Usuario a otros idiomas como por
ejemplo el inglés. De este modo se podría llegar a más usuarios y que tuvieran
menos dificultad a la hora de iniciarse con esta librería.
Ampliar el número de Sistemas Operativos en los que funciona la librería: debido
a la importancia de los dispositivos móviles sería realmente interesante poder conseguir que la librería funcione tanto para Android como para iOS, además de Mac
OS.
Programa de ejemplo con interfaz gráfica: para acercar la Realidad Aumentada a
las personas con menos capacidades de programación podría ser interesante realizar una aplicación con interfaz gráfica que permitiera crear e imprimir tanto marcadores como tableros y, posteriormente, detectarlos y mostrar sobre ellos alguna
información.
92
Bibliografía
[1] Oliver Bimber, Ramesh Raskar. “Spatial Augmented Reality”. Ed AK Peters, 2005.
[2] Página web de learnAR http://www.learnar.org/. Fecha de última consulta:
11 de agosto de 2014.
[3] Página web de Google Sky Map http://www.google.com/mobile/
skymap/. Fecha de última consulta: 11 de agosto de 2014.
[4] Página web de blippAR http://blippar.com. Fecha de última consulta: 11 de
agosto de 2014.
[5] Página web de Ingress https://www.ingress.com/. Fecha de última consulta:
11 de agosto de 2014.
[6] Página web de Quest Visual, creadores de Word Lens http://questvisual.
com/. Fecha de última consulta: 11 de agosto de 2014.
[7] Página web de ArUco http://www.uco.es/investiga/grupos/ava/
node/26. Fecha de última consulta: 11 de agosto de 2014.
[8] Página web de OpenCV http://opencv.org/. Fecha de última consulta: 11 de
agosto de 2014.
[9] Página web de Java http://java.com/es/. Fecha de última consulta: 11 de
agosto de 2014.
[10] Página web de ARToolKit en SourceForge http://artoolkit.
sourceforge.net/. Fecha de última consulta: 11 de agosto de 2014.
[11] Página web de ARLab http://www.arlab.com/. Fecha de última consulta:
11 de agosto de 2014.
[12] Página web de droidAR https://github.com/bitstars/droidar. Fecha de última consulta: 11 de agosto de 2014.
[13] Página web de GRATF http://www.aforgenet.com/projects/
gratf/. Fecha de última consulta: 11 de agosto de 2014.
93
BIBLIOGRAFÍA
[14] Página web de js-aruco https://code.google.com/p/js-aruco/. Fecha
de última consulta: 16 de agosto de 2014.
94