【问题标题】:Converting a .mat file from MATLAB into cv::Mat matrix in OpenCV将 .mat 文件从 MATLAB 转换为 OpenCV 中的 cv::Mat 矩阵
【发布时间】:2012-07-17 23:58:35
【问题描述】:

我有一些 MATLAB 代码想要迁移到 OpenCV。 MATLAB 代码使用的数据存储在 .mat 文件中,然后在运行时加载该文件。

我将此 .mat 文件转换为 .csv 文件,然后使用 ifstream 将此数据作为字符串读入 OpenCV。我在将此字符串转换为可以在 OpenCV 中使用的数据结构时遇到问题。

无论如何我可以将 .mat 文件/.csv 文件转换为 OpenCV 中的 Mat 数据结构吗?

编辑:根据我收到的答复,我成功地使用 YML 文件将 MATLAB 数据读入 OpenCV。这是我在 MAC 环境中所做的。但是,当我尝试在 Windows 环境中使用相同的代码读取文件时,文件并没有被读取。只是想知道是否有人遇到过这样的问题。下面是我的代码sn-p:

// 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;
}

【问题讨论】:

  • 我尝试在 Visual Studio 的发布模式下运行相同的代码,并且能够成功读取 .yml。

标签: c++ matlab opencv matrix io


【解决方案1】:

您可以使用来自opencv contrib 的 Matlab 桥。 Opencv Contrib 所需要的只是将 contrib/modules/matlab/include/opencv2/matlab 文件夹复制到 include/opencv2 文件夹中。

连同Matlab Compiler Runtime(只有 libmx.lib、libmex.lib 和 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 
     }
}

【讨论】:

    【解决方案2】:

    除了使用@Drodbar 建议的XML/YAML 文件存储之外,您还可以尝试cvmatio,它提供了将MATLAB MAT 文件直接加载到OpenCV 的API。

    代码如下:

    #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")
    

    【讨论】:

      【解决方案3】:

      您可以使用OpenCV类Filestorage提供的XML/YAML file storages

      例如,如果您有一个像这样的 yml 文件,我将其命名为 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 ]
      

      然后,您可以使用 OpenCV FileStorage 类将包含在此 demo.yml 文件中的变量加载为:

      #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;
      }
      

      现在,您可以编写自己的 Matlab 解析器,类似于下面的 ma​​tlab2opencv.m

      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);
      

      所以你可以运行类似的东西:

      varA = rand( 3, 6);
      varB = rand( 7, 2);
      
      matlab2opencv( varA, 'newStorageFile.yml');
      matlab2opencv( varB, 'newStorageFile.yml', 'a'); % append mode passed by 'a' flag
      

      获取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]
      

      您可以从中读取varAvarB,如前面对Variable1Variable2 的解释。

      希望对你有帮助

      【讨论】:

      • 谢谢卓巴。我确实考虑过使用 xml,因为 Haar 分类器上有一个使用 xml 文件的 OpenCV 示例。但不确定如何以兼容的方式保存我的 MATLAB 数据。 YAML 格式效果很好。感谢您提供格式。
      • 别担心!那么我将不得不看一下 Haar Classifier 示例。我知道如何使用YAML,但不知道如何使用XML :)
      猜你喜欢
      • 2015-06-11
      • 1970-01-01
      • 1970-01-01
      • 2022-06-13
      • 2020-02-09
      • 2022-06-25
      • 1970-01-01
      • 2016-08-16
      • 2013-10-21
      相关资源
      最近更新 更多