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