miércoles, 26 de septiembre de 2012

Instalando openkinect en Fedora

Aunque actualmente existe un excelente SDK para Kinect no podremos utilizarlo en nuestro SO favorito, aka Linux. A continuación os dejo paso por paso todos los pasos para poder utilizar libfreenect en Fedora:

En primer lugar debemos instalar libusb

$yum install libusb1*

Y después todo esto aunque la mayoría espero que ya lo tengáis:

$yum install git cmake gcc gcc-c++ libXi libXi-devel libXmu libXmu-devel freeglut freeglut-devel

Después descargamos el código desde el repositorio GIT con en el directorio actual (así que os recomiendo crear un directorio para el proyecto)

$ git clone git://github.com/OpenKinect/libfreenect.git
 

Y ahora queda configurar la compilación:

 
$ cd libfreenect
$ mkdir build
$ cd build
$ ccmake ..

Una vez ejecutado el editor ccmake presionar c para configurar.
Debereis comprobar que la variable LIBUSB_1_INCLUDE_DIR es /usr/include/libusb-1.0  aunque deberia estar bien por defecto.
Pulsar intro para terminar.
Pulsar c para seguir la configuración.
Si todo esta bien hay que pulsar g que generara el fichero de configuración y terminara la operación.


Ahora queda construir todo e instalar:

$ cmake ..
$ make
$ sudo make install

Y listo.

Para probar si todo funciona podemos conectar nuestro kinect al puerto USB (recordar que tiene que ser un puerto 2.0 (si yo he estado un par de horas tratando de hacer que funcione en un USB 3.0)) e ir a la carpeta build y ejecutar el programa de ejemplo:

$ bin/glview

Ahora ya podemos empezar a utilizar la librería. Para ello solo tenemos que anadir la carpeta inlclude de la libreria que deberia estar por defecto en /usr/local/include/libfreenect/ y anadir al proyecto la libreria  freenect que deberia estar en /usr/local/lib64 (si usais una version de 64 bits de fedora).

Si al compilar os da un error parecido a "error while loading shared libraries: libfreenect.so.0.1: cannot open shared object file: No such file or directory" si vuestro sistema es de 32 bits debeis anadir el directorio a la path de librerias del sistema con:

$export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

o si contáis con Fedora de 64 bits:

$export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib64

Para más información:






viernes, 15 de junio de 2012

Creación de librerias en Matlab para su uso en aplicaciones en C

Estos días estoy trabajando en la integración de una aplicación creada en Matlab (2008b) junto con otra en una aplicación en C\C++ en Visual Studio (2005) y la verdad es que aunque a primer vista parezca un proceso fácil en realidad es algo bastante enrevesado.

A lo largo de este tutorial trabajaremos con el siguiente código Matlab que debemos guardar en un archivo llamado getCorrelation.m y que calcula la coeficiente de correlación entre dos matrices (que indica si son o no similares las diferencias entre sus valores):

function cor = getCorrelation(temp, comp)
    tsize = size(temp);
    csize = size(comp);
   
    if (tsize == csize)   
        %media de los valores de la matriz temp 
        aver_temp = median(median(temp)); 
        %media de los valores de la matriz comp
        aver_comp = median(median(comp));
       
        tc = 0.0;
        vaa = 0.0;
        vab = 0.0;
        for nr=1:tsize(1)
            for nc=1:tsize(2)
                tc = tc + double((temp(nr, nc)-aver_temp) * (comp(nr, nc) - aver_comp));
                vaa = vaa + double((temp(nr, nc)-aver_temp)^2);
                vab = vab + double((comp(nr, nc)-aver_comp)^2);       
            end
        end      
        % Calculo de la fórmula completa.
        cor = tc/sqrt(double(vaa * vab));
    end 


Antes de crear una librería en C de este código desde Matlab debemos configurarlo para que compile utilizando el compilador de Visual Studio para lo que se debe utilizar el siguiente comando en Matlab:

>> mbuild -setup

Tras lo cual se nos preguntara si queremos cambiar el compilador y que lo seleccionemos de una lista de entre los disponibles en el sistema. Como trabajaremos con VS2005 sera este el que se debe elegir. Este paso genera un script de configuración que por lo menos en mi caso no ha resultado funcionar por defecto por lo que lo debemos editar modificando un par de lineas. Para ello buscamos el archivo compopts.bat (que se encuentra en la carpeta de configuración de aplicaciones del sistema algo similar a C:\Documents and Settings\TU_USER\Datos aplicaciones\MathWorks\MATLAB\R2008b). En este archivo debemos modificar las siguientes asignaciones de variables:

set VSINSTALLDIR=C:\Program Files\Microsoft Visual Studio 8   
(O donde este instalada vuestra versión de VS)

set INCLUDE=%VCINSTALLDIR%\ATLMFC\INCLUDE;%VCINSTALLDIR%\INCLUDE;%LINKERDIR%\INCLUDE;%VSINSTALLDIR%\SDK\v2.0\include;%VCINSTALLDIR%\PlatformSDK\Include;%INCLUDE%

set LIB=%VCINSTALLDIR%\ATLMFC\LIB;%VCINSTALLDIR%\LIB;%LINKERDIR%\lib;%VSINSTALLDIR%\SDK\v2.0\lib;%MATLAB%\extern\lib\win32;%VCINSTALLDIR%\PlatformSDK\Lib;%LIB%


Ahora ya podemos generar la librería sin problemas y con solo escribir en Matlab el comando:

>> mcc -B csharedlib:libcorrelation getCorrelation.m

Que generará entre otro, los siguientes ficheros que son los que utilizaremos después para crear la aplicación que utilizará esta librearía desde Visual Studio:

libcorrelation.c
libcorrelation.h
libcorrelation.dll
libcorrelation.lib

Ahora ya podemos olvidarnos de Matlab y comenzar a trabajar en Visual Studio. En primer lugar debemos configurar nuestro proyecto para lo que debemos indicar donde se encuentran los archivos creados y las cabeceras y librerías de Matlab que normalmente estarán en los directorios:

...Caperta instalacion\MATLAB\R2008b\extern\lib\win32\microsoft
...Carpeta instalacion\MATLAB\R2008b\extern\include

También deberemos añadir al proyecto las librerías:

mclmcrrt.lib
libcorrelation.lib

Ahora ya podemos incluir en nuestro código la definición de nuestra librería creada en Matlab y las cabeceras de la API de Matlab:

#include "libcorrelation.h"

Y el resto del código, que debe empezar por la inicialización de la API de Matlab para lo que debemos llamar a la función mclInitializeApplication y a la función de inicialización que se ha definido en la librería que vendrá siempre dada por el nombre de la librería junto con la palabra Initialize (en nuestro caso la función libcorrelationInitialize). Por tanto el código de inicialización queda definido por:

if (!mclInitializeApplication(NULL,0)) {
        fprintf(stderr,"No se ha podido inicializar la API de Matlab!\n");
        return;
}
if (!libcorrelationInitialize()){
        fprintf(stderr,"No se ha podido inicializar la librería!\n");
        return;
}

Ahora ya podemos definir las matrices (por medio de la estructura mxArray) con los datos que le pasaremos a la función definida en la librería para que realice el cálculo del coeficiente de correlación así como la matriz en la que se almacenara la salida producida. Para ello debemos escribir:

    // Definición estructuras y datos
    mxArray *in1, *in2;
    mxArray *out = NULL;
    double data1[] = {1,2,3,4,5,6,7,8,9};
    double data2[] = {1,1,1,3,3,3,6,6,6};
    // creación matrices de entrada entrada    
    in1 = mxCreateDoubleMatrix(3,3,mxREAL);
    in2 = mxCreateDoubleMatrix(3,3,mxREAL);
    // Asignación de valores.
    memcpy(mxGetPr(in1), data1, 9*sizeof(double));
    memcpy(mxGetPr(in2), data2, 9*sizeof(double));
 
A continuación ya podemos  llamar a nuestra función que se habrá generado con el mismo nombre con el que está definida en el código en Matlab precedida del prefijo mlf siendo los primeros argumentos el numero de argumentos de salida y las estructuras donde se almacenan y el resto los definidos en la cabecera de la función del código en Matlab:

    mlfGetCorrelation(1, &out, in1, in2);
   
Aunque en este caso obtenemos una matriz de salida de 1x1, si quisiéramos saber sus dimensiones podemos escribir (dónde mwSize es en realidad un size_t):

    mwSize nRow = mxGetM(out); //Filas
    mwSize nCol = mxGetN(out); //columnas

Para recibir los datos de forma que podamos utilizarlos desde C utilizaremos:

    double *xValues = mxGetPr(out);
   
Y ya podemos imprimir la solución (o soluciones si se tratase de una matriz de mayor dimensión):

    for(size_t row = 0; row < nRow; row++) {
        for(size_t col = 0; col < nCol; col++) {
            cout << xValues[nRow * col + row];
        }
        printf("\n");
    }
 
Finalmente para liberar las estructuras generadas utilizaremos las función mxDetstroyArray:

    mxDestroyArray(in1); in1=0;
    mxDestroyArray(in2); in2=0;
    mxDestroyArray(out); out=0;
 
Y al igual que en la inicialización deberemos ejecutar las funciones de terminación en primer lugar la de la librería que vendrá definida por el nombre de la librería seguido de la palabra Terminate y a continuación la de la API de Matlab que viene dada por la función mclTerminateApplication:

    libcorrelationTerminate();
    mclTerminateApplication();


Por ultimo os dejo un par de enlaces donde podéis encontrar mas ejemplos de código C utilizando Matlab e información adicional:


martes, 29 de mayo de 2012

Tiempo en C++

Para medir el tiempo que pasa entre dos eventos (por ejemplo para realizar test de rendimiento) tan solo hay que importar la librería time.h y utilizar la función clock() que devuelve el ciclo de reloj de la CPU. A continuación un ejemplo de su uso:

#include <time.h>
#inculde <iostream>


// Variables para almacenar instantes
double tstart, tstop, ttime;

// .... aqui cabecera función/metodo etc.

// Tiempo inicial
tstart = (double)clock()/CLOCKS_PER_SEC;


// Aquí operaciones test rendimiento.

// Tiempo final
tstop = (double)clock()/CLOCKS_PER_SEC;
ttime= tstop-tstart; //Tiempo entre inicio y final

std::cout << "La operación ha llevado " << ttime << " segundos" << std::endl;

lunes, 21 de mayo de 2012

Lectura de archivos shapefile con GeoTools



GeoTools que es una biblioteca SIG de código libre que permite desarrollar soluciones adaptadas a los estándares proporcionando una implementación de las especificaciones del Open Geospatial Consortium (OGC) según van apareciendo. Es decir, que no solo permite la lectura archivos Shapefile sino que dispone de otras muchas funcionalidades entre las que destacan:
  • Lectura y escritura de otros formatos como GeoTiff, GML,  Jpeg, Png, etc...
  • Acceso a servicios web de datos geoespaciales como WMS, WFS, etc...
  • Proporciona estructuras para trabajo con datos geoespaciales, 
  • Realización de operaciones sobre datos espaciales.
  • Manejo y cambio entre sistemas de coordenadas.
  • Renderizado de datos.
  • Creación de interfaces de usuario.
Requisitos y configuración

Para poder trabajar con GeoTools tan solo debemos bajarnos la ultima versión (a día de hoy 2.7.4) y configurar nuestro IDE favorito importando las librerías que necesitemos que en nuestro caso será gt-shapefile-2.7.4.jar.

Código

En primer lugar deberemos realizar los siguientes imports que incluyen tanto las clases necesarias para cargar los shapefiles como para definir la geometría leída y los datos:

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.FeatureSource;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.opengis.feature.Feature;

import com.vividsolutions.jts.geom.GeometryCollection;



Y ya podemos pasar a realizar la apertura del fichero que en nuestro caso sera un fichero de polígonos (los shapefiles pueden ser de puntos, polilíneas o poligonos). Por tanto a la hora de trabajar con un shapefile tenemos que tener en cuenta su geometría y ademas como contiene datos en forma de cadena (es decir string) debemos tener en cuenta tamien su codificación. Así para abrir un fichero en que esta en utf-8 debemos escribir:

  // Definición del fichero al shapefile (es decir el que tiene la extensión .shp) de entre los que forman el shapefile (ver wikipedia para mas info).
 File file = new File("buildings.shp");
 Map connect = new HashMap();
  // Se establecen los parametros para abrir el fichero.
 connect.put("url", file.toURL());
 connect.put("charset", "utf-8");
 // Se abre el shapefile como almacen de datos.
 DataStore dataStore = DataStoreFinder.getDataStore(connect);
 String[] typeNames = dataStore.getTypeNames();
 String typeName = typeNames[0];

 System.out.println("Reading content " + typeName);
 // Se cargan datos y geometria
 FeatureSource featureSource = dataStore.getFeatureSource(typeName);
 FeatureCollection collection = featureSource.getFeatures();
 FeatureIterator iterator = collection.features();
 // Se recorre cada uno de los registros y se escribe el contenido en este caso un campo llamado name (que es una de las columnas del shapfile leído
try {
 while (iterator.hasNext()) {
  Feature feature = iterator.next();
  if (!feature.getProperty("name").getValue().toString().isEmpty()) {
             
    System.out.println(String.valueOf(feature.getProperty("name").getValue()));    GeometryCollection geo = (GeometryCollection)  feature.getDefaultGeometryProperty().getValue();
            
     // Se lee cada punto del polígono y se escribe
     for (int nC=0; nC < geo.getCoordinates().length; nC++) {
        System.out.println("\t" + String.valueOf(geo.getCoordinates()[nC].x)+
                           ", " + String.valueOf(geo.getCoordinates()[nC].y));
     }
   }     
         
 }
} finally {
    iterator.close();
} catch (Throwable e) {}


miércoles, 2 de mayo de 2012

PROLOG en Java

PROLOG proveniente del francés PROgrammation en LOGique, es un lenguaje de programación lógico e interpretado, bastante conocido en el medio de investigación en Inteligencia Artificial.A diferencia de los lenguajes tradicionales su uso se basa en la definición de reglas y predicados que nos permitirán llegar a una determinada conclusión. Para más información sobre este lenguaje podéis bajaros este libro en el que a parte de las bases sobre el lenguaje encontrareis ejemplos, proyectos, etc. 

Antes de comenzar para poder trabajar en PROLOG desde Java vamos a utilizar la librería GNU Prolog for Java aunque también os recomiendo descargaros SWI-Prolog para probar los scripts que utilicéis y que también se puede linkar desde Java.

En primer lugar vamos a definir un sencillo script en PROLOG que determina si alguien es descendiente de otro alguien para lo que definimos los siguientes predicados:

% definiciones de padres
padre(tito, pepe).
padre(pepe, paco).
padre(pepe, ana).
% definiciones de madres
madre(maria, pepe).
madre(pepa, paco).
madre(pepa, lope).
madre(pepa, kique).

%Y es padre de alguien cuyo hijo es X
%o Y es madre de alguien cuyo hijo es X
es_descendiente(X, Y) :- padre(Y, _) , padre(_, X);
                         madre(Y, _) , madre(_, X).


Para probar este código en SWI-Prolog en primer lugar creamos el fichero desde cualquier editor de textos o desde el entorno escribiendo (acordaros de poner siempre .(punto) al final de cada linea/frase/predicado en Prolog):

?- edit(file('C:/tudir/tuprolog.pl')).

Lo completamos con el script de antes y para cargarlo y poder trabajar con las reglas que se definen tendremos que escribir:

? consult('C:/tudir/tuprolog.pl').

Y por ultimo para comprobar que funciona correctamente podemos probar con las siguientes consultas:

?- es_descendiente(paco, tito). %Paco es descendiente de Tito.
    true.
?- es_descendiente(tito, kique).
    false.
?- es_descendiente(X, tito). %Quien es descendiente de tito
X = pepe ;
X = paco ;
X = ana .

Ahora la idea es poder hacer uso de las características de PROLOG desde Java por lo que deberemos al igual que se ha hecho en SWI-Prolog en primer lugar cargar el fichero y después ejecutar las consultas que queramos verificar. Para ello en primer lugar necesitamos referenciar la librería e importar las siguientes clases:

import gnu.prolog.term.AtomTerm;
import gnu.prolog.term.CompoundTerm;
import gnu.prolog.term.Term;
import gnu.prolog.term.VariableTerm;
import gnu.prolog.vm.Environment;
import gnu.prolog.vm.Interpreter;
import gnu.prolog.vm.PrologCode;
import gnu.prolog.vm.PrologException;

Lo siguiente es inicilizar el interprete para lo que deberemos escribir el siguiente código:

    /**
     * Entorno que usara el interprete.
     */
    Environment env;
    /**
     * Interprete de PROLOG.
     */
    Interpreter interpreter;

    env = new Environment();
    // Cargamos el fichero en el entorno.
    env.ensureLoaded(AtomTerm.get("C:\\tudir\\tuprolog.pl"));
    // Obtenemos el interprete
    interpreter = env.createInterpreter();
    // Y lo inicializamos
    env.runInitialization(interpreter);

Y por ultimo realizar las consultas  :

    // Argumentos para la consulta en este caso constantes.
    Term[] args = { AtomTerm.get("paco"), AtomTerm.get("tito") };
    // Construimos la consulta Paco es desdenciente de Tito?
    CompoundTerm goalTerm =
        new CompoundTerm(AtomTerm.get("es_descendiente"), args);

       
    try {
        if (interpreter.runOnce(goalTerm) == 
            PrologCode.SUCCESS)
        {               
            System.out.println("Pepe es descendiente de Tito.");
        } else {
            System.out.println("Pepe NO es descendiente de Tito.");
        }
    } catch (PrologException e) {
        System.out.println("Error." + e.getMessage());           
   
    // Fin. 
    env.closeStreams();       



Para más información podéis consultar la API de la librería o el ejemplo que viene con ella donde se realiza lo mismo pero con variables y mostrando las respuestas obtenidas.

lunes, 23 de abril de 2012

Matrices con Boost

La librería Boost es un conjunto de bibliotecas de software libre preparadas para extender las capacidades del lenguaje de programación C++. Es decir que es una extensión de las librerías STL que incluye C++ estándar en la que entre otras cosas podemos encontrar una extensión que nos permite trabajar con matrices y operar con ellas tal y como veremos a continuación.

Instalación

Para instalar Boost en vuestro sistema os recomiendo que sigáis la guía oficial para vuestro sistema operativo (Linux, Windows). Existen versiones pre-compiladas y dependiendo del vuestra de distribución Linux en ocasiones Boost viene pre-instalado directamente. Por otro lado si trabajáis en Windows con Visual Studio podeis bajaros la versión binaria que proporciona BoostPro con la librería pre-compilada para cada una de las versiones de Visual Studio. 

Matrices

Y ahora vamos al grano. La clase template matrix nos permite trabajar de una forma fácil con matrices de cualquier tipo y realizar sobre ellas operaciones simples (sumas, restas, etc.) . En el siguiente ejemplo en primer lugar se importa la clase, después se definen los namespaces en los que se trabaja y finalmente se muestra el un código que realiza la carda de una matriz, una serie de operaciones y vuelve a mostrar los resultados:

// includes
#include <boost/numeric/ublas/matrix.hpp>
#include <iostream>
// seleccion namespaces
using namespace std;
using namespace boost::numeric::ublas;

int main(int argc, char* argv[]) {
    matrix<int> mt (3, 3);   
    cout << "Generacion de la matriz: " << endl;
    for (unsigned r=0; r < mt.size1(); r++) {
        for (unsigned c=0; c < mt.size2(); c++) {
            mt(r,c) = r+c;
            cout << mt(r,c) << " ";
        }
        cout << endl;
    }
    cout << "Operaciones con la matrix y resultados: " << endl;
    mt = mt + mt;    // operacion entre matrices
    mt = mt * 4;        // matriz y escalar.
    mt = mt / 2;
    mt = mt - mt;
    // Impresion resultados
    for (unsigned r=0; r < mt.size1(); r++) {
        for (unsigned c=0; c < mt.size2(); c++) {
            cout << mt(r,c) << " ";
        }
        cout << endl;
    }
   
}

 

Matrix en C++

Aquí tenéis el código:

#include "stdafx.h"
#include <cstdlib>
#include <iostream>
#include <windows.h>
#include <ctime>
using namespace std;



int main(int argc, char* argv[])
{
    int a;
    srand(time(NULL));    
    // Inicialización de la tabla de caracteres seleccionables.
    char arr[64]={'A','0','B','C','3','D','E','7','F','G','H',' ','I','J','5','K',
                  '6','L','M','N','O','P','Q','!','R','S','T','U','V','W','X','Y',
                  ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','Z','1','2','4','6','8',
                  '9',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ', '};
    system("color 0A"); // Consola en verde.
    while (1)
    {
          Sleep(50);
          char pline[40];
          for(int i=0; i<39; i++)
          {
             a=rand()%64; // Selecciona un char aleatorio
             if (pline[i] != ' ') {   
                cout<<arr[a]<<" "; // Se imprime
             } else {
                cout<<" "<<" ";
             }
             pline[i] = arr[a];
          }
          cout<<endl;
    }
    system("pause");
    return 0;
}


Y aquí el resultado: