http://www.ninadthakoor.com/2012/03/03/matcv/


        //Transpose the opencv data to get row major data for matlab
        tmp=opencv.t();

opencv mat를 matlab mex 데이터로 변환할때는 .t()로 transpose시켜줘야 한다.



Using OpenCV functions in Matlab

I wrote Converter class few days back to simplify creating MEX files for OpenCV functions. Example of using the class follows in the next post.

Source for matcv.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef __MATCV__H__
#define __MATCV__H__
 
#include "mex.h"
#include "matrix.h"
#include <cstring>
#include "opencvcv.h"
#include "opencvhighgui.h"
#include "boostbimap.hpp"
 
class Converter{
public:
 Converter(mxArray* src, bool Interleve=true);
 Converter(cv::Mat& src);
 
 operator cv::Mat();
 operator mxArray*();
 
private:
 enum{MATLAB_MXARRAY,OPENCV_MAT} _id;
 bool _interleve;
 
 cv::Mat opencv;
 mxArray* matlab;
 
 typedef boost::bimap<mxClassID,unsigned char> bmtype;
 bmtype _idmap;
 void _initidmap();
 
 void _matlab2opencv();
 void _opencv2matlab();
};
 
#endif //__MATCV__H__

Source for matcv.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include "matcv.h"
 
Converter::Converter(mxArray* src,bool Interleve):matlab(src),_id(MATLAB_MXARRAY),_interleve(Interleve){
    _initidmap();
}
Converter::Converter(cv::Mat& src):opencv(src),_id(OPENCV_MAT){
    _initidmap();
}
 
Converter::operator cv::Mat()
{
    if(_id==OPENCV_MAT)
        return(opencv);
    _matlab2opencv();
    return(opencv);
}
 
Converter::operator mxArray*()
{
    if(_id==MATLAB_MXARRAY)
        return(matlab);
    _opencv2matlab();
    return(matlab);
}
 
void Converter::_initidmap()
{
    _idmap.insert(bmtype::value_type(mxINT8_CLASS,CV_8S));
    _idmap.insert(bmtype::value_type(mxUINT8_CLASS,CV_8U));
    _idmap.insert(bmtype::value_type(mxINT16_CLASS,CV_16S));
    _idmap.insert(bmtype::value_type(mxUINT16_CLASS,CV_16U));
    _idmap.insert(bmtype::value_type(mxINT32_CLASS,CV_32S));
    _idmap.insert(bmtype::value_type(mxSINGLE_CLASS,CV_32F));
    _idmap.insert(bmtype::value_type(mxDOUBLE_CLASS,CV_64F));
}
 
void  Converter::_opencv2matlab()
{
    //Is the data type supported?
    bmtype::right_map::const_iterator itr=_idmap.right.find(opencv.depth());
     
    //if not then
    if(itr==_idmap.right.end())
    {
        mexErrMsgTxt("OpenCV2Matlab:Unsupported data type.");
    }
     
    //Find the matlab data type
    mxClassID type=itr->second;
     
    //We support max 3 dimensions
    mwSignedIndex dims[3];
    dims[0]=opencv.rows;
    dims[1]=opencv.cols;
    dims[2]=opencv.channels();
     
    //if number of channels is 1, its a 2D array
    if(dims[0]>0 && dims[1]>0 && dims[2]==1)
    {
        //Create the array to be returned
        matlab=mxCreateNumericArray(2,dims,type,mxREAL);
        //Create opencv header for the matlab data
        cv::Mat tmp=cv::Mat(dims[1],dims[0],CV_MAKETYPE(opencv.depth(),1),mxGetData(matlab),0);
        //Transpose the opencv data to get row major data for matlab
        tmp=opencv.t();
         
        const mwSize* size=mxGetDimensions(matlab);
        mxAssert((opencv.rows==size[0])&(opencv.cols==size[1]),"OpenCV2Matlab:Conversion mismatch");
    }
    else
    {
        //Create the array to be returned
        matlab=mxCreateNumericArray(3,dims,type,mxREAL);
         
        //Seperate the channels
        std::vector<cv::Mat> chans(dims[2]);
        //cv::split(opencv,&chans[0]);
        cv::split(opencv,chans);
         
        //Create opencv header as a "flat" image for the matlab data
        cv::Mat tmp=cv::Mat(dims[1]*dims[2],dims[0],CV_MAKETYPE(opencv.depth(),1),mxGetData(matlab),0);
         
        for(int i=0;i<dims[2];i++)
        {
            //transpose the opencv channels image to row major matlab data
            cv::Mat tmp2=chans[i].t();
            //Copy the data to the flat matlab data
            tmp2.copyTo(tmp.rowRange(i*dims[1],(i+1)*dims[1]));
        }
         
        const mwSize* size=mxGetDimensions(matlab);
        mxAssert((opencv.rows==size[0])&(opencv.cols==size[1])&(opencv.channels()==size[2]),"OpenCV2Matlab:Conversion mismatch");
    }  
}
 
void  Converter::_matlab2opencv()
{
    //find the corresponding corresponding opencv data type
    bmtype::left_map::const_iterator itr=_idmap.left.find(mxGetClassID(matlab));
     
    //No corresponding type?
    if(itr==_idmap.left.end()| mxIsComplex(matlab) | mxIsSparse(matlab))
    {
        std::string msg="Matlab2OpenCV:Unsupported data type:"+(itr==_idmap.left.end()?std::string(mxGetClassName(matlab)):"")
        +(mxIsComplex(matlab)?" Complex":"")+(mxIsSparse(matlab)?" Sparse":".");
        mexErrMsgTxt(msg.c_str());
    }
     
    unsigned char type=itr->second;
     
    //Get number of dimensions
    const mwSize dims=mxGetNumberOfDimensions(matlab);
     
    //Cannot handle more that 3 dimensions
    if(dims>3)
    {
        std::ostringstream o;
        o<<"Matlab2OpenCV:Supports upto 3 dimensions. You supplied "<<dims<<".";
        mexErrMsgTxt(o.str().c_str());
    }
     
    //Get actual dimensions
    const mwSize* size=mxGetDimensions(matlab);
     
    //Check if 2 or 3 dimentions
    if(dims==2)
    {
        //Create header for row major matlab data
        const cv::Mat donotmodify=cv::Mat(size[1],size[0],CV_MAKETYPE(type,1),mxGetData(matlab),0);
         
        //Transpose the data so that it is column major for opencv.
        opencv=donotmodify.t();
        mxAssert((opencv.rows==size[0])&(opencv.cols==size[1]),"Matlab2OpenCV:Conversion mismatch");
    }
    else
    {
        //Create header for the "flat" matlab data
        const cv::Mat donotmodify=cv::Mat(size[1]*size[2],size[0],CV_MAKETYPE(type,1),mxGetData(matlab),0);
         
        //Transpose the flat data
        cv::Mat flat=donotmodify.t();
         
        //Create vector of channels to pass to opencv merge operataion
        std::vector<cv::Mat> chans(size[2]);
         
        for(int i=0;i<size[2];i++)
        {
            chans[i]=flat.colRange(i*size[1],(i+1)*size[1]);
        }
        cv::merge(chans,opencv);
        mxAssert((opencv.rows==size[0])&(opencv.cols==size[1])&(opencv.channels()==size[2]),"Matlab2OpenCV:Conversion mismatch");
    }
}


Posted by uniqueone
,