miércoles, 14 de mayo de 2014

Modificamos nuestra aplicación RA para detectar varios patrones

Con unos sencillos cambios podemos modificar nuestra primera aplicación de Realidad Aumentada para que reconozca en la escena varios marcadores, asociando a cada uno de ellos una imagen tridimensional diferente. Os mostraré cómo reconocer cinco marcadores para dibujar cinco objetos diferentes. Podéis descargaros el código y los ficheros necesarios mediante los links correspondientes en este post.



A la hora de realizar una aplicación de Realidad Aumentada que sea capaz de reconocer diferentes patrones asignando imágenes u objetos 3D distintos a cada uno de ellos, tendremos que tener en cuenta las siguientes cambios: (en la imagen se ve la salida del programa ejemplo para dos marcadores distintos)


  1. Cargaremos un fichero de datos que contenga información sobre varios patrones en lugar del fichero de patrón ya utilizado pattMeditel.
  2. Utilizaremos, también, una estructura de datos asociada a los patrones diferente; que permita almacenar varios patrones.
  3. Modificaremos la función de dibujo draw para poder dibujar diferentes objetos en función del patron detectado.

Carga del fichero de datos de los patrones

El fichero de datos que contiene información de todos los marcadores es mi_object_data (es un fichero de texto con una estructura muy sencilla que contiene, para cada marcador, su nombre, el nombre de su fichero de datos y la anchura y centro del marcador; puedes descargarlo aquí). Para cargarlo en el programa, primero definiremos las variables:

   // ==== Fichero Object Data =========================================
   char            *model_name = "Data/mi_object_data";
   ObjectData_T    *object;

   int             objectnum;

A continuación, en la función init, cargamos el fichero mediante una función de ARToolKit definida en object.c llamada read_ObjData a la que le pasamos el fichero de datos y el número de marcadores definidos en él. Los datos referentes a las marcas quedan almacenados en una estructura de datos ObjectData_T específica de ARToolKit. Aquí os dejo el código que hace esto:

  // Cargamos el fichero mi_object_data 
  if ((object = read_ObjData(model_name, &objectnum)) == NULL) exit(0);
  printf("Objectfile num = %d\n", objectnum);


Detección de patrones


ARToolKit puede ahora tratar de identificar varios patrones en la rutina arDetectMarker. Puesto que ahora la detección es para múltiples marcadores, una vez detectado una marca con mayor fiabilidad, habrá que comprobar si se trata de un patrón conocido (presente en el fichero cargado). En este ejemplo, dibujamos también sus bordes cuando esto ocurre. Por otra parte, también es necesario mantener la transformación específica para cada uno de los marcadores detectados. La parte de código que hace esto será:

   // busca patrones conocidos en los marcadores detectados y dibuja un cuadrado
   // de otro color sobre los patrones reconocidos
   for (i = 0; i < objectnum; i++) {
      k = -1;
      for (j = 0; j < marker_num; j++) {
      if (object[i].id == marker_info[j].id) {   //si reconoce un patron
          glColor3f(0.0, 1.0, 0.0);
          argDrawSquare(marker_info[j].vertex, 0, 0);
              if (k == -1) k = j;
          else       // Vemos donde detecta el patron con mayor fiabilidad
           if (marker_info[k].cf < marker_info[j].cf) k = j;
         }
      }
       if (k == -1) {
          object[i].visible = 0;
          continue;
          }

       // calculamos la transformada para cada patron reconocido.
       object[i].visible = 1;
       arGetTransMat(&marker_info[k], object[i].marker_center, 
       object[i].marker_width,
       object[i].trans);
    }

Hay una bandera del visiblitdad asociada con cada marcador, y se realizará una nueva transformación para cada marcador detectado.


Dibujado del objeto asociado al marcador

Para dibujar el objeto asociado al marcador detectado, se llama a la función draw con la estructura ObjectData_T  y el número de objetos como parámetros. Dentro de esta función, se convertimos la matriz de transformación a formato openGL para cada marcador detectado:

    for (i = 0; i < objectnum; i++) {
      if (object[i].visible == 0) continue;
      argConvGlpara(object[i].trans, gl_para);  
          draw_object(object[i].id, gl_para);
    }

Finalmente, dibujamos el objeto asociado al marcador detectado a través de la subrutina draw_object que, mediante la anidación de funciones if selecciona el objeto para cada marcador (pondré solo un ejemplo):

    if (obj_id == 0){
       glMaterialfv(GL_FRONT, GL_SPECULAR, mat_flash_collide);
       glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient_collide);
       glTranslatef(0.0, 0.0, 30.0);
       glutSolidSphere(30, 12, 6);    // dibujamos una esfera
    }


Salida del programa

La salida de este programa detectando dos marcadores diferentes, con sus correspondientes objetos asociados (en este caso una esferarosa y un conjunto esfera-toroide azul) puede verse en la imagen siguiente:

salida varios marcadores
Salida del programa de detección de varios marcadores


No hay comentarios:

Publicar un comentario