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");
|
||||
|
||||
// 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 %}
|
||||
{%- if noutputs %}
|
||||
std::vector<Bridge> outputs({{noutputs}});
|
||||
|
@ -46,93 +46,139 @@ typedef cv::Ptr<cv::StereoSGBM> Ptr_StereoSGBM;
|
||||
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) {
|
||||
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) {
|
||||
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 {
|
||||
class DefaultTraits {};
|
||||
class InheritType {};
|
||||
static const int Dynamic = -1;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// INTERNAL TRAITS CLASS
|
||||
// --------------------------------------------------------------------------
|
||||
template<typename _Tp = DefaultTraits> class Traits {
|
||||
public:
|
||||
static const mxClassID ScalarType = mxUNKNOWN_CLASS;
|
||||
static const mxComplexity Complex = mxCOMPLEX;
|
||||
static const mxComplexity Real = mxCOMPLEX;
|
||||
static std::string ToString() { return "Unknown/Unsupported"; }
|
||||
};
|
||||
// bool
|
||||
template<> class Traits<bool> {
|
||||
public:
|
||||
static const mxClassID ScalarType = mxLOGICAL_CLASS;
|
||||
static std::string ToString() { return "boolean"; }
|
||||
};
|
||||
// uint8_t
|
||||
template<> class Traits<uint8_t> {
|
||||
public:
|
||||
static const mxClassID ScalarType = mxUINT8_CLASS;
|
||||
static std::string ToString() { return "uint8_t"; }
|
||||
};
|
||||
// int8_t
|
||||
template<> class Traits<int8_t> {
|
||||
public:
|
||||
static const mxClassID ScalarType = mxINT8_CLASS;
|
||||
static std::string ToString() { return "int8_t"; }
|
||||
};
|
||||
// uint16_t
|
||||
template<> class Traits<uint16_t> {
|
||||
public:
|
||||
static const mxClassID ScalarType = mxUINT16_CLASS;
|
||||
static std::string ToString() { return "uint16_t"; }
|
||||
};
|
||||
// int16_t
|
||||
template<> class Traits<int16_t> {
|
||||
public:
|
||||
static const mxClassID ScalarType = mxINT16_CLASS;
|
||||
static std::string ToString() { return "int16_t"; }
|
||||
};
|
||||
// uint32_t
|
||||
template<> class Traits<uint32_t> {
|
||||
public:
|
||||
static const mxClassID ScalarType = mxUINT32_CLASS;
|
||||
static std::string ToString() { return "uint32_t"; }
|
||||
};
|
||||
// int32_t
|
||||
template<> class Traits<int32_t> {
|
||||
public:
|
||||
static const mxClassID ScalarType = mxINT32_CLASS;
|
||||
static std::string ToString() { return "int32_t"; }
|
||||
};
|
||||
// uint64_t
|
||||
template<> class Traits<uint64_t> {
|
||||
public:
|
||||
static const mxClassID ScalarType = mxUINT64_CLASS;
|
||||
static std::string ToString() { return "uint64_t"; }
|
||||
};
|
||||
// int64_t
|
||||
template<> class Traits<int64_t> {
|
||||
public:
|
||||
static const mxClassID ScalarType = mxINT64_CLASS;
|
||||
static std::string ToString() { return "int64_t"; }
|
||||
};
|
||||
// float
|
||||
template<> class Traits<float> {
|
||||
public:
|
||||
static const mxClassID ScalarType = mxSINGLE_CLASS;
|
||||
static std::string ToString() { return "float"; }
|
||||
};
|
||||
// double
|
||||
template<> class Traits<double> {
|
||||
public:
|
||||
static const mxClassID ScalarType = mxDOUBLE_CLASS;
|
||||
static std::string ToString() { return "double"; }
|
||||
};
|
||||
// size_t
|
||||
template<> class Traits<size_t> {
|
||||
public:
|
||||
static const mxClassID ScalarType = (sizeof(size_t) == 4) ? mxUINT32_CLASS : mxUINT64_CLASS;
|
||||
static std::string ToString() { return "size_t"; }
|
||||
};
|
||||
// char
|
||||
template<> class Traits<char> {
|
||||
public:
|
||||
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
|
||||
* 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 {
|
||||
private:
|
||||
mxArray* ptr_;
|
||||
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:
|
||||
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() {
|
||||
virtual ~MxArray() {
|
||||
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
|
||||
@ -189,7 +280,6 @@ public:
|
||||
}
|
||||
|
||||
|
||||
// TODO: Make sure NULL pointers are checked in all functions!
|
||||
template <typename Scalar>
|
||||
explicit MxArray(size_t m, size_t n, size_t k=1) : owns_(true) {
|
||||
mwSize dims[] = {m, n, k};
|
||||
@ -197,26 +287,31 @@ public:
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
explicit MxArray(const cv::Mat& mat) : owns_(true) {
|
||||
mwSize dims[] = { mat.rows, mat.cols, mat.channels() };
|
||||
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);
|
||||
}
|
||||
explicit MxArray(const cv::Mat& mat) : owns_(false) {
|
||||
fromMat<Scalar>(mat);
|
||||
}
|
||||
|
||||
template <typename Scalar>
|
||||
cv::Mat toMat() const {
|
||||
cv::Mat mat(cols(), rows(), CV_MAKETYPE(cv::DataType<Scalar>::type, channels()));
|
||||
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())); }
|
||||
|
||||
template <typename Scalar>
|
||||
@ -259,14 +354,55 @@ public:
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
cv::Mat MxArray::toMat<Matlab::InheritType>() const {
|
||||
return cv::Mat();
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief template specialization for inheriting types
|
||||
*
|
||||
* 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 <>
|
||||
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 <>
|
||||
void deepCopyAndTranspose<float, float>(const MxArray& src, cv::Mat& dst) {
|
||||
// use mkl
|
||||
}
|
||||
|
||||
template <>
|
||||
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 -----------------------------
|
||||
|
Loading…
x
Reference in New Issue
Block a user