2012-07-18 104 views
8

我有一些MATLAB代碼需要遷移到OpenCV。 MATLAB代碼使用的數據存儲在.mat文件中,然後在運行時加載。將MATLAB中的.mat文件轉換爲OpenCV中的cv :: Mat矩陣

我將這個.mat文件轉換成.csv文件,然後使用ifstream將這些數據作爲字符串讀入OpenCV。我在將這個字符串轉換爲數據結構時遇到了問題,我可以在OpenCV中使用它。

無論如何,我可以將.mat文件/ .csv文件轉換爲OpenCV中的Mat數據結構嗎?

編輯:基於我收到的答案,我成功地使用YML文件將MATLAB數據讀入OpenCV。這是我在MAC環境中做的。但是,當我嘗試在Windows環境中使用同一段代碼讀取文件時,該文件未被讀取。只是想知道是否有人遇到過這樣的問題。以下是我的代碼片段:

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

我試着在Visual Studio的發佈模式下運行相同的代碼,並能夠成功讀取.yml文件。 – Sid 2012-08-08 21:36:44

回答

14

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

舉個例子,如果你有一個陽明文件像這樣的,我會打電話給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的解析器,同樣我matlab2opencv.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如之前針對Variable1和所解釋的。

希望它可以幫助

+0

謝謝drodbar。我考慮過使用xml,因爲Haar Classifier上有一個使用xml文件的OpenCV示例。但不知道如何以兼容的方式保存我的MATLAB數據。 YAML格式工作得很好。感謝您提供的格式。 – Sid 2012-07-19 20:49:35

+0

不用擔心!然後,我將不得不看看Haar Classifier的例子。我知道如何用'YAML'來完成,但不知道如何使用'XML'來工作:) – Drodbar 2012-07-19 21:06:13

0

除了使用@Drodbar建議XML/YAML文件倉庫,你也可以嘗試cvmatio,其提供的API可直接加載MATLAB MAT文件的OpenCV。

的代碼將是單純的喜歡:

#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

可以使用Matlab的橋從opencv contrib。 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 
    } 
}