Leer ficheros de matlab en C/C++ con matio
Menuda tardecita me he tirado para conseguir leer desde una aplicación C/C++ un puñetero (perdónenme la expresión) fichero de Matlab .mat. Os pongo en situación. En el tema de investigación en el que me encuentro inmerso ahora mismo tengo que probar distintos modos de aprendizaje y clasificación con ciertos descriptores de acciones en 3D. Estoy utilizando una base de datos muy conocida en este tema de investigación que me provee los datos en ficheros generados con MatLab y en otros formatos. Dichos ficheros *.mat pueden ser leídos sin problemas desde Octave un programa de GNU muy similar a Matlab, y en la mayoría de sus funciones totalmente compatible. Percatándome de este hecho intenté utilizar las librerías C++ de octave para intentar leer dichos ficheros, pero observé que no incluyen ningún método para realizar esta operación. Matlab proporciona unas librerías que te permiten hacer esta tarea, pero el problema es que Matlab es un paquete software privativo, y además la licencia tiene pinta de costar bastante (hago esta suposición por la entidad del programa ya que no lo he mirado siquiera, teniendo alternativas libres está la cosa como para tirar el dinero … O:-) ). Después de un “muy buen rato” googleando he dado con la librería matio, que nos permite manejar ficheros y variables Matlab. La documentación de esta librería se ciñe a describir las estructuras de datos manejadas y las funciones, pero no he visto ningún ejemplo por la red que me ayudase a conseguir mi propósito. Después de un buen rato trasteando he conseguido leer el puñetero ficherito y he decidido compartir lo aprendido hoy con aquellos científicos amantes del software libre que prefieren no gastarse el poco dinero que hay en investigación en comprar licencias de software 8-).
La vía fácil
Antes de empezar a describir como instalar la librería matio y como usarla os tengo que comentar que hay una vía más sencilla para poder tratar con los ficheros de matlab. En este caso necesitaremos tener instalado octave y realizar los siguientes pasos desde la terminal de octave:
octave:1> load "file.mat" octave:2> save "newfile.txt" VARIABLE octave:3> exit
Primero cargamos el fichero en cuestión y luego simplemente salvamos la variable (o variables) que queramos en un nuevo fichero ASCII que podremos tratar sin problemas desde C/C++.
MAT File I/O Library
Instalación
Para instalar la librería tenemos dos opciones: instalarlo mediante nuestro gestor de paquetes (en ubuntu el paquete se llama libmatio-dev, en gentoo no está :-( ) o irnos a la página del proyecto y bajarlo desde ahí. Para el segundo caso podéis bajar directamente el tarball o la versión svn o git. Instalamos como ya sabéis …
tar -xvf file.tar.gz cd directorio autoreconf --install (para crear el configure si no existe) ./configure make sudo make install
Os recomiendo bajaros la documentación de la librería ya que sin ella no haremos mucho.
Uso
Cómo suelen decir, una imagen vale más que mil palabras, así que os pego el código y luego os voy explicando.
#include <iostream>
#include <cstdlib>
#include <matio.h>
#include <fstream>
using namespace std;
int main ( int argc, char *argv[] )
{
try
{
mat_t *file = Mat_Open("matrix.mat", MAT_ACC_RDONLY);
if (file == NULL)
{
cerr << "Error al abrir el fichero mat" << endl;
exit(1);
}
matvar_t *matrix = Mat_VarReadNext(file);
if (matrix == NULL)
{
cerr << "Error al crear la variable" << endl;
exit(1);
}
cout << "class_type: " << matrix->class_type << endl;
cout << "compression: " << matrix->compression << endl; // zlib
cout << "nbytes: " << matrix->nbytes << endl;
cout << "rank: " << matrix->rank << endl;
cout << "data_syze: " << matrix->data_size << endl;
cout << "data_type: " << matrix->data_type << endl; //uint8
for (unsigned int i=0; i<matrix->rank; i++)
cout << "dimension " << i+1 << " : " << matrix->dims[i] << endl;
ofstream myfile("prueba.txt" );
unsigned char *data = (unsigned char *)matrix->data;
for (unsigned int i=0; i<matrix->nbytes; i++)
myfile << (unsigned int )data[i] << endl;
myfile.close();
Mat_Close(file);
Mat_VarFree(matrix);
}
catch (exception &ex)
{
cout << ex.what() << endl;
}
return EXIT_SUCCESS;
}
En la línea 12 creamos una estructura mat_t, que representa al fichero matlab, y la inicializamos con la función de apertura de ficheros. Posteriormente, en la línea 19, creamos una estructura matvar_t, que representa una variable, y leemos la primera variable del fichero. Si todo ha ido bien podremos acceder a los atributos de esta estructura para ver la información de la variable. Es importante fijarse en los valores de data_size y data_type ya que determinarán el tipo de puntero a crear en la línea 37 y el casting en la línea 39. Básicamente lo que hago en las últimas líneas es crear un puntero a los datos de la variable y acceder byte a byte a sus valores, ya que en mi caso los datos están en unsigned char. Por último que no se os olvide de cerrar el fichero y liberar memoria
. Por cierto, siento que el código no esté indentado correctamente, no se porque pero no me coge las tabulaciones el plugin este de wordpress.
loading...



loading...
TE RECOMIENDO UTILIZAR SCILAB COMO ALTERNATIVA AL MATLAB
SALUDOS
loading...
Hola leo, gracias por la sugerencia. Había oído hablar de él, pero según tengo entendido Octave tiene tiene un mejor soporte de compatibilidad con matlab que scilab (http://www.dspguru.com/sw/opendsp/mathclo2.htm). Ya me pondré algún día de estos a aprender a fondo como utilizar alguno de estos programas, ya que de momento hago todo desde C/C++, y para graficar utilizo gnuplot :-) .
Saludos.
loading...
Muy interesante, gracias.
loading...
Uffffffff yo me he tenido que pelear con archivos Mat y mxarray desde C++ para el proyecto.. (Vision artificial) y ha sido un puto infierno… y despues actualicé a 64 bits y dejo de funcionar el codigo!!! jjeje
loading...
@Julian
xD. La verdad es que es un temazo, como no utilices las librerías que te dan los de Matlab no es sencillo, porque vienen comprimidos los datos. Y claro, yo no voy a pagar licencias cuando utilizo SL para todo. La librería esta que comento está muy bien, pero hay que entender bien como es el formato de los ficheros matlab y leerse bastante documentación. En fin, ahora al menos puedo trabajar con los ficheros sin problemas