I have some MATLAB code that I want to migrate to OpenCV. The data that the MATLAB code uses is stored in a .mat file which is then loaded at run time.
I converted this .mat file into a .csv file and am then reading this data into OpenCV as a string using ifstream. I am having problems converting this string into a data-structure that I can then use in OpenCV.
Is there anyway that I can convert the .mat file / .csv file to a Mat data structure in OpenCV?
Edit: Based on the Answer I received, I was successful in reading MATLAB data into OpenCV using a YML file. This I did in a MAC environment. However, when I try to read the file with the same piece of code in a Windows environment, the file is not being read. Just wondering if anyone ran into such an issue. Below is my code snippet:
// 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;
}
You can use the XML/YAML file storages provided by the OpenCV class Filestorage.
As an example, if you have a yml file like this one, that I'll call 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 ]
Then, you can use OpenCV FileStorage class to load the variables contained on this demo.yml file as:
#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;
}
Now, what you can do is writing your own Matlab parser, similarly to my matlab2opencv.m below:
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);
So you could run something like:
varA = rand( 3, 6);
varB = rand( 7, 2);
matlab2opencv( varA, 'newStorageFile.yml');
matlab2opencv( varB, 'newStorageFile.yml', 'a'); % append mode passed by 'a' flag
obtaining 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]
from which you could read varA and varB as previously explained for Variable1 and Variable2.
Hope it helps
You can use the Matlab bridge from opencv contrib. All you need from Opencv Contrib is to copy contrib/modules/matlab/include/opencv2/matlab folder into the include/opencv2 folder.
along with the Matlab Compiler Runtime (just libmx.lib, libmex.lib and 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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With