2015-05-02-OpenCV 讀取 Matlab .mat 文件的方法

在把 Matlab 轉(zhuǎn)化成 OpenCV(C++) 的過程中癣猾,經(jīng)常會遇見 load .mat 文件這個問題青灼。正巧暂吉,Stackoverflow 上有個問題《Converting a .mat file from MATLAB into cv::Mat matrix in OpenCV》就是回答這個的竣付。這篇博文的主要分為兩部分,第 1 部分是將這個答案轉(zhuǎn)述一遍竭钝,以方便日后需要;第 2 部分是在原答案的基礎(chǔ)上的改進雹洗,以求在方便程度和靈活性上有一定的提高香罐。

1. (翻譯)將 MATLAB 的 .mat 文件轉(zhuǎn)化成 OpenCV 的 cv::Mat 矩陣

由于 OpenCV 沒法直接讀取 MATLAB 的 .mat 文件,這就需要通過第三方的格式作為兩者之間的橋梁队伟⊙ù担考慮到 OpenCV 的 FileStorage 類提供了 XML/YML 文件的存取功能。
例如嗜侮,我們有一個如下的 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 parser,類似于如下這樣的:

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

由此击吱,我們就可以將 Matlab 變量儲存成 yml 文件淋淀,如下所示:

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 那樣朵纷。

2. 改進的代碼

需求

  • 根據(jù)輸入的數(shù)據(jù)類型炭臭,自適應(yīng)地調(diào)整寫入到 yml 文件的數(shù)據(jù)類型,以方便后面 cv::Mat 類型的數(shù)據(jù)訪問袍辞。

先來一個稍微改動一下鞋仍,寫入 int 類型的代碼:

function matlab2opencv_int( 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: i\n');
fprintf( file, '        data: [ ');
 
% Write variable data
for i=1:rows*cols
    fprintf( file, '%i', variable(i));
    if (i == rows*cols), break, end
    fprintf( file, ', ');
    if mod(i+1,8) == 0
        fprintf( file, '\n            ');
    end
end
 
fprintf( file, ']\n');
 
fclose(file);

有了上面的基礎(chǔ),下面自動的代碼就可以是:

function dym_matlab2opencv(variable, fileName, flag, varClass)
 
% varClass: the variable class waiting for write:
%           'i': for int
%           'f': for float
% flag    : Write mode
%           'w': for write
%           'a': for append
 
[rows, cols] = size(variable);
 
% Beware of Matlab's linear indexing
variable = variable';
 
% Write mode as default
if ( ~exist('flag','var') )
    flag = 'w';
end
 
% float as default
if ( ~exist('varClass','var') )
    if isfloat(variable)
        varClass = 'f';
    else isinteger(variable)
        varClass = 'i';
    end
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: ' varClass '\n']);
fprintf( file,  '        data: [ ');
 
% Write variable data
for i=1:rows*cols
    fprintf( file, ['%' varClass], variable(i));
    if (i == rows*cols), break, end
    fprintf( file, ', ');
    if mod(i+1,8) == 0
        fprintf( file, '\n            ');
    end
end
 
fprintf( file, ']\n');
 
fclose(file);

以上搅吁,初寫于 2015-05-02威创,更新于 2015-07-23。
首發(fā)于 Yimian Dai's Homepage谎懦,轉(zhuǎn)載請注明出處肚豺。

參考資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市界拦,隨后出現(xiàn)的幾起案子吸申,更是在濱河造成了極大的恐慌,老刑警劉巖寞奸,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呛谜,死亡現(xiàn)場離奇詭異,居然都是意外死亡枪萄,警方通過查閱死者的電腦和手機隐岛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瓷翻,“玉大人聚凹,你說我怎么就攤上這事∑胫悖” “怎么了妒牙?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長对妄。 經(jīng)常有香客問我湘今,道長,這世上最難降的妖魔是什么剪菱? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任摩瞎,我火速辦了婚禮,結(jié)果婚禮上孝常,老公的妹妹穿的比我還像新娘旗们。我一直安慰自己,他們只是感情好构灸,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布上渴。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪稠氮。 梳的紋絲不亂的頭發(fā)上吊圾,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天稳强,我揣著相機與錄音官还,去河邊找鬼喜德。 笑死翅帜,一個胖子當(dāng)著我的面吹牛颅夺,可吹牛的內(nèi)容都是我干的拳亿。 我是一名探鬼主播享怀,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼漓库,長吁一口氣:“原來是場噩夢啊……” “哼恃慧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起渺蒿,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤痢士,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后茂装,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體怠蹂,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年少态,在試婚紗的時候發(fā)現(xiàn)自己被綠了城侧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡彼妻,死狀恐怖嫌佑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情侨歉,我是刑警寧澤屋摇,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站幽邓,受9級特大地震影響炮温,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜牵舵,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一柒啤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧棋枕,春花似錦白修、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春祖很,著一層夾襖步出監(jiān)牢的瞬間笛丙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工假颇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留胚鸯,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓笨鸡,卻偏偏與公主長得像姜钳,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子形耗,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容