Improved bridge. Fixed I/O problem in function template
This commit is contained in:
parent
53c9c40eba
commit
53a7fbf74b
@ -35,7 +35,7 @@ void mexFunction(int nlhs, mxArray* plhs[],
|
|||||||
conditionalError(nlhs <= {{ fun.rtp|void|not + fun.req|outputs|length + fun.opt|outputs|length}}, "Too many output arguments specified");
|
conditionalError(nlhs <= {{ fun.rtp|void|not + fun.req|outputs|length + fun.opt|outputs|length}}, "Too many output arguments specified");
|
||||||
|
|
||||||
// setup
|
// setup
|
||||||
std::vector<Bridge> inputs(plhs, plhs+nrhs);
|
std::vector<Bridge> inputs(prhs, prhs+nrhs);
|
||||||
{% set noutputs = fun.rtp|void|not + fun.req|outputs|length + fun.opt|outputs|length %}
|
{% set noutputs = fun.rtp|void|not + fun.req|outputs|length + fun.opt|outputs|length %}
|
||||||
{%- if noutputs %}
|
{%- if noutputs %}
|
||||||
std::vector<Bridge> outputs({{noutputs}});
|
std::vector<Bridge> outputs({{noutputs}});
|
||||||
|
@ -46,93 +46,139 @@ typedef cv::Ptr<cv::StereoSGBM> Ptr_StereoSGBM;
|
|||||||
typedef cv::Ptr<cv::FeatureDetector> Ptr_FeatureDetector;
|
typedef cv::Ptr<cv::FeatureDetector> Ptr_FeatureDetector;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief raise error if condition fails
|
||||||
|
*
|
||||||
|
* This is a conditional wrapper for mexErrMsgTxt. If the conditional
|
||||||
|
* expression fails, an error is raised and the mex function returns
|
||||||
|
* to Matlab, otherwise this function does nothing
|
||||||
|
*/
|
||||||
void conditionalError(bool expr, const std::string& str) {
|
void conditionalError(bool expr, const std::string& str) {
|
||||||
if (!expr) mexErrMsgTxt(std::string("condition failed: ").append(str).c_str());
|
if (!expr) mexErrMsgTxt(std::string("condition failed: ").append(str).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief raise an error
|
||||||
|
*
|
||||||
|
* This function is a wrapper around mexErrMsgTxt
|
||||||
|
*/
|
||||||
void error(const std::string& str) {
|
void error(const std::string& str) {
|
||||||
mexErrMsgTxt(str.c_str());
|
mexErrMsgTxt(str.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// PREDECLARATIONS
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
class MxArray;
|
||||||
|
class Bridge;
|
||||||
|
|
||||||
|
template <typename InputScalar, typename OutputScalar>
|
||||||
|
void deepCopyAndTranspose(const cv::Mat& src, MxArray& dst);
|
||||||
|
|
||||||
|
template <typename InputScalar, typename OutputScalar>
|
||||||
|
void deepCopyAndTranspose(const MxArray& src, cv::Mat& dst);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// MATLAB TRAITS
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
namespace Matlab {
|
namespace Matlab {
|
||||||
class DefaultTraits {};
|
class DefaultTraits {};
|
||||||
class InheritType {};
|
class InheritType {};
|
||||||
static const int Dynamic = -1;
|
static const int Dynamic = -1;
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
// INTERNAL TRAITS CLASS
|
|
||||||
// --------------------------------------------------------------------------
|
|
||||||
template<typename _Tp = DefaultTraits> class Traits {
|
template<typename _Tp = DefaultTraits> class Traits {
|
||||||
public:
|
public:
|
||||||
static const mxClassID ScalarType = mxUNKNOWN_CLASS;
|
static const mxClassID ScalarType = mxUNKNOWN_CLASS;
|
||||||
static const mxComplexity Complex = mxCOMPLEX;
|
static const mxComplexity Complex = mxCOMPLEX;
|
||||||
static const mxComplexity Real = mxCOMPLEX;
|
static const mxComplexity Real = mxCOMPLEX;
|
||||||
|
static std::string ToString() { return "Unknown/Unsupported"; }
|
||||||
};
|
};
|
||||||
// bool
|
// bool
|
||||||
template<> class Traits<bool> {
|
template<> class Traits<bool> {
|
||||||
public:
|
public:
|
||||||
static const mxClassID ScalarType = mxLOGICAL_CLASS;
|
static const mxClassID ScalarType = mxLOGICAL_CLASS;
|
||||||
|
static std::string ToString() { return "boolean"; }
|
||||||
};
|
};
|
||||||
// uint8_t
|
// uint8_t
|
||||||
template<> class Traits<uint8_t> {
|
template<> class Traits<uint8_t> {
|
||||||
public:
|
public:
|
||||||
static const mxClassID ScalarType = mxUINT8_CLASS;
|
static const mxClassID ScalarType = mxUINT8_CLASS;
|
||||||
|
static std::string ToString() { return "uint8_t"; }
|
||||||
};
|
};
|
||||||
// int8_t
|
// int8_t
|
||||||
template<> class Traits<int8_t> {
|
template<> class Traits<int8_t> {
|
||||||
public:
|
public:
|
||||||
static const mxClassID ScalarType = mxINT8_CLASS;
|
static const mxClassID ScalarType = mxINT8_CLASS;
|
||||||
|
static std::string ToString() { return "int8_t"; }
|
||||||
};
|
};
|
||||||
// uint16_t
|
// uint16_t
|
||||||
template<> class Traits<uint16_t> {
|
template<> class Traits<uint16_t> {
|
||||||
public:
|
public:
|
||||||
static const mxClassID ScalarType = mxUINT16_CLASS;
|
static const mxClassID ScalarType = mxUINT16_CLASS;
|
||||||
|
static std::string ToString() { return "uint16_t"; }
|
||||||
};
|
};
|
||||||
// int16_t
|
// int16_t
|
||||||
template<> class Traits<int16_t> {
|
template<> class Traits<int16_t> {
|
||||||
public:
|
public:
|
||||||
static const mxClassID ScalarType = mxINT16_CLASS;
|
static const mxClassID ScalarType = mxINT16_CLASS;
|
||||||
|
static std::string ToString() { return "int16_t"; }
|
||||||
};
|
};
|
||||||
// uint32_t
|
// uint32_t
|
||||||
template<> class Traits<uint32_t> {
|
template<> class Traits<uint32_t> {
|
||||||
public:
|
public:
|
||||||
static const mxClassID ScalarType = mxUINT32_CLASS;
|
static const mxClassID ScalarType = mxUINT32_CLASS;
|
||||||
|
static std::string ToString() { return "uint32_t"; }
|
||||||
};
|
};
|
||||||
// int32_t
|
// int32_t
|
||||||
template<> class Traits<int32_t> {
|
template<> class Traits<int32_t> {
|
||||||
public:
|
public:
|
||||||
static const mxClassID ScalarType = mxINT32_CLASS;
|
static const mxClassID ScalarType = mxINT32_CLASS;
|
||||||
|
static std::string ToString() { return "int32_t"; }
|
||||||
};
|
};
|
||||||
// uint64_t
|
// uint64_t
|
||||||
template<> class Traits<uint64_t> {
|
template<> class Traits<uint64_t> {
|
||||||
public:
|
public:
|
||||||
static const mxClassID ScalarType = mxUINT64_CLASS;
|
static const mxClassID ScalarType = mxUINT64_CLASS;
|
||||||
|
static std::string ToString() { return "uint64_t"; }
|
||||||
};
|
};
|
||||||
// int64_t
|
// int64_t
|
||||||
template<> class Traits<int64_t> {
|
template<> class Traits<int64_t> {
|
||||||
public:
|
public:
|
||||||
static const mxClassID ScalarType = mxINT64_CLASS;
|
static const mxClassID ScalarType = mxINT64_CLASS;
|
||||||
|
static std::string ToString() { return "int64_t"; }
|
||||||
};
|
};
|
||||||
// float
|
// float
|
||||||
template<> class Traits<float> {
|
template<> class Traits<float> {
|
||||||
public:
|
public:
|
||||||
static const mxClassID ScalarType = mxSINGLE_CLASS;
|
static const mxClassID ScalarType = mxSINGLE_CLASS;
|
||||||
|
static std::string ToString() { return "float"; }
|
||||||
};
|
};
|
||||||
// double
|
// double
|
||||||
template<> class Traits<double> {
|
template<> class Traits<double> {
|
||||||
public:
|
public:
|
||||||
static const mxClassID ScalarType = mxDOUBLE_CLASS;
|
static const mxClassID ScalarType = mxDOUBLE_CLASS;
|
||||||
|
static std::string ToString() { return "double"; }
|
||||||
};
|
};
|
||||||
// size_t
|
// size_t
|
||||||
template<> class Traits<size_t> {
|
template<> class Traits<size_t> {
|
||||||
public:
|
public:
|
||||||
static const mxClassID ScalarType = (sizeof(size_t) == 4) ? mxUINT32_CLASS : mxUINT64_CLASS;
|
static const mxClassID ScalarType = (sizeof(size_t) == 4) ? mxUINT32_CLASS : mxUINT64_CLASS;
|
||||||
|
static std::string ToString() { return "size_t"; }
|
||||||
};
|
};
|
||||||
// char
|
// char
|
||||||
template<> class Traits<char> {
|
template<> class Traits<char> {
|
||||||
public:
|
public:
|
||||||
static const mxClassID ScalarType = mxCHAR_CLASS;
|
static const mxClassID ScalarType = mxCHAR_CLASS;
|
||||||
|
static std::string ToString() { return "char"; }
|
||||||
|
};
|
||||||
|
// char
|
||||||
|
template<> class Traits<Matlab::InheritType> {
|
||||||
|
public:
|
||||||
|
static std::string ToString() { return "Inherited type"; }
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -149,18 +195,63 @@ namespace Matlab {
|
|||||||
*
|
*
|
||||||
* MxArray provides a thin object oriented wrapper around Matlab's
|
* MxArray provides a thin object oriented wrapper around Matlab's
|
||||||
* native mxArray type which exposes most of the functionality of the
|
* native mxArray type which exposes most of the functionality of the
|
||||||
* Matlab interface, but in a more C++ manner.
|
* Matlab interface, but in a more C++ manner. MxArray objects are scoped,
|
||||||
|
* so you can freely create and destroy them without worrying about memory
|
||||||
|
* management. If you wish to pass the underlying mxArray* representation
|
||||||
|
* back to Matlab as an lvalue, see the releaseOwnership() method
|
||||||
*/
|
*/
|
||||||
class MxArray {
|
class MxArray {
|
||||||
private:
|
private:
|
||||||
mxArray* ptr_;
|
mxArray* ptr_;
|
||||||
bool owns_;
|
bool owns_;
|
||||||
|
|
||||||
|
// this function is called exclusively from constructors!!
|
||||||
|
template <typename Scalar>
|
||||||
|
void fromMat(const cv::Mat& mat) {
|
||||||
|
mwSize dims[] = { mat.rows, mat.cols, mat.channels() };
|
||||||
|
ptr_ = mxCreateNumericArray(3, dims, Matlab::Traits<Scalar>::ScalarType, Matlab::Traits<>::Real);
|
||||||
|
owns_ = true;
|
||||||
|
switch (mat.depth()) {
|
||||||
|
case CV_8U: deepCopyAndTranspose<uint8_t, Scalar>(mat, *this); break;
|
||||||
|
case CV_8S: deepCopyAndTranspose<int8_t, Scalar>(mat, *this); break;
|
||||||
|
case CV_16U: deepCopyAndTranspose<uint16_t, Scalar>(mat, *this); break;
|
||||||
|
case CV_16S: deepCopyAndTranspose<int16_t, Scalar>(mat, *this); break;
|
||||||
|
case CV_32S: deepCopyAndTranspose<int32_t, Scalar>(mat, *this); break;
|
||||||
|
case CV_32F: deepCopyAndTranspose<float, Scalar>(mat, *this); break;
|
||||||
|
case CV_64F: deepCopyAndTranspose<double, Scalar>(mat, *this); break;
|
||||||
|
default: error("Attempted to convert from unknown class");
|
||||||
|
}
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
MxArray() : ptr_(NULL), owns_(false) {}
|
// constructors and destructor
|
||||||
|
MxArray() : ptr_(mxCreateDoubleMatrix(1, 1, Matlab::Traits<>::Real)), owns_(true) {}
|
||||||
MxArray(const mxArray* ptr) : ptr_(const_cast<mxArray *>(ptr)), owns_(false) {}
|
MxArray(const mxArray* ptr) : ptr_(const_cast<mxArray *>(ptr)), owns_(false) {}
|
||||||
~MxArray() {
|
virtual ~MxArray() {
|
||||||
if (owns_ && ptr_) mxDestroyArray(ptr_);
|
if (owns_ && ptr_) mxDestroyArray(ptr_);
|
||||||
}
|
}
|
||||||
|
// copy constructor
|
||||||
|
// all copies are deep copies
|
||||||
|
MxArray(const MxArray& other) : ptr_(mxDuplicateArray(other.ptr_)), owns_(true) {}
|
||||||
|
// swap
|
||||||
|
friend void swap(MxArray& first, MxArray& second) {
|
||||||
|
using std::swap;
|
||||||
|
swap(first.ptr_, second.ptr_);
|
||||||
|
swap(first.owns_, second.owns_);
|
||||||
|
}
|
||||||
|
// assignment operator
|
||||||
|
// copy-and-swap idiom
|
||||||
|
// all copies are deep copies
|
||||||
|
MxArray& operator=(MxArray other) {
|
||||||
|
swap(*this, other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
// move constructor, if C++11
|
||||||
|
// default construct and swap
|
||||||
|
MxArray(MxArray&& other) : MxArray() {
|
||||||
|
swap(*this, other);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @brief release ownership to allow return into Matlab workspace
|
* @brief release ownership to allow return into Matlab workspace
|
||||||
@ -189,7 +280,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: Make sure NULL pointers are checked in all functions!
|
|
||||||
template <typename Scalar>
|
template <typename Scalar>
|
||||||
explicit MxArray(size_t m, size_t n, size_t k=1) : owns_(true) {
|
explicit MxArray(size_t m, size_t n, size_t k=1) : owns_(true) {
|
||||||
mwSize dims[] = {m, n, k};
|
mwSize dims[] = {m, n, k};
|
||||||
@ -197,24 +287,29 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Scalar>
|
template <typename Scalar>
|
||||||
explicit MxArray(const cv::Mat& mat) : owns_(true) {
|
explicit MxArray(const cv::Mat& mat) : owns_(false) {
|
||||||
mwSize dims[] = { mat.rows, mat.cols, mat.channels() };
|
fromMat<Scalar>(mat);
|
||||||
if (mat.channels() == 2) {
|
|
||||||
ptr_ = mxCreateNumericArray(2, dims, Matlab::Traits<Scalar>::ScalarType, Matlab::Traits<>::Complex);
|
|
||||||
} else {
|
|
||||||
ptr_ = mxCreateNumericArray(2, dims, Matlab::Traits<Scalar>::ScalarType, Matlab::Traits<>::Real);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Scalar>
|
template <typename Scalar>
|
||||||
cv::Mat toMat() const {
|
cv::Mat toMat() const {
|
||||||
cv::Mat mat(cols(), rows(), CV_MAKETYPE(cv::DataType<Scalar>::type, channels()));
|
cv::Mat mat(cols(), rows(), CV_MAKETYPE(cv::DataType<Scalar>::type, channels()));
|
||||||
return mat;
|
switch (ID()) {
|
||||||
|
case mxINT8_CLASS: deepCopyAndTranspose<int8_t, Scalar>(*this, mat); break;
|
||||||
|
case mxUINT8_CLASS: deepCopyAndTranspose<uint8_t, Scalar>(*this, mat); break;
|
||||||
|
case mxINT16_CLASS: deepCopyAndTranspose<int16_t, Scalar>(*this, mat); break;
|
||||||
|
case mxUINT16_CLASS: deepCopyAndTranspose<uint16_t, Scalar>(*this, mat); break;
|
||||||
|
case mxINT32_CLASS: deepCopyAndTranspose<int32_t, Scalar>(*this, mat); break;
|
||||||
|
case mxUINT32_CLASS: deepCopyAndTranspose<uint32_t, Scalar>(*this, mat); break;
|
||||||
|
case mxINT64_CLASS: deepCopyAndTranspose<int64_t, Scalar>(*this, mat); break;
|
||||||
|
case mxUINT64_CLASS: deepCopyAndTranspose<uint64_t, Scalar>(*this, mat); break;
|
||||||
|
case mxSINGLE_CLASS: deepCopyAndTranspose<float, Scalar>(*this, mat); break;
|
||||||
|
case mxDOUBLE_CLASS: deepCopyAndTranspose<double, Scalar>(*this, mat); break;
|
||||||
|
case mxCHAR_CLASS: deepCopyAndTranspose<char, Scalar>(*this, mat); break;
|
||||||
|
case mxLOGICAL_CLASS: deepCopyAndTranspose<int8_t, Scalar>(*this, mat); break;
|
||||||
|
default: error("Attempted to convert from unknown class");
|
||||||
}
|
}
|
||||||
|
return mat;
|
||||||
template <typename Scalar>
|
|
||||||
void fromMat(const cv::Mat& mat) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MxArray field(const std::string& name) { return MxArray(mxGetField(ptr_, 0, name.c_str())); }
|
MxArray field(const std::string& name) { return MxArray(mxGetField(ptr_, 0, name.c_str())); }
|
||||||
@ -259,14 +354,55 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <>
|
/*!
|
||||||
cv::Mat MxArray::toMat<Matlab::InheritType>() const {
|
* @brief template specialization for inheriting types
|
||||||
return cv::Mat();
|
*
|
||||||
}
|
* This template specialization attempts to preserve the best mapping
|
||||||
|
* between OpenCV and Matlab types. Matlab uses double types almost universally, so
|
||||||
|
* all floating float types are converted to doubles.
|
||||||
|
* Unfortunately OpenCV does not have a native logical type, so
|
||||||
|
* that gets mapped to an unsigned 8-bit value
|
||||||
|
*/
|
||||||
template <>
|
template <>
|
||||||
void MxArray::fromMat<Matlab::InheritType>(const cv::Mat& mat) {
|
void MxArray::fromMat<Matlab::InheritType>(const cv::Mat& mat) {
|
||||||
|
switch (mat.depth()) {
|
||||||
|
case CV_8U: fromMat<uint8_t>(mat); break;
|
||||||
|
case CV_8S: fromMat<int8_t>(mat); break;
|
||||||
|
case CV_16U: fromMat<uint16_t>(mat); break;
|
||||||
|
case CV_16S: fromMat<int16_t>(mat); break;
|
||||||
|
case CV_32S: fromMat<int32_t>(mat); break;
|
||||||
|
case CV_32F: fromMat<double>(mat); break; //NOTE: Matlab uses double as native type!
|
||||||
|
case CV_64F: fromMat<double>(mat); break;
|
||||||
|
default: error("Attempted to convert from unknown class");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @brief template specialization for inheriting types
|
||||||
|
*
|
||||||
|
* This template specialization attempts to preserve the best mapping
|
||||||
|
* between Matlab and OpenCV types. OpenCV has poor support for double precision
|
||||||
|
* types, so all floating point types are cast to float. Logicals get cast
|
||||||
|
* to unsignd 8-bit value.
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
cv::Mat MxArray::toMat<Matlab::InheritType>() const {
|
||||||
|
switch (ID()) {
|
||||||
|
case mxINT8_CLASS: return toMat<int8_t>();
|
||||||
|
case mxUINT8_CLASS: return toMat<uint8_t>();;
|
||||||
|
case mxINT16_CLASS: return toMat<int16_t>();
|
||||||
|
case mxUINT16_CLASS: return toMat<uint16_t>();
|
||||||
|
case mxINT32_CLASS: return toMat<int32_t>();
|
||||||
|
case mxUINT32_CLASS: return toMat<int32_t>();
|
||||||
|
case mxINT64_CLASS: return toMat<int64_t>();
|
||||||
|
case mxUINT64_CLASS: return toMat<int64_t>();
|
||||||
|
case mxSINGLE_CLASS: return toMat<float>();
|
||||||
|
case mxDOUBLE_CLASS: return toMat<float>(); //NOTE: OpenCV uses float as native type!
|
||||||
|
case mxCHAR_CLASS: return toMat<int8_t>();
|
||||||
|
case mxLOGICAL_CLASS: return toMat<int8_t>();
|
||||||
|
default: error("Attempted to convert from unknown class");
|
||||||
|
}
|
||||||
|
return cv::Mat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -293,10 +429,12 @@ void deepCopyAndTranspose<double, double>(const cv::Mat& src, MxArray& dst) {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
void deepCopyAndTranspose<float, float>(const MxArray& src, cv::Mat& dst) {
|
void deepCopyAndTranspose<float, float>(const MxArray& src, cv::Mat& dst) {
|
||||||
|
// use mkl
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void deepCopyAndTranspose<double, double>(const MxArray& src, cv::Mat& dst) {
|
void deepCopyAndTranspose<double, double>(const MxArray& src, cv::Mat& dst) {
|
||||||
|
// use mkl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -560,7 +698,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// OPENCV COMPLEX TYPES
|
// OPENCV COMPOUND TYPES
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
// --------------------------- Ptr_StereoBM -----------------------------
|
// --------------------------- Ptr_StereoBM -----------------------------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user