2012-07-18 28 views
8

Tengo un código MATLAB que deseo migrar a OpenCV. Los datos que utiliza el código MATLAB se almacenan en un archivo .mat que luego se carga en tiempo de ejecución.Convirtiendo un archivo .mat de MATLAB en una matriz cv :: Mat en OpenCV

Convertí este archivo .mat en un archivo .csv y luego estoy leyendo estos datos en OpenCV como una cadena que utiliza ifstream. Tengo problemas para convertir esta cadena en una estructura de datos que luego puedo usar en OpenCV.

¿Hay alguna forma de que pueda convertir el archivo .mat/archivo .mat a una estructura de datos Mat en OpenCV?

Editar: De acuerdo con la respuesta que recibí, tuve éxito en la lectura de datos de MATLAB en OpenCV usando un archivo YML. Esto lo hice en un entorno MAC. Sin embargo, cuando intento leer el archivo con el mismo código en un entorno de Windows, el archivo no se está leyendo. Me preguntaba si alguien se encontró con un problema así. A continuación se muestra mi fragmento de código:

// OpenCVDemo.cpp : Defines the entry point for the console application. 
// Created for build/install tutorial, Microsoft Visual Studio and OpenCV 2.4.0 

#include "stdafx.h" 

#include <cv.h> 
#include <cxcore.h> 
#include <highgui.h> 
#include <iostream> 

using namespace cv; 
using namespace std; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
     cout << "Loading the basis." << endl; 

     FileStorage fs1("basis.yml", FileStorage::READ); 

     cv::FileNode B = fs1["B"]; 

     if (B.EMPTY) 
     { 
      cout << "File is empty or does not exist" << endl; 
      return 1; 
     } 

     fs1["B"] >> basis; 

     cout << basis.cols << endl; 

     fs1.release(); 

      return 0; 
} 
+1

Intenté ejecutar el mismo código en el modo de lanzamiento de Visual Studio y pude leer el archivo .yml con éxito. – Sid

Respuesta

14

Puede utilizar el XML/YAML file storages proporcionada por la clase OpenCV Filestorage.

A modo de ejemplo, si tiene un archivo yml como éste, que llamaré a demo.yml

%YAML:1.0 
    Variable1: !!opencv-matrix 
     rows: 4 
     cols: 5 
     dt: f 
     data: [ -1.60522782e-03, -5.93489595e-03, 2.92204670e-03, 
      1.14785777e-02, -1.57432575e-02, -2.17529312e-02, 4.05947529e-02, 
      6.56594411e-02, 1.24527821e-02, 3.19751091e-02, 5.41692637e-02, 
      4.04683389e-02, 2.59191263e-03, 1.15112308e-03, 1.11024221e-02, 
      4.03668173e-03, -3.19138430e-02, -9.40114353e-03, 4.93452176e-02, 
      5.73473945e-02 ] 
    Variable2: !!opencv-matrix 
     rows: 7 
     cols: 2 
     dt: f 
     data: [ -2.17529312e-02, 4.05947529e-02, 5.73473945e-02, 
      6.56594411e-02, 1.24527821e-02, 3.19751091e-02, 5.41692637e-02, 
      4.03668173e-03, -3.19138430e-02, -9.40114353e-03, 4.93452176e-02, 
      4.04683389e-02, 2.59191263e-03, 1.15112308e-03 ] 

A continuación, puede utilizar la clase OpenCV FileStorage para cargar las variables contenidas en este demo.yml archivo como:

#include <iostream> 
#include <string> 

#include <cv.h> 
#include <highgui.h> 

using namespace cv; 
using namespace std; 

int main (int argc, char * const argv[]) 
{ 
    Mat var1; 
    Mat var2; 

    string demoFile = "demo.yml"; 

    FileStorage fsDemo(demoFile, FileStorage::READ); 
    fsDemo["Variable1"] >> var1; 
    fsDemo["Variable2"] >> var2; 

    cout << "Print the contents of var1:" << endl; 
    cout << var1 << endl << endl; 

    cout << "Print the contents of var2:" << endl; 
    cout << var2 << endl; 

    fsDemo.release(); 
    return 0; 
} 

Ahora, lo que puede hacer es escribir su propio analizador Matlab, de manera similar a mi matlab2opencv.m a continuación:

function matlab2opencv(variable, fileName, flag) 

[rows cols] = size(variable); 

% Beware of Matlab's linear indexing 
variable = variable'; 

% Write mode as default 
if (~exist('flag','var')) 
    flag = 'w'; 
end 

if (~exist(fileName,'file') || flag == 'w') 
    % New file or write mode specified 
    file = fopen(fileName, 'w'); 
    fprintf(file, '%%YAML:1.0\n'); 
else 
    % Append mode 
    file = fopen(fileName, 'a'); 
end 

% Write variable header 
fprintf(file, ' %s: !!opencv-matrix\n', inputname(1)); 
fprintf(file, '  rows: %d\n', rows); 
fprintf(file, '  cols: %d\n', cols); 
fprintf(file, '  dt: f\n'); 
fprintf(file, '  data: [ '); 

% Write variable data 
for i=1:rows*cols 
    fprintf(file, '%.6f', variable(i)); 
    if (i == rows*cols), break, end 
    fprintf(file, ', '); 
    if mod(i+1,4) == 0 
     fprintf(file, '\n   '); 
    end 
end 

fprintf(file, ']\n'); 

fclose(file); 

Por lo que podría ejecutar algo como:

varA = rand(3, 6); 
varB = rand(7, 2); 

matlab2opencv(varA, 'newStorageFile.yml'); 
matlab2opencv(varB, 'newStorageFile.yml', 'a'); % append mode passed by 'a' flag 

obtener newStorageFile.yml:

%YAML:1.0 
    varA: !!opencv-matrix 
     rows: 3 
     cols: 6 
     dt: f 
     data: [ 0.430207, 0.979748, 0.258065, 
      0.262212, 0.221747, 0.318778, 0.184816, 
      0.438870, 0.408720, 0.602843, 0.117418, 
      0.424167, 0.904881, 0.111119, 0.594896, 
      0.711216, 0.296676, 0.507858] 
    varB: !!opencv-matrix 
     rows: 7 
     cols: 2 
     dt: f 
     data: [ 0.085516, 0.578525, 0.262482, 
      0.237284, 0.801015, 0.458849, 0.029220, 
      0.963089, 0.928854, 0.546806, 0.730331, 
      0.521136, 0.488609, 0.231594] 

desde donde se podía leer varA y varB como se explicó anteriormente para Variable1 y Variable2.

creo que sirve

+0

Gracias drodbar. Consideré usar xml ya que hay un ejemplo de OpenCV en Haar Classifier que usa un archivo xml. Pero no estaba seguro de cómo guardar mis datos de MATLAB de una manera compatible. El formato YAML funciona maravillosamente. Gracias por proporcionar el formato. – Sid

+0

¡Sin preocupaciones! Tendré que echar un vistazo al ejemplo del clasificador Haar. Sé cómo hacerlo con 'YAML', pero no tenía idea de cómo hacerlo funcionar con' XML' :) – Drodbar

0

Además de utilizar los almacenes de archivos XML/YAML sugeridas por @Drodbar, también puede probar cvmatio, que proporciona las API para cargar directamente los archivos MAT MATLAB para OpenCV.

El código será simplemente como:

#include "MatlabIO.hpp" 
#include "MatlabIOContainer.hpp" 

... 

// load the MATLAB MAT file 
MatlabIO matio; 
bool ok = matio.open("-path-to-mat-file.mat", "r"); 
if (!ok) return -1; 

// read all of the variables in the file 
std::vector<MatlabIOContainer> variables; 
variables = matio.read(); 
matio.close(); 

// load the matrix by name in OpenCV style 
cv::Mat basis = matio.find<cv::Mat>(variables, "B") 
1

Usted puede utilizar el puente Matlab de opencv contrib. Todo lo que necesita de Opencv Contrib es copiar la carpeta contrib/modules/matlab/include/opencv2/matlab en la carpeta include/opencv2.

junto con Matlab Compiler Runtime (solo libmx.lib, libmex.lib y libmat.lib).

MATFile *pmat = matOpen(filename, "r"); 
if (pmat == NULL) 
{ 
    cerr << "Error opening file " << filename << endl; 
} 
else 
{ 
    int numVars; 
    char** namePtr = matGetDir(pmat, &numVars); 
    cout << filename << " contains vars " << endl; 
    for (int idx = 0; idx < numVars; idx++) 
    { 
      std::cout << "      " << namePtr[idx] << " "; 
      mxArray* m = matGetVariable(pmat, namePtr[idx]); 
      matlab::MxArray mArray(m); 
      cv::bridge::Bridge bridge(mArray); 
      cv::Mat mat = bridge.toMat(); 
      // do something with opencv Mat 
    } 
} 
Cuestiones relacionadas