From bc93edac3473d1eba6e0f8f569343ca0ba17f1dd Mon Sep 17 00:00:00 2001 From: hbristow Date: Fri, 30 Aug 2013 11:18:08 +1000 Subject: [PATCH] Removed all OpenCV-specific functionality from mxarray into bridge. mxarray is now standalone --- .../matlab/include/opencv2/matlab/bridge.hpp | 168 +++++++++++++++- .../matlab/include/opencv2/matlab/mxarray.hpp | 184 ++---------------- 2 files changed, 169 insertions(+), 183 deletions(-) diff --git a/modules/matlab/include/opencv2/matlab/bridge.hpp b/modules/matlab/include/opencv2/matlab/bridge.hpp index 4b0ed29c6..a22373061 100644 --- a/modules/matlab/include/opencv2/matlab/bridge.hpp +++ b/modules/matlab/include/opencv2/matlab/bridge.hpp @@ -66,6 +66,18 @@ typedef cv::Ptr Ptr_StereoSGBM; typedef cv::Ptr Ptr_FeatureDetector; +// ---------------------------------------------------------------------------- +// PREDECLARATIONS +// ---------------------------------------------------------------------------- +class Bridge; + +template +void deepCopyAndTranspose(const cv::Mat& src, MxArray& dst); + +template +void deepCopyAndTranspose(const MxArray& src, cv::Mat& dst); + + // ---------------------------------------------------------------------------- @@ -157,10 +169,6 @@ public: } - - - - // -------------------------------------------------------------------------- // MATLAB TYPES // -------------------------------------------------------------------------- @@ -171,7 +179,50 @@ public: MxArray toMxArray() { return ptr_; } - + // -------------------------------------------------------------------------- + // MATRIX CONVERSIONS + // -------------------------------------------------------------------------- + Bridge& operator=(const cv::Mat& mat); + cv::Mat toMat() const; + operator cv::Mat() const { return toMat(); } + + template + static MxArray FromMat(const cv::Mat& mat) { + MxArray arr(mat.rows, mat.cols, mat.channels(), Matlab::Traits::ScalarType); + switch (mat.depth()) { + case CV_8U: deepCopyAndTranspose(mat, arr); break; + case CV_8S: deepCopyAndTranspose(mat, arr); break; + case CV_16U: deepCopyAndTranspose(mat, arr); break; + case CV_16S: deepCopyAndTranspose(mat, arr); break; + case CV_32S: deepCopyAndTranspose(mat, arr); break; + case CV_32F: deepCopyAndTranspose(mat, arr); break; + case CV_64F: deepCopyAndTranspose(mat, arr); break; + default: error("Attempted to convert from unknown class"); + } + return arr; + } + + template + cv::Mat toMat() const { + cv::Mat mat(ptr_.rows(), ptr_.cols(), CV_MAKETYPE(cv::DataType::type, ptr_.channels())); + switch (ptr_.ID()) { + case mxINT8_CLASS: deepCopyAndTranspose(ptr_, mat); break; + case mxUINT8_CLASS: deepCopyAndTranspose(ptr_, mat); break; + case mxINT16_CLASS: deepCopyAndTranspose(ptr_, mat); break; + case mxUINT16_CLASS: deepCopyAndTranspose(ptr_, mat); break; + case mxINT32_CLASS: deepCopyAndTranspose(ptr_, mat); break; + case mxUINT32_CLASS: deepCopyAndTranspose(ptr_, mat); break; + case mxINT64_CLASS: deepCopyAndTranspose(ptr_, mat); break; + case mxUINT64_CLASS: deepCopyAndTranspose(ptr_, mat); break; + case mxSINGLE_CLASS: deepCopyAndTranspose(ptr_, mat); break; + case mxDOUBLE_CLASS: deepCopyAndTranspose(ptr_, mat); break; + case mxCHAR_CLASS: deepCopyAndTranspose(ptr_, mat); break; + case mxLOGICAL_CLASS: deepCopyAndTranspose(ptr_, mat); break; + default: error("Attempted to convert from unknown class"); + } + return mat; + } + // -------------------------------------------------------------------------- @@ -213,11 +264,6 @@ public: // CORE OPENCV TYPES // -------------------------------------------------------------------------- - // --------------------------- cv::Mat -------------------------------------- - Bridge& operator=(const cv::Mat& mat) { ptr_ = MxArray::FromMat(mat); return *this; } - cv::Mat toMat() const { return ptr_.toMat(); } - operator cv::Mat() const { return toMat(); } - // -------------------------- Point -------------------------------------- Bridge& operator=(const cv::Point& ) { return *this; } cv::Point toPoint() const { return cv::Point(); } @@ -351,4 +397,106 @@ public: }; +/*! + * @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 <> +MxArray Bridge::FromMat(const cv::Mat& mat) { + switch (mat.depth()) { + case CV_8U: return FromMat(mat); + case CV_8S: return FromMat(mat); + case CV_16U: return FromMat(mat); + case CV_16S: return FromMat(mat); + case CV_32S: return FromMat(mat); + case CV_32F: return FromMat(mat); //NOTE: Matlab uses double as native type! + case CV_64F: return FromMat(mat); + default: error("Attempted to convert from unknown class"); + } + return MxArray(); +} + +/*! + * @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 Bridge::toMat() const { + switch (ptr_.ID()) { + case mxINT8_CLASS: return toMat(); + case mxUINT8_CLASS: return toMat(); + case mxINT16_CLASS: return toMat(); + case mxUINT16_CLASS: return toMat(); + case mxINT32_CLASS: return toMat(); + case mxUINT32_CLASS: return toMat(); + case mxINT64_CLASS: return toMat(); + case mxUINT64_CLASS: return toMat(); + case mxSINGLE_CLASS: return toMat(); + case mxDOUBLE_CLASS: return toMat(); //NOTE: OpenCV uses float as native type! + case mxCHAR_CLASS: return toMat(); + case mxLOGICAL_CLASS: return toMat(); + default: error("Attempted to convert from unknown class"); + } + return cv::Mat(); +} + +Bridge& Bridge::operator=(const cv::Mat& mat) { ptr_ = FromMat(mat); return *this; } +cv::Mat Bridge::toMat() const { return toMat(); } + + +// ---------------------------------------------------------------------------- +// MATRIX TRANSPOSE +// ---------------------------------------------------------------------------- + + +template +void deepCopyAndTranspose(const cv::Mat& in, MxArray& out) { + conditionalError(static_cast(in.rows) == out.rows(), "Matrices must have the same number of rows"); + conditionalError(static_cast(in.cols) == out.cols(), "Matrices must have the same number of cols"); + conditionalError(static_cast(in.channels()) == out.channels(), "Matrices must have the same number of channels"); + std::vector channels; + cv::split(in, channels); + for (size_t c = 0; c < out.channels(); ++c) { + cv::transpose(channels[c], channels[c]); + cv::Mat outmat(out.cols(), out.rows(), cv::DataType::type, + static_cast(out.real() + out.cols()*out.rows()*c)); + channels[c].convertTo(outmat, cv::DataType::type); + } + + //const InputScalar* inp = in.ptr(0); + //OutputScalar* outp = out.real(); + //gemt('R', out.rows(), out.cols(), inp, in.step1(), outp, out.rows()); +} + +template +void deepCopyAndTranspose(const MxArray& in, cv::Mat& out) { + conditionalError(in.rows() == static_cast(out.rows), "Matrices must have the same number of rows"); + conditionalError(in.cols() == static_cast(out.cols), "Matrices must have the same number of cols"); + conditionalError(in.channels() == static_cast(out.channels()), "Matrices must have the same number of channels"); + std::vector channels; + for (size_t c = 0; c < in.channels(); ++c) { + cv::Mat outmat; + cv::Mat inmat(in.cols(), in.rows(), cv::DataType::type, + static_cast(const_cast(in.real() + in.cols()*in.rows()*c))); + inmat.convertTo(outmat, cv::DataType::type); + cv::transpose(outmat, outmat); + channels.push_back(outmat); + } + cv::merge(channels, out); + + //const InputScalar* inp = in.real(); + //OutputScalar* outp = out.ptr(0); + //gemt('C', in.rows(), in.cols(), inp, in.rows(), outp, out.step1()); +} + + #endif diff --git a/modules/matlab/include/opencv2/matlab/mxarray.hpp b/modules/matlab/include/opencv2/matlab/mxarray.hpp index fe0f82f39..f831dd49d 100644 --- a/modules/matlab/include/opencv2/matlab/mxarray.hpp +++ b/modules/matlab/include/opencv2/matlab/mxarray.hpp @@ -43,15 +43,12 @@ #ifndef OPENCV_MXARRAY_HPP_ #define OPENCV_MXARRAY_HPP_ +#include #include #include #include #include -#include #include -#include -#include -#include #if __cplusplus > 201103 #include typedef std::unordered_set StringSet; @@ -59,8 +56,6 @@ typedef std::unordered_set StringSet; #include typedef std::set StringSet; #endif -#include -#include "transpose.hpp" /* * All recent versions of Matlab ship with the MKL library which contains @@ -103,20 +98,6 @@ static void error(const std::string& str) { } -// ---------------------------------------------------------------------------- -// PREDECLARATIONS -// ---------------------------------------------------------------------------- -class MxArray; - -template -void deepCopyAndTranspose(const cv::Mat& src, MxArray& dst); - -template -void deepCopyAndTranspose(const MxArray& src, cv::Mat& dst); - - - - // ---------------------------------------------------------------------------- // MATLAB TRAITS // ---------------------------------------------------------------------------- @@ -407,44 +388,6 @@ public: return ptr_; } - - template - static MxArray FromMat(const cv::Mat& mat) { - MxArray arr(mat.rows, mat.cols, mat.channels(), Matlab::Traits::ScalarType); - switch (mat.depth()) { - case CV_8U: deepCopyAndTranspose(mat, arr); break; - case CV_8S: deepCopyAndTranspose(mat, arr); break; - case CV_16U: deepCopyAndTranspose(mat, arr); break; - case CV_16S: deepCopyAndTranspose(mat, arr); break; - case CV_32S: deepCopyAndTranspose(mat, arr); break; - case CV_32F: deepCopyAndTranspose(mat, arr); break; - case CV_64F: deepCopyAndTranspose(mat, arr); break; - default: error("Attempted to convert from unknown class"); - } - return arr; - } - - template - cv::Mat toMat() const { - cv::Mat mat(rows(), cols(), CV_MAKETYPE(cv::DataType::type, channels())); - switch (ID()) { - case mxINT8_CLASS: deepCopyAndTranspose(*this, mat); break; - case mxUINT8_CLASS: deepCopyAndTranspose(*this, mat); break; - case mxINT16_CLASS: deepCopyAndTranspose(*this, mat); break; - case mxUINT16_CLASS: deepCopyAndTranspose(*this, mat); break; - case mxINT32_CLASS: deepCopyAndTranspose(*this, mat); break; - case mxUINT32_CLASS: deepCopyAndTranspose(*this, mat); break; - case mxINT64_CLASS: deepCopyAndTranspose(*this, mat); break; - case mxUINT64_CLASS: deepCopyAndTranspose(*this, mat); break; - case mxSINGLE_CLASS: deepCopyAndTranspose(*this, mat); break; - case mxDOUBLE_CLASS: deepCopyAndTranspose(*this, mat); break; - case mxCHAR_CLASS: deepCopyAndTranspose(*this, mat); break; - case mxLOGICAL_CLASS: deepCopyAndTranspose(*this, mat); break; - default: error("Attempted to convert from unknown class"); - } - return mat; - } - MxArray field(const std::string& name) { return MxArray(mxGetField(ptr_, 0, name.c_str())); } template @@ -486,6 +429,10 @@ public: }; +// ---------------------------------------------------------------------------- +// ARGUMENT PARSER +// ---------------------------------------------------------------------------- + /*! @class ArgumentParser * @brief parses inputs to a method and resolves the argument names. * @@ -568,6 +515,8 @@ private: : name_(name), Nreq_(Nreq), Nopt_(Nopt), keys_(keys), order_(Nreq+Nopt, Nreq+2*Nopt), valid_(true), nparsed_(0), nkeys_(0), working_opt_(0), expecting_val_(false), using_named_(false) {} + /*! @brief the name of the variant */ + String name() const { return name_; } /*! @brief return the total number of arguments the variant can take */ size_t size() const { return Nreq_ + Nopt_; } /*! @brief has the variant been fulfilled? */ @@ -613,14 +562,12 @@ private: void sortArguments(Variant& v, MxArrayVector& in, MxArrayVector& out) { // allocate the output array with ALL arguments out.resize(v.size()); - std::copy(v.order().begin(), v.order().end(), std::ostream_iterator(std::cout, ", ")); // reorder the inputs based on the variant ordering for (size_t n = 0; n < v.size(); ++n) { if (v.order(n) >= in.size()) continue; swap(in[v.order(n)], out[n]); } } - MxArrayVector filled_; VariantVector variants_; String valid_; String method_name_; @@ -668,6 +615,7 @@ public: */ MxArrayVector parse(const MxArrayVector& inputs) { // allocate the outputs + String variant_string; MxArrayVector outputs; VariantVector candidates = variants_; @@ -675,25 +623,16 @@ public: for (MxArrayVector::const_iterator input = inputs.begin(); input != inputs.end(); ++input) { String name = input->isString() ? input->toString() : String(); for (VariantVector::iterator candidate = candidates.begin(); candidate < candidates.end(); ++candidate) { - if (candidate->exist(name)) { - mexPrintf("%d\n", candidate->parseNextAsKey(name)); - } else { - mexPrintf("%d\n", candidate->parseNextAsValue()); - } + candidate->exist(name) ? candidate->parseNextAsKey(name) : candidate->parseNextAsValue(); } } - mexPrintf("We get here!\n"); - // make sure the candidates have been fulfilled for (VariantVector::iterator candidate = candidates.begin(); candidate < candidates.end(); ++candidate) { - if (!candidate->fulfilled()) { - candidate = candidates.erase(candidate)--; - } + if (!candidate->fulfilled()) candidate = candidates.erase(candidate)--; } // if there is not a unique candidate, throw an error - String variant_string; for (VariantVector::iterator variant = variants_.begin(); variant != variants_.end(); ++variant) { variant_string += "\n" + variant->toString(method_name_); } @@ -708,111 +647,10 @@ public: } // Unique candidate! + valid_ = candidates[0].name(); sortArguments(candidates[0], const_cast(inputs), outputs); return outputs; } }; - -/*! - * @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 <> -MxArray MxArray::FromMat(const cv::Mat& mat) { - switch (mat.depth()) { - case CV_8U: return FromMat(mat); - case CV_8S: return FromMat(mat); - case CV_16U: return FromMat(mat); - case CV_16S: return FromMat(mat); - case CV_32S: return FromMat(mat); - case CV_32F: return FromMat(mat); //NOTE: Matlab uses double as native type! - case CV_64F: return FromMat(mat); - default: error("Attempted to convert from unknown class"); - } - return MxArray(); -} - -/*! - * @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() const { - switch (ID()) { - case mxINT8_CLASS: return toMat(); - case mxUINT8_CLASS: return toMat(); - case mxINT16_CLASS: return toMat(); - case mxUINT16_CLASS: return toMat(); - case mxINT32_CLASS: return toMat(); - case mxUINT32_CLASS: return toMat(); - case mxINT64_CLASS: return toMat(); - case mxUINT64_CLASS: return toMat(); - case mxSINGLE_CLASS: return toMat(); - case mxDOUBLE_CLASS: return toMat(); //NOTE: OpenCV uses float as native type! - case mxCHAR_CLASS: return toMat(); - case mxLOGICAL_CLASS: return toMat(); - default: error("Attempted to convert from unknown class"); - } - return cv::Mat(); -} - - - -// ---------------------------------------------------------------------------- -// MATRIX TRANSPOSE -// ---------------------------------------------------------------------------- - - -template -void deepCopyAndTranspose(const cv::Mat& in, MxArray& out) { - conditionalError(static_cast(in.rows) == out.rows(), "Matrices must have the same number of rows"); - conditionalError(static_cast(in.cols) == out.cols(), "Matrices must have the same number of cols"); - conditionalError(static_cast(in.channels()) == out.channels(), "Matrices must have the same number of channels"); - std::vector channels; - cv::split(in, channels); - for (size_t c = 0; c < out.channels(); ++c) { - cv::transpose(channels[c], channels[c]); - cv::Mat outmat(out.cols(), out.rows(), cv::DataType::type, - static_cast(out.real() + out.cols()*out.rows()*c)); - channels[c].convertTo(outmat, cv::DataType::type); - } - - //const InputScalar* inp = in.ptr(0); - //OutputScalar* outp = out.real(); - //gemt('R', out.rows(), out.cols(), inp, in.step1(), outp, out.rows()); -} - -template -void deepCopyAndTranspose(const MxArray& in, cv::Mat& out) { - conditionalError(in.rows() == static_cast(out.rows), "Matrices must have the same number of rows"); - conditionalError(in.cols() == static_cast(out.cols), "Matrices must have the same number of cols"); - conditionalError(in.channels() == static_cast(out.channels()), "Matrices must have the same number of channels"); - std::vector channels; - for (size_t c = 0; c < in.channels(); ++c) { - cv::Mat outmat; - cv::Mat inmat(in.cols(), in.rows(), cv::DataType::type, - static_cast(const_cast(in.real() + in.cols()*in.rows()*c))); - inmat.convertTo(outmat, cv::DataType::type); - cv::transpose(outmat, outmat); - channels.push_back(outmat); - } - cv::merge(channels, out); - - //const InputScalar* inp = in.real(); - //OutputScalar* outp = out.ptr(0); - //gemt('C', in.rows(), in.cols(), inp, in.rows(), outp, out.step1()); -} - - - #endif