vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e

This commit is contained in:
Gitea Mirror Bot
2026-08-22 00:11:13 +08:00
commit 12022378a3
3872 changed files with 2513409 additions and 0 deletions
@@ -0,0 +1,688 @@
////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this
// license. If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote
// products derived from this software without specific prior written
// permission.
//
// This software is provided by the copyright holders and contributors "as is"
// and any express or implied warranties, including, but not limited to, the
// implied warranties of merchantability and fitness for a particular purpose
// are disclaimed. In no event shall the Intel Corporation or contributors be
// liable for any direct, indirect, incidental, special, exemplary, or
// consequential damages (including, but not limited to, procurement of
// substitute goods or services; loss of use, data, or profits; or business
// interruption) however caused and on any theory of liability, whether in
// contract, strict liability, or tort (including negligence or otherwise)
// arising in any way out of the use of this software, even if advised of the
// possibility of such damage.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef OPENCV_BRIDGE_HPP_
#define OPENCV_BRIDGE_HPP_
/** @defgroup matlab MATLAB Bridge
*/
#include "mxarray.hpp"
#include <vector>
#include <string>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/geometry.hpp>
#include <opencv2/photo.hpp>
#include <opencv2/stitching.hpp>
#include <opencv2/video.hpp>
#include <opencv2/optflow.hpp>
#include <opencv2/xphoto.hpp>
/* This 'using' line was added in order to fix the following Error.
* Failed to compile currentUIFramework:
* modules/matlab/src/currentUIFramework.cpp:
* In function void mexFunction(int, mxArray**, int, const mxArray**)
* error: string was not declared in this scope
* string retval; in line 41
*
* This error happens at the last stage of opencv build, when compiling the mex bindings
* TODO: This is NOT the optimal fix, and needs to be addressed
*/
using std::string;
namespace cv {
namespace bridge {
//! @addtogroup matlab
//! @{
/*
* Custom typedefs
* Parsed names from the hdr_parser
*/
typedef std::vector<cv::Mat> vector_Mat;
typedef std::vector<cv::Point> vector_Point;
typedef std::vector<int> vector_int;
typedef std::vector<float> vector_float;
typedef std::vector<cv::String> vector_String;
typedef std::vector<unsigned char> vector_uchar;
typedef std::vector<std::vector<char> > vector_vector_char;
typedef std::vector<std::vector<cv::DMatch> > vector_vector_DMatch;
typedef std::vector<cv::Rect> vector_Rect;
typedef std::vector<cv::KeyPoint> vector_KeyPoint;
typedef cv::Ptr<cv::StereoBM> Ptr_StereoBM;
typedef cv::Ptr<cv::StereoSGBM> Ptr_StereoSGBM;
typedef cv::Ptr<cv::FeatureDetector> Ptr_FeatureDetector;
typedef cv::Ptr<CLAHE> Ptr_CLAHE;
typedef cv::Ptr<LineSegmentDetector> Ptr_LineSegmentDetector;
typedef cv::Ptr<AlignMTB> Ptr_AlignMTB;
typedef cv::Ptr<CalibrateDebevec> Ptr_CalibrateDebevec;
typedef cv::Ptr<CalibrateRobertson> Ptr_CalibrateRobertson;
typedef cv::Ptr<DenseOpticalFlow> Ptr_DenseOpticalFlow;
typedef cv::Ptr<cv::optflow::DualTVL1OpticalFlow> Ptr_DualTVL1OpticalFlow;
typedef cv::Ptr<MergeDebevec> Ptr_MergeDebevec;
typedef cv::Ptr<MergeMertens> Ptr_MergeMertens;
typedef cv::Ptr<MergeRobertson> Ptr_MergeRobertson;
typedef cv::Ptr<Stitcher> Ptr_Stitcher;
typedef cv::Ptr<Tonemap> Ptr_Tonemap;
typedef cv::Ptr<TonemapDrago> Ptr_TonemapDrago;
typedef cv::Ptr<cv::xphoto::TonemapDurand> Ptr_TonemapDurand;
typedef cv::Ptr<TonemapMantiuk> Ptr_TonemapMantiuk;
typedef cv::Ptr<TonemapReinhard> Ptr_TonemapReinhard;
typedef cv::Ptr<float> Ptr_float;
typedef cv::Ptr<cv::GeneralizedHoughBallard> Ptr_GeneralizedHoughBallard;
typedef cv::Ptr<cv::GeneralizedHoughGuil> Ptr_GeneralizedHoughGuil;
// ----------------------------------------------------------------------------
// PREDECLARATIONS
// ----------------------------------------------------------------------------
class Bridge;
typedef std::vector<Bridge> BridgeVector;
template <typename InputScalar, typename OutputScalar>
void deepCopyAndTranspose(const cv::Mat& src, matlab::MxArray& dst);
template <typename InputScalar, typename OutputScalar>
void deepCopyAndTranspose(const matlab::MxArray& src, cv::Mat& dst);
// ----------------------------------------------------------------------------
// BRIDGE
// ----------------------------------------------------------------------------
/*!
* @class Bridge
* @brief Type conversion class for converting OpenCV and native C++ types
*
* Bridge provides an interface for converting between OpenCV/C++ types
* to Matlab's mxArray format.
*
* Each type conversion requires three operators:
* // conversion from ObjectType --> Bridge
* Bridge& operator=(const ObjectType&);
* // implicit conversion from Bridge --> ObjectType
* operator ObjectType();
* // explicit conversion from Bridge --> ObjectType
* ObjectType toObjectType();
*
* The bridging class provides common conversions between OpenCV types,
* std and stl types to Matlab's mxArray format. By inheriting Bridge,
* you can add your own custom type conversions.
*
* Because Matlab uses a homogeneous storage type, all operations are provided
* relative to Matlab's type. That is, Bridge always stores an matlab::MxArray object
* and converts to and from other object types on demand.
*
* NOTE: for the explicit conversion function, the object name must be
* in UpperCamelCase, for example:
* int --> toInt
* my_object --> MyObject
* my_Object --> MyObject
* myObject --> MyObject
* this is because the binding generator standardises the calling syntax.
*
* Bridge attempts to make as few assumptions as possible, however in
* some cases where 1-to-1 mappings don't exist, some assumptions are necessary.
* In particular:
* - conversion from of a 2-channel Mat to an mxArray will result in a complex
* output
* - conversion from multi-channel interleaved Mats will result in
* multichannel planar mxArrays
*
*/
class Bridge {
private:
matlab::MxArray ptr_;
public:
// bridges are default constructible
Bridge() {}
virtual ~Bridge() {}
// --------------------------------------------------------------------------
// Bridge Properties
// --------------------------------------------------------------------------
bool empty() const { return ptr_.empty(); }
/*! @brief unpack an object from Matlab into C++
*
* this function checks whether the given bridge is derived from an
* object in Matlab. If so, it converts it to a (platform dependent)
* pointer to the underlying C++ object.
*
* NOTE! This function assumes that the C++ pointer is stored in inst_
*/
template <typename Object>
Object* getObjectByName(const std::string& name) {
// check that the object is actually of correct type before unpacking
// TODO: Traverse class hierarchy?
if (!ptr_.isClass(name)) {
matlab::error(std::string("Expected class ").append(std::string(name))
.append(" but was given ").append(ptr_.className()));
}
// get the instance field
matlab::MxArray inst = ptr_.field("inst_");
Object* obj = NULL;
// make sure the pointer is the correct size for the system
if (sizeof(void *) == 8 && inst.ID() == mxUINT64_CLASS) {
// 64-bit pointers
// TODO: Do we REALLY REALLY need to reinterpret_cast?
obj = reinterpret_cast<Object *>(inst.scalar<uint64_t>());
} else if (sizeof(void *) == 4 && inst.ID() == mxUINT32_CLASS) {
// 32-bit pointers
obj = reinterpret_cast<Object *>(inst.scalar<uint32_t>());
} else {
matlab::error("Incorrect pointer type stored for architecture");
}
// finally check if the object is NULL
matlab::conditionalError(obj, std::string("Object ").append(std::string(name)).append(std::string(" is NULL")));
return obj;
}
// --------------------------------------------------------------------------
// MATLAB TYPES
// --------------------------------------------------------------------------
Bridge& operator=(const mxArray* obj) { ptr_ = obj; return *this; }
Bridge& operator=(const matlab::MxArray& obj) { ptr_ = obj; return *this; }
Bridge(const matlab::MxArray& obj) : ptr_(obj) {}
Bridge(const mxArray* obj) : ptr_(obj) {}
matlab::MxArray toMxArray() { return ptr_; }
// --------------------------------------------------------------------------
// MATRIX CONVERSIONS
// --------------------------------------------------------------------------
Bridge& operator=(const cv::Mat& mat);
cv::Mat toMat() const;
operator cv::Mat() const { return toMat(); }
template <typename Scalar>
static matlab::MxArray FromMat(const cv::Mat& mat) {
matlab::MxArray arr(mat.rows, mat.cols, mat.channels(), matlab::Traits<Scalar>::ScalarType);
switch (mat.depth()) {
case CV_8U: deepCopyAndTranspose<uint8_t, Scalar>(mat, arr); break;
case CV_8S: deepCopyAndTranspose<int8_t, Scalar>(mat, arr); break;
case CV_16U: deepCopyAndTranspose<uint16_t, Scalar>(mat, arr); break;
case CV_16S: deepCopyAndTranspose<int16_t, Scalar>(mat, arr); break;
case CV_32S: deepCopyAndTranspose<int32_t, Scalar>(mat, arr); break;
case CV_32F: deepCopyAndTranspose<float, Scalar>(mat, arr); break;
case CV_64F: deepCopyAndTranspose<double, Scalar>(mat, arr); break;
default: matlab::error("Attempted to convert from unknown class");
}
return arr;
}
template <typename Scalar>
cv::Mat toMat() const {
cv::Mat mat(ptr_.rows(), ptr_.cols(), CV_MAKETYPE(cv::DataType<Scalar>::type, ptr_.channels()));
switch (ptr_.ID()) {
case mxINT8_CLASS: deepCopyAndTranspose<int8_t, Scalar>(ptr_, mat); break;
case mxUINT8_CLASS: deepCopyAndTranspose<uint8_t, Scalar>(ptr_, mat); break;
case mxINT16_CLASS: deepCopyAndTranspose<int16_t, Scalar>(ptr_, mat); break;
case mxUINT16_CLASS: deepCopyAndTranspose<uint16_t, Scalar>(ptr_, mat); break;
case mxINT32_CLASS: deepCopyAndTranspose<int32_t, Scalar>(ptr_, mat); break;
case mxUINT32_CLASS: deepCopyAndTranspose<uint32_t, Scalar>(ptr_, mat); break;
//case mxINT64_CLASS: deepCopyAndTranspose<int64_t, Scalar>(ptr_, mat); break;
//case mxUINT64_CLASS: deepCopyAndTranspose<uint64_t, Scalar>(ptr_, mat); break;
case mxSINGLE_CLASS: deepCopyAndTranspose<float, Scalar>(ptr_, mat); break;
case mxDOUBLE_CLASS: deepCopyAndTranspose<double, Scalar>(ptr_, mat); break;
case mxCHAR_CLASS: deepCopyAndTranspose<char, Scalar>(ptr_, mat); break;
case mxLOGICAL_CLASS: deepCopyAndTranspose<int8_t, Scalar>(ptr_, mat); break;
default: matlab::error("Attempted to convert from unknown/unsupported class");
}
return mat;
}
// --------------------------------------------------------------------------
// INTEGRAL TYPES
// --------------------------------------------------------------------------
// --------------------------- string --------------------------------------
Bridge& operator=(const std::string& ) { return *this; }
std::string toString() {
return ptr_.toString();
}
operator std::string() { return toString(); }
// --------------------------- bool --------------------------------------
Bridge& operator=(const bool& ) { return *this; }
bool toBool() { return 0; }
operator bool() { return toBool(); }
// --------------------------- double --------------------------------------
Bridge& operator=(const double& ) { return *this; }
double toDouble() { return ptr_.scalar<double>(); }
operator double() { return toDouble(); }
// --------------------------- float ---------------------------------------
Bridge& operator=(const float& ) { return *this; }
float toFloat() { return ptr_.scalar<float>(); }
operator float() { return toFloat(); }
// --------------------------- int --------------------------------------
Bridge& operator=(const int& ) { return *this; }
int toInt() { return ptr_.scalar<int>(); }
operator int() { return toInt(); }
// --------------------------- size_t -----------------------------------------
Bridge& operator=(const size_t&) { return *this; }
size_t toSizeT() { return ptr_.scalar<size_t>(); }
operator size_t() { return toSizeT(); }
// --------------------------------------------------------------------------
// CORE OPENCV TYPES
// --------------------------------------------------------------------------
// -------------------------- Point --------------------------------------
Bridge& operator=(const cv::Point& ) { return *this; }
cv::Point toPoint() const { return cv::Point(); }
operator cv::Point() const { return toPoint(); }
// -------------------------- Point2f ------------------------------------
Bridge& operator=(const cv::Point2f& ) { return *this; }
cv::Point2f toPoint2f() const { return cv::Point2f(); }
operator cv::Point2f() const { return toPoint2f(); }
// -------------------------- Point2d ------------------------------------
Bridge& operator=(const cv::Point2d& ) { return *this; }
cv::Point2d toPoint2d() const { return cv::Point2d(); }
operator cv::Point2d() const { return toPoint2d(); }
// -------------------------- Size ---------------------------------------
Bridge& operator=(const cv::Size& ) { return *this; }
cv::Size toSize() const { return cv::Size(); }
operator cv::Size() const { return toSize(); }
// -------------------------- Moments --------------------------------------
Bridge& operator=(const cv::Moments& ) { return *this; }
cv::Moments toMoments() const { return cv::Moments(); }
operator cv::Moments() const { return toMoments(); }
// -------------------------- Scalar --------------------------------------
Bridge& operator=(const cv::Scalar& ) { return *this; }
cv::Scalar toScalar() { return cv::Scalar(); }
operator cv::Scalar() { return toScalar(); }
// -------------------------- Rect -----------------------------------------
Bridge& operator=(const cv::Rect& ) { return *this; }
cv::Rect toRect() { return cv::Rect(); }
operator cv::Rect() { return toRect(); }
// ---------------------- RotatedRect ---------------------------------------
Bridge& operator=(const cv::RotatedRect& ) { return *this; }
cv::RotatedRect toRotatedRect() { return cv::RotatedRect(); }
operator cv::RotatedRect() { return toRotatedRect(); }
// ---------------------- TermCriteria --------------------------------------
Bridge& operator=(const cv::TermCriteria& ) { return *this; }
cv::TermCriteria toTermCriteria() { return cv::TermCriteria(); }
operator cv::TermCriteria() { return toTermCriteria(); }
// ---------------------- RNG --------------------------------------
Bridge& operator=(const cv::RNG& ) { return *this; }
/*! @brief explicit conversion to cv::RNG()
*
* Converts a bridge object to a cv::RNG(). We explicitly assert that
* the object is an RNG in matlab space before attempting to deference
* its pointer
*/
cv::RNG toRNG() {
return (*getObjectByName<cv::RNG>("RNG"));
}
operator cv::RNG() { return toRNG(); }
// --------------------------------------------------------------------------
// OPENCV VECTOR TYPES
// --------------------------------------------------------------------------
// -------------------- vector_Mat ------------------------------------------
Bridge& operator=(const vector_Mat& ) { return *this; }
vector_Mat toVectorMat() { return vector_Mat(); }
operator vector_Mat() { return toVectorMat(); }
// --------------------------- vector_int ----------------------------------
Bridge& operator=(const vector_int& ) { return *this; }
vector_int toVectorInt() { return vector_int(); }
operator vector_int() { return toVectorInt(); }
// --------------------------- vector_float --------------------------------
Bridge& operator=(const vector_float& ) { return *this; }
vector_float toVectorFloat() { return vector_float(); }
operator vector_float() { return toVectorFloat(); }
// --------------------------- vector_Rect ---------------------------------
Bridge& operator=(const vector_Rect& ) { return *this; }
vector_Rect toVectorRect() { return vector_Rect(); }
operator vector_Rect() { return toVectorRect(); }
// --------------------------- vector_KeyPoint -----------------------------
Bridge& operator=(const vector_KeyPoint& ) { return *this; }
vector_KeyPoint toVectorKeyPoint() { return vector_KeyPoint(); }
operator vector_KeyPoint() { return toVectorKeyPoint(); }
// --------------------------- vector_String -------------------------------
Bridge& operator=(const vector_String& ) { return *this; }
vector_String toVectorString() { return vector_String(); }
operator vector_String() { return toVectorString(); }
// ------------------------ vector_Point ------------------------------------
Bridge& operator=(const vector_Point& ) { return *this; }
vector_Point toVectorPoint() { return vector_Point(); }
operator vector_Point() { return toVectorPoint(); }
// ------------------------ vector_uchar ------------------------------------
Bridge& operator=(const vector_uchar& ) { return *this; }
vector_uchar toVectorUchar() { return vector_uchar(); }
operator vector_uchar() { return toVectorUchar(); }
// ------------------------ vector_vector_char ------------------------------
Bridge& operator=(const vector_vector_char& ) { return *this; }
vector_vector_char toVectorVectorChar() { return vector_vector_char(); }
operator vector_vector_char() { return toVectorVectorChar(); }
// ------------------------ vector_vector_DMatch ---------------------------
Bridge& operator=(const vector_vector_DMatch& ) { return *this; }
vector_vector_DMatch toVectorVectorDMatch() { return vector_vector_DMatch(); }
operator vector_vector_DMatch() { return toVectorVectorDMatch(); }
// --------------------------------------------------------------------------
// OPENCV COMPOUND TYPES
// --------------------------------------------------------------------------
// --------------------------- Ptr_StereoBM -----------------------------
Bridge& operator=(const Ptr_StereoBM& ) { return *this; }
Ptr_StereoBM toPtrStereoBM() { return Ptr_StereoBM(); }
operator Ptr_StereoBM() { return toPtrStereoBM(); }
// --------------------------- Ptr_StereoSGBM ---------------------------
Bridge& operator=(const Ptr_StereoSGBM& ) { return *this; }
Ptr_StereoSGBM toPtrStereoSGBM() { return Ptr_StereoSGBM(); }
operator Ptr_StereoSGBM() { return toPtrStereoSGBM(); }
// --------------------------- Ptr_FeatureDetector ----------------------
Bridge& operator=(const Ptr_FeatureDetector& ) { return *this; }
Ptr_FeatureDetector toPtrFeatureDetector() { return Ptr_FeatureDetector(); }
operator Ptr_FeatureDetector() { return toPtrFeatureDetector(); }
// --------------------------- Ptr_CLAHE --------------------------------
Bridge& operator=(const Ptr_CLAHE& ) { return *this; }
Ptr_CLAHE toPtrCLAHE() { return Ptr_CLAHE(); }
operator Ptr_CLAHE() { return toPtrCLAHE(); }
// --------------------------- Ptr_LineSegmentDetector ------------------
Bridge& operator=(const Ptr_LineSegmentDetector& ) { return *this; }
Ptr_LineSegmentDetector toPtrLineSegmentDetector() { return Ptr_LineSegmentDetector(); }
operator Ptr_LineSegmentDetector() { return toPtrLineSegmentDetector(); }
// --------------------------- Ptr_AlignMTB -----------------------------
Bridge& operator=(const Ptr_AlignMTB& ) { return *this; }
Ptr_AlignMTB toPtrAlignMTB() { return Ptr_AlignMTB(); }
operator Ptr_AlignMTB() { return toPtrAlignMTB(); }
// --------------------------- Ptr_CalibrateDebevec -------------------
Bridge& operator=(const Ptr_CalibrateDebevec& ) { return *this; }
Ptr_CalibrateDebevec toPtrCalibrateDebevec() { return Ptr_CalibrateDebevec(); }
operator Ptr_CalibrateDebevec() { return toPtrCalibrateDebevec(); }
// --------------------------- Ptr_CalibrateRobertson -------------------
Bridge& operator=(const Ptr_CalibrateRobertson& ) { return *this; }
Ptr_CalibrateRobertson toPtrCalibrateRobertson() { return Ptr_CalibrateRobertson(); }
operator Ptr_CalibrateRobertson() { return toPtrCalibrateRobertson(); }
// --------------------------- Ptr_DenseOpticalFlow -------------------
Bridge& operator=(const Ptr_DenseOpticalFlow& ) { return *this; }
Ptr_DenseOpticalFlow toPtrDenseOpticalFlow() { return Ptr_DenseOpticalFlow(); }
operator Ptr_DenseOpticalFlow() { return toPtrDenseOpticalFlow(); }
// --------------------------- Ptr_DualTVL1OpticalFlow -------------------
Bridge& operator=(const Ptr_DualTVL1OpticalFlow& ) { return *this; }
Ptr_DualTVL1OpticalFlow toPtrDualTVL1OpticalFlow() { return Ptr_DualTVL1OpticalFlow(); }
operator Ptr_DualTVL1OpticalFlow() { return toPtrDualTVL1OpticalFlow(); }
// --------------------------- Ptr_MergeDebevec -----------------------
Bridge& operator=(const Ptr_MergeDebevec& ) { return *this; }
Ptr_MergeDebevec toPtrMergeDebevec() { return Ptr_MergeDebevec(); }
operator Ptr_MergeDebevec() { return toPtrMergeDebevec(); }
// --------------------------- Ptr_MergeMertens -----------------------
Bridge& operator=(const Ptr_MergeMertens& ) { return *this; }
Ptr_MergeMertens toPtrMergeMertens() { return Ptr_MergeMertens(); }
operator Ptr_MergeMertens() { return toPtrMergeMertens(); }
// --------------------------- Ptr_MergeRobertson -----------------------
Bridge& operator=(const Ptr_MergeRobertson& ) { return *this; }
Ptr_MergeRobertson toPtrMergeRobertson() { return Ptr_MergeRobertson(); }
operator Ptr_MergeRobertson() { return toPtrMergeRobertson(); }
// --------------------------- Ptr_Stitcher ------------------------------
Bridge& operator=(const Ptr_Stitcher& ) { return *this; }
Ptr_Stitcher toPtrStitcher() { return Ptr_Stitcher(); }
operator Ptr_Stitcher() { return toPtrStitcher(); }
// --------------------------- Ptr_Tonemap ------------------------------
Bridge& operator=(const Ptr_Tonemap& ) { return *this; }
Ptr_Tonemap toPtrTonemap() { return Ptr_Tonemap(); }
operator Ptr_Tonemap() { return toPtrTonemap(); }
// --------------------------- Ptr_TonemapDrago -------------------------
Bridge& operator=(const Ptr_TonemapDrago& ) { return *this; }
Ptr_TonemapDrago toPtrTonemapDrago() { return Ptr_TonemapDrago(); }
operator Ptr_TonemapDrago() { return toPtrTonemapDrago(); }
// --------------------------- Ptr_TonemapDurand ------------------------
Bridge& operator=(const Ptr_TonemapDurand& ) { return *this; }
Ptr_TonemapDurand toPtrTonemapDurand() { return Ptr_TonemapDurand(); }
operator Ptr_TonemapDurand() { return toPtrTonemapDurand(); }
// --------------------------- Ptr_TonemapMantiuk -----------------------
Bridge& operator=(const Ptr_TonemapMantiuk& ) { return *this; }
Ptr_TonemapMantiuk toPtrTonemapMantiuk() { return Ptr_TonemapMantiuk(); }
operator Ptr_TonemapMantiuk() { return toPtrTonemapMantiuk(); }
// --------------------------- Ptr_TonemapReinhard ----------------------
Bridge& operator=(const Ptr_TonemapReinhard& ) { return *this; }
Ptr_TonemapReinhard toPtrTonemapReinhard() { return Ptr_TonemapReinhard(); }
operator Ptr_TonemapReinhard() { return toPtrTonemapReinhard(); }
// --------------------------- Ptr_float ----------------------
Bridge& operator=(const Ptr_float& ) { return *this; }
Ptr_float toPtrFloat() { return Ptr_float(); }
operator Ptr_float() { return toPtrFloat(); }
// --------------------------- Ptr_GeneralizedHoughBallard --------------
Bridge& operator=(const Ptr_GeneralizedHoughBallard& obj) { return *this; }
operator Ptr_GeneralizedHoughBallard() { return Ptr_GeneralizedHoughBallard(); }
// --------------------------- Ptr_GeneralizedHoughGuil ----------------------
Bridge& operator=(const Ptr_GeneralizedHoughGuil& obj) { return *this; }
operator Ptr_GeneralizedHoughGuil() { return Ptr_GeneralizedHoughGuil(); }
}; // class Bridge
// --------------------------------------------------------------------------
// SPECIALIZATIONS
// --------------------------------------------------------------------------
/*!
* @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 <>
matlab::MxArray Bridge::FromMat<matlab::InheritType>(const cv::Mat& mat) {
switch (mat.depth()) {
case CV_8U: return FromMat<uint8_t>(mat);
case CV_8S: return FromMat<int8_t>(mat);
case CV_16U: return FromMat<uint16_t>(mat);
case CV_16S: return FromMat<int16_t>(mat);
case CV_32S: return FromMat<int32_t>(mat);
case CV_32F: return FromMat<double>(mat); //NOTE: Matlab uses double as native type!
case CV_64F: return FromMat<double>(mat);
default: matlab::error("Attempted to convert from unknown class");
}
return matlab::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<matlab::InheritType>() const {
switch (ptr_.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: matlab::error("Attempted to convert from unknown/unsuported class");
}
return cv::Mat();
}
Bridge& Bridge::operator=(const cv::Mat& mat) { ptr_ = FromMat<matlab::InheritType>(mat); return *this; }
cv::Mat Bridge::toMat() const { return toMat<matlab::InheritType>(); }
// ----------------------------------------------------------------------------
// MATRIX TRANSPOSE
// ----------------------------------------------------------------------------
template <typename InputScalar, typename OutputScalar>
void deepCopyAndTranspose(const cv::Mat& in, matlab::MxArray& out) {
const int cols = out.cols();
const int rows = out.rows();
matlab::conditionalError(static_cast<size_t>(in.rows) == out.rows(), "Matrices must have the same number of rows");
matlab::conditionalError(static_cast<size_t>(in.cols) == out.cols(), "Matrices must have the same number of cols");
matlab::conditionalError(static_cast<size_t>(in.channels()) == out.channels(), "Matrices must have the same number of channels");
std::vector<cv::Mat> channels;
cv::split(in, channels);
for (size_t c = 0; c < out.channels(); ++c) {
cv::Mat_<InputScalar> m;
cv::transpose(channels[c], m);
OutputScalar* dst_plane = (OutputScalar*)out.real<InputScalar>() + cols*rows*c;
for (int x = 0; x < cols; x++)
{
OutputScalar* dst_col = dst_plane + x * rows;
for (int y = 0; y < rows; y++)
{
dst_col[y] = cv::saturate_cast<OutputScalar>(m(y, x));
}
}
}
//const InputScalar* inp = in.ptr<InputScalar>(0);
//OutputScalar* outp = out.real<OutputScalar>();
//gemt('R', out.rows(), out.cols(), inp, in.step1(), outp, out.rows());
}
template <typename InputScalar, typename OutputScalar>
void deepCopyAndTranspose(const matlab::MxArray& in, cv::Mat& out) {
const int cols = in.cols();
const int rows = in.rows();
matlab::conditionalError(in.rows() == static_cast<size_t>(out.rows), "Matrices must have the same number of rows");
matlab::conditionalError(in.cols() == static_cast<size_t>(out.cols), "Matrices must have the same number of cols");
matlab::conditionalError(in.channels() == static_cast<size_t>(out.channels()), "Matrices must have the same number of channels");
std::vector<cv::Mat> channels;
for (size_t c = 0; c < in.channels(); ++c) {
cv::Mat_<OutputScalar> m(cols, rows);
const InputScalar* src_plane = in.real<InputScalar>() + cols*rows*c;
for (int x = 0; x < cols; x++)
{
const InputScalar* src_col = src_plane + x * rows;
for (int y = 0; y < rows; y++)
{
m(y, x) = cv::saturate_cast<InputScalar>(src_col[y]);
}
}
cv::transpose(m, m);
channels.push_back(m);
}
cv::merge(channels, out);
//const InputScalar* inp = in.real<InputScalar>();
//OutputScalar* outp = out.ptr<OutputScalar>(0);
//gemt('C', in.rows(), in.cols(), inp, in.rows(), outp, out.step1());
}
//! @}
} // namespace bridge
} // namespace cv
#endif
@@ -0,0 +1,99 @@
////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this
// license. If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote
// products derived from this software without specific prior written
// permission.
//
// This software is provided by the copyright holders and contributors "as is"
// and any express or implied warranties, including, but not limited to, the
// implied warranties of merchantability and fitness for a particular purpose
// are disclaimed. In no event shall the Intel Corporation or contributors be
// liable for any direct, indirect, incidental, special, exemplary, or
// consequential damages (including, but not limited to, procurement of
// substitute goods or services; loss of use, data, or profits; or business
// interruption) however caused and on any theory of liability, whether in
// contract, strict liability, or tort (including negligence or otherwise)
// arising in any way out of the use of this software, even if advised of the
// possibility of such damage.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef OPENCV_MAP_HPP_
#define OPENCV_MAP_HPP_
namespace matlab {
#if __cplusplus >= 201103L
// If we have C++11 support, we just want to use unordered_map
#include <unordered_map>
template <typename KeyType, typename ValueType>
using Map = std::unordered_map<KeyType, ValueType>;
#else
//! @addtogroup matlab
//! @{
// If we don't have C++11 support, we wrap another map implementation
// in the same public API as unordered_map
//! @cond IGNORED
#include <map>
#include <stdexcept>
//! @endcond
template <typename KeyType, typename ValueType>
class Map {
private:
std::map<KeyType, ValueType> map_;
public:
// map[key] = val;
ValueType& operator[] (const KeyType& k) {
return map_[k];
}
// map.at(key) = val (throws)
ValueType& at(const KeyType& k) {
typename std::map<KeyType, ValueType>::iterator it;
it = map_.find(k);
if (it == map_.end()) throw std::out_of_range("Key not found");
return *it;
}
// val = map.at(key) (throws, const)
const ValueType& at(const KeyType& k) const {
typename std::map<KeyType, ValueType>::const_iterator it;
it = map_.find(k);
if (it == map_.end()) throw std::out_of_range("Key not found");
return *it;
}
};
//! @}
} // namespace matlab
#endif
#endif
@@ -0,0 +1,690 @@
////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this
// license. If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote
// products derived from this software without specific prior written
// permission.
//
// This software is provided by the copyright holders and contributors "as is"
// and any express or implied warranties, including, but not limited to, the
// implied warranties of merchantability and fitness for a particular purpose
// are disclaimed. In no event shall the Intel Corporation or contributors be
// liable for any direct, indirect, incidental, special, exemplary, or
// consequential damages (including, but not limited to, procurement of
// substitute goods or services; loss of use, data, or profits; or business
// interruption) however caused and on any theory of liability, whether in
// contract, strict liability, or tort (including negligence or otherwise)
// arising in any way out of the use of this software, even if advised of the
// possibility of such damage.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef OPENCV_MXARRAY_HPP_
#define OPENCV_MXARRAY_HPP_
#include <mex.h>
#include <stdint.h>
#include <cstdarg>
#include <algorithm>
#include <string>
#include <vector>
#include <sstream>
#if __cplusplus > 201103
#include <unordered_set>
typedef std::unordered_set<std::string> StringSet;
#else
#include <set>
typedef std::set<std::string> StringSet;
#endif
/*
* All recent versions of Matlab ship with the MKL library which contains
* a blas extension called mkl_?omatcopy(). This defines an out-of-place
* copy and transpose operation.
*
* The mkl library is in ${MATLAB_ROOT}/bin/${MATLAB_MEXEXT}/libmkl...
* Matlab does not ship headers for the mkl functions, so we define them
* here.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
namespace matlab {
//! @addtogroup matlab
//! @{
// ----------------------------------------------------------------------------
// PREDECLARATIONS
// ----------------------------------------------------------------------------
class MxArray;
typedef std::vector<MxArray> MxArrayVector;
/*!
* @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
*/
static 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
*/
static void error(const std::string& str) {
mexErrMsgTxt(str.c_str());
}
// ----------------------------------------------------------------------------
// MATLAB TRAITS
// ----------------------------------------------------------------------------
class DefaultTraits {};
class InheritType {};
template<typename _Tp = DefaultTraits> class Traits {
public:
static const mxClassID ScalarType = mxUNKNOWN_CLASS;
static const mxComplexity Complex = mxCOMPLEX;
static const mxComplexity Real = mxREAL;
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"; }
};
// char
template<> class Traits<char> {
public:
static const mxClassID ScalarType = mxCHAR_CLASS;
static std::string ToString() { return "char"; }
};
// inherited type
template<> class Traits<matlab::InheritType> {
public:
static std::string ToString() { return "Inherited type"; }
};
// ----------------------------------------------------------------------------
// MXARRAY
// ----------------------------------------------------------------------------
/*!
* @class MxArray
* @brief A thin wrapper around Matlab's mxArray types
*
* 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. 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
*
* MxArrays can be directly converted into OpenCV mat objects and std::string
* objects, since there is a natural mapping between these types. More
* complex types are mapped through the Bridge which does custom conversions
* such as MxArray --> cv::Keypoints, etc
*/
class MxArray {
private:
mxArray* ptr_;
bool owns_;
/*!
* @brief swap all members of this and other
*
* the swap method is used by the assignment and move constructors
* to swap the members of two MxArrays, leaving both in destructible states
*/
friend void swap(MxArray& first, MxArray& second) {
using std::swap;
swap(first.ptr_, second.ptr_);
swap(first.owns_, second.owns_);
}
void dealloc() {
if (owns_ && ptr_) { mxDestroyArray(ptr_); ptr_ = NULL; owns_ = false; }
}
public:
// --------------------------------------------------------------------------
// CONSTRUCTORS
// --------------------------------------------------------------------------
/*!
* @brief default constructor
*
* Construct a valid 0x0 matrix (so all other methods do not need validity checks)
*/
MxArray() : ptr_(mxCreateDoubleMatrix(0, 0, matlab::Traits<>::Real)), owns_(true) {}
/*!
* @brief destructor
*
* The destructor deallocates any data allocated by mxCreate* methods only
* if the object is owned
*/
virtual ~MxArray() {
dealloc();
}
/*!
* @brief inheriting constructor
*
* Inherit an mxArray from Matlab. Don't claim ownership of the array,
* just encapsulate it
*/
MxArray(const mxArray* ptr) : ptr_(const_cast<mxArray *>(ptr)), owns_(false) {}
MxArray& operator=(const mxArray* ptr) {
dealloc();
ptr_ = const_cast<mxArray *>(ptr);
owns_ = false;
return *this;
}
/*!
* @brief explicit typed constructor
*
* This constructor explicitly creates an MxArray of the given size and type.
*/
MxArray(size_t m, size_t n, size_t k, mxClassID id, mxComplexity com = matlab::Traits<>::Real)
: ptr_(NULL), owns_(true) {
mwSize dims[] = { static_cast<mwSize>(m), static_cast<mwSize>(n), static_cast<mwSize>(k) };
ptr_ = mxCreateNumericArray(3, dims, id, com);
}
/*!
* @brief explicit tensor constructor
*
* Explicitly construct a tensor of given size and type. Since constructors cannot
* be explicitly templated, this is a static factory method
*/
template <typename Scalar>
static MxArray Tensor(size_t m, size_t n, size_t k=1) {
return MxArray(m, n, k, matlab::Traits<Scalar>::ScalarType);
}
/*!
* @brief explicit matrix constructor
*
* Explicitly construct a matrix of given size and type. Since constructors cannot
* be explicitly templated, this is a static factory method
*/
template <typename Scalar>
static MxArray Matrix(size_t m, size_t n) {
return MxArray(m, n, 1, matlab::Traits<Scalar>::ScalarType);
}
/*!
* @brief explicit vector constructor
*
* Explicitly construct a vector of given size and type. Since constructors cannot
* be explicitly templated, this is a static factory method
*/
template <typename Scalar>
static MxArray Vector(size_t m) {
return MxArray(m, 1, 1, matlab::Traits<Scalar>::ScalarType);
}
/*!
* @brief explicit scalar constructor
*
* Explicitly construct a scalar of given type. Since constructors cannot
* be explicitly templated, this is a static factory method
*/
template <typename ScalarType>
static MxArray Scalar(ScalarType value = 0) {
MxArray s(1, 1, 1, matlab::Traits<ScalarType>::ScalarType);
s.real<ScalarType>()[0] = value;
return s;
}
/*!
* @brief copy constructor
*
* All copies are deep copies. If you have a C++11 compatible compiler, prefer
* move construction to copy construction
*/
MxArray(const MxArray& other) : ptr_(mxDuplicateArray(other.ptr_)), owns_(true) {}
/*!
* @brief copy-and-swap assignment
*
* This assignment operator uses the copy and swap idiom to provide a strong
* exception guarantee when swapping two objects.
*
* Note in particular that the other MxArray is passed by value, thus invoking
* the copy constructor which performs a deep copy of the input. The members of
* this and other are then swapped
*/
MxArray& operator=(MxArray other) {
swap(*this, other);
return *this;
}
#if __cplusplus >= 201103L
/*
* @brief C++11 move constructor
*
* When C++11 support is available, move construction is used to move returns
* out of functions, etc. This is much fast than copy construction, since the
* move constructed object replaced itself with a default constructed MxArray,
* which is of size 0 x 0.
*/
MxArray(MxArray&& other) : MxArray() {
swap(*this, other);
}
#endif
/*
* @brief release ownership to allow return into Matlab workspace
*
* MxArray is not directly convertible back to mxArray types through assignment
* because the MxArray may have been allocated on the free store, making it impossible
* to know whether the returned pointer will be released by someone else or not.
*
* Since Matlab requires mxArrays be passed back into the workspace, the only way
* to achieve that is through this function, which explicitly releases ownership
* of the object, assuming the Matlab interpreter receving the object will delete
* it at a later time
*
* e.g.
* {
* MxArray A = MxArray::Matrix<double>(5, 5); // allocates memory
* MxArray B = MxArray::Matrix<double>(5, 5); // ditto
* plhs[0] = A; // not allowed!!
* plhs[0] = A.releaseOwnership(); // makes explicit that ownership is being released
* } // end of scope. B is released, A isn't
*
*/
mxArray* releaseOwnership() {
owns_ = false;
return ptr_;
}
MxArray field(const std::string& name) { return MxArray(mxGetField(ptr_, 0, name.c_str())); }
template <typename Scalar>
Scalar* real() { return static_cast<Scalar *>(mxGetData(ptr_)); }
template <typename Scalar>
Scalar* imag() { return static_cast<Scalar *>(mxGetImagData(ptr_)); }
template <typename Scalar>
const Scalar* real() const { return static_cast<const Scalar *>(mxGetData(ptr_)); }
template <typename Scalar>
const Scalar* imag() const { return static_cast<const Scalar *>(mxGetData(ptr_)); }
template <typename Scalar>
Scalar scalar() const { return static_cast<Scalar *>(mxGetData(ptr_))[0]; }
std::string toString() const {
conditionalError(isString(), "Attempted to convert non-string type to string");
std::string str(size(), '\0');
mxGetString(ptr_, const_cast<char *>(str.data()), str.size()+1);
return str;
}
size_t size() const { return mxGetNumberOfElements(ptr_); }
bool empty() const { return size() == 0; }
size_t rows() const { return mxGetDimensions(ptr_)[0]; }
size_t cols() const { return mxGetDimensions(ptr_)[1]; }
size_t channels() const { return (mxGetNumberOfDimensions(ptr_) > 2) ? mxGetDimensions(ptr_)[2] : 1; }
bool isComplex() const { return mxIsComplex(ptr_); }
bool isNumeric() const { return mxIsNumeric(ptr_); }
bool isLogical() const { return mxIsLogical(ptr_); }
bool isString() const { return mxIsChar(ptr_); }
bool isCell() const { return mxIsCell(ptr_); }
bool isStructure() const { return mxIsStruct(ptr_); }
bool isClass(const std::string& name) const { return mxIsClass(ptr_, name.c_str()); }
std::string className() const { return std::string(mxGetClassName(ptr_)); }
mxClassID ID() const { return mxGetClassID(ptr_); }
};
// ----------------------------------------------------------------------------
// ARGUMENT PARSER
// ----------------------------------------------------------------------------
/*! @class ArgumentParser
* @brief parses inputs to a method and resolves the argument names.
*
* The ArgumentParser resolves the inputs to a method. It checks that all
* required arguments are specified and also allows named optional arguments.
* For example, the C++ function:
* void randn(Mat& mat, Mat& mean=Mat(), Mat& std=Mat());
* could be called in Matlab using any of the following signatures:
* \code
* out = randn(in);
* out = randn(in, 0, 1);
* out = randn(in, 'mean', 0, 'std', 1);
* \endcode
*
* ArgumentParser also enables function overloading by allowing users
* to add variants to a method. For example, there may be two C++ sum() methods:
* \code
* double sum(Mat& mat); % sum elements of a matrix
* Mat sum(Mat& A, Mat& B); % add two matrices
* \endcode
*
* by adding two variants to ArgumentParser, the correct underlying sum
* method can be called. If the function call is ambiguous, the
* ArgumentParser will fail with an error message.
*
* The previous example could be parsed as:
* \code
* // set up the Argument parser
* ArgumentParser arguments;
* arguments.addVariant("elementwise", 1);
* arguments.addVariant("matrix", 2);
*
* // parse the arguments
* std::vector<MxArray> inputs;
* inputs = arguments.parse(std::vector<MxArray>(prhs, prhs+nrhs));
*
* // if we get here, one unique variant is valid
* if (arguments.variantIs("elementwise")) {
* // call elementwise sum()
* }
* \endcode
*/
class ArgumentParser {
private:
struct Variant;
typedef std::string String;
typedef std::vector<std::string> StringVector;
typedef std::vector<size_t> IndexVector;
typedef std::vector<Variant> VariantVector;
/* @class Variant
* @brief Describes a variant of arguments to a method
*
* When addVariant() is called on an instance to ArgumentParser, this class
* holds the the information that decribes that variant. The parse() method
* of ArgumentParser then attempts to match a Variant, given a set of
* inputs for a method invocation.
*/
class Variant {
private:
String name_;
size_t Nreq_;
size_t Nopt_;
StringVector keys_;
IndexVector order_;
bool valid_;
size_t nparsed_;
size_t nkeys_;
size_t working_opt_;
bool expecting_val_;
bool using_named_;
size_t find(const String& key) const {
return std::find(keys_.begin(), keys_.end(), key) - keys_.begin();
}
public:
/*! @brief default constructor */
Variant() : Nreq_(0), Nopt_(0), valid_(false) {}
/*! @brief construct a new variant spec */
Variant(const String& name, size_t Nreq, size_t Nopt, const StringVector& keys)
: 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? */
bool fulfilled() const { return (valid_ && nparsed_ >= Nreq_ && !expecting_val_); }
/*! @brief is the variant in a valid state (though not necessarily fulfilled) */
bool valid() const { return valid_; }
/*! @brief check if the named argument exists in the variant */
bool exist(const String& key) const { return find(key) != keys_.size(); }
/*! @brief retrieve the order mapping raw inputs to their position in the variant */
const IndexVector& order() const { return order_; }
size_t order(size_t n) const { return order_[n]; }
/*! @brief attempt to parse the next argument as a value */
bool parseNextAsValue() {
if (!valid_) {}
else if ((using_named_ && !expecting_val_) || (nparsed_-nkeys_ == Nreq_+Nopt_)) { valid_ = false; }
else if (nparsed_ < Nreq_) { order_[nparsed_] = nparsed_; }
else if (!using_named_) { order_[nparsed_] = nparsed_; }
else if (using_named_ && expecting_val_) { order_[Nreq_ + working_opt_] = nparsed_; }
nparsed_++;
expecting_val_ = false;
return valid_;
}
/*! @biref attempt to parse the next argument as a name (key) */
bool parseNextAsKey(const String& key) {
if (!valid_) {}
else if ((nparsed_ < Nreq_) || (nparsed_-nkeys_ == Nreq_+Nopt_)) { valid_ = false; }
else if (using_named_ && expecting_val_) { valid_ = false; }
else if ((working_opt_ = find(key)) == keys_.size()) { valid_ = false; }
else { using_named_ = true; expecting_val_ = true; nkeys_++; nparsed_++; }
return valid_;
}
String toString(const String& method_name="f") const {
int req_begin = 0, req_end = 0, opt_begin = 0, opt_end = 0;
std::ostringstream s;
// f(...)
s << method_name << "(";
// required arguments
req_begin = s.str().size();
for (size_t n = 0; n < Nreq_; ++n) { s << "src" << n+1 << (n != Nreq_-1 ? ", " : ""); }
req_end = s.str().size();
if (Nreq_ && Nopt_) s << ", ";
// optional arguments
opt_begin = s.str().size();
for (size_t n = 0; n < keys_.size(); ++n) { s << "'" << keys_[n] << "', " << keys_[n] << (n != Nopt_-1 ? ", " : ""); }
opt_end = s.str().size();
s << ");";
if (Nreq_ + Nopt_ == 0) return s.str();
// underscores
String under = String(req_begin, ' ') + String(req_end-req_begin, '-')
+ String(std::max(opt_begin-req_end,0), ' ') + String(opt_end-opt_begin, '-');
s << "\n" << under;
// required and optional sets
String req_set(req_end-req_begin, ' ');
String opt_set(opt_end-opt_begin, ' ');
if (!req_set.empty() && req_set.size() < 8) req_set.replace((req_set.size()-3)/2, 3, "req");
if (req_set.size() > 7) req_set.replace((req_set.size()-8)/2, 8, "required");
if (!opt_set.empty() && opt_set.size() < 8) opt_set.replace((opt_set.size()-3)/2, 3, "opt");
if (opt_set.size() > 7) opt_set.replace((opt_set.size()-8)/2, 8, "optional");
String set = String(req_begin, ' ') + req_set + String(std::max(opt_begin-req_end,0), ' ') + opt_set;
s << "\n" << set;
return s.str();
}
};
/*! @brief given an input and output vector of arguments, and a variant spec, sort */
void sortArguments(Variant& v, MxArrayVector& in, MxArrayVector& out) {
// allocate the output array with ALL arguments
out.resize(v.size());
// 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]);
}
}
VariantVector variants_;
String valid_;
String method_name_;
public:
ArgumentParser(const String& method_name) : method_name_(method_name) {}
/*! @brief add a function call variant to the parser
*
* Adds a function-call signature to the parser. The function call *must* be
* unique either in its number of arguments, or in the named-syntax.
* Currently this function does not check whether that invariant stands true.
*
* This function is variadic. If should be called as follows:
* addVariant(2, 2, 'opt_1_name', 'opt_2_name');
*/
void addVariant(const String& name, size_t nreq, size_t nopt = 0, ...) {
StringVector keys;
va_list opt;
va_start(opt, nopt);
for (size_t n = 0; n < nopt; ++n) keys.push_back(va_arg(opt, const char*));
addVariant(name, nreq, nopt, keys);
}
void addVariant(const String& name, size_t nreq, size_t nopt, StringVector keys) {
variants_.push_back(Variant(name, nreq, nopt, keys));
}
/*! @brief check if the valid variant is the key name */
bool variantIs(const String& name) {
return name.compare(valid_) == 0;
}
/*! @brief parse a vector of input arguments
*
* This method parses a vector of input arguments, attempting to match them
* to a Variant spec. For each input, the method attempts to cull any
* Variants which don't match the given inputs so far.
*
* Once all inputs have been parsed, if there is one unique spec remaining,
* the output MxArray vector gets populated with the arguments, with named
* arguments removed. Any optional arguments that have not been encountered
* are set to an empty array.
*
* If multiple variants or no variants match the given call, an error
* message is emitted
*/
MxArrayVector parse(const MxArrayVector& inputs) {
// allocate the outputs
String variant_string;
MxArrayVector outputs;
VariantVector candidates = variants_;
// iterate over the inputs, attempting to match a variant
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) {
candidate->exist(name) ? candidate->parseNextAsKey(name) : candidate->parseNextAsValue();
}
}
// 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 there is not a unique candidate, throw an error
for (VariantVector::iterator variant = variants_.begin(); variant != variants_.end(); ++variant) {
variant_string += "\n" + variant->toString(method_name_);
}
// if there is not a unique candidate, throw an error
if (candidates.size() > 1) {
error(String("Call to method is ambiguous. Valid variants are:")
.append(variant_string).append("\nUse named arguments to disambiguate call"));
}
if (candidates.size() == 0) {
error(String("No matching method signatures for given arguments. Valid variants are:").append(variant_string));
}
// Unique candidate!
valid_ = candidates[0].name();
sortArguments(candidates[0], const_cast<MxArrayVector&>(inputs), outputs);
return outputs;
}
};
//! @}
} // namespace matlab
#endif
@@ -0,0 +1,147 @@
////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this
// license. If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote
// products derived from this software without specific prior written
// permission.
//
// This software is provided by the copyright holders and contributors "as is"
// and any express or implied warranties, including, but not limited to, the
// implied warranties of merchantability and fitness for a particular purpose
// are disclaimed. In no event shall the Intel Corporation or contributors be
// liable for any direct, indirect, incidental, special, exemplary, or
// consequential damages (including, but not limited to, procurement of
// substitute goods or services; loss of use, data, or profits; or business
// interruption) however caused and on any theory of liability, whether in
// contract, strict liability, or tort (including negligence or otherwise)
// arising in any way out of the use of this software, even if advised of the
// possibility of such damage.
//
////////////////////////////////////////////////////////////////////////////////
#ifndef OPENCV_TRANSPOSE_HPP_
#define OPENCV_TRANSPOSE_HPP_
//! @addtogroup matlab
//! @{
template <typename InputScalar, typename OutputScalar>
void transposeBlock(const size_t M, const size_t N, const InputScalar* src, size_t lda, OutputScalar* dst, size_t ldb) {
InputScalar cache[16];
// copy the source into the cache contiguously
for (size_t n = 0; n < N; ++n)
for (size_t m = 0; m < M; ++m)
cache[m+n*4] = src[m+n*lda];
// copy the destination out of the cache contiguously
for (size_t m = 0; m < M; ++m)
for (size_t n = 0; n < N; ++n)
dst[n+m*ldb] = cache[m+n*4];
}
template <typename InputScalar, typename OutputScalar>
void transpose4x4(const InputScalar* src, size_t lda, OutputScalar* dst, size_t ldb) {
InputScalar cache[16];
// copy the source into the cache contiguously
cache[0] = src[0]; cache[1] = src[1]; cache[2] = src[2]; cache[3] = src[3]; src+=lda;
cache[4] = src[0]; cache[5] = src[1]; cache[6] = src[2]; cache[7] = src[3]; src+=lda;
cache[8] = src[0]; cache[9] = src[1]; cache[10] = src[2]; cache[11] = src[3]; src+=lda;
cache[12] = src[0]; cache[13] = src[1]; cache[14] = src[2]; cache[15] = src[3]; src+=lda;
// copy the destination out of the contiguously
dst[0] = cache[0]; dst[1] = cache[4]; dst[2] = cache[8]; dst[3] = cache[12]; dst+=ldb;
dst[0] = cache[1]; dst[1] = cache[5]; dst[2] = cache[9]; dst[3] = cache[13]; dst+=ldb;
dst[0] = cache[2]; dst[1] = cache[6]; dst[2] = cache[10]; dst[3] = cache[14]; dst+=ldb;
dst[0] = cache[3]; dst[1] = cache[7]; dst[2] = cache[11]; dst[3] = cache[15]; dst+=ldb;
}
/*
* Vanilla copy, transpose and cast
*/
template <typename InputScalar, typename OutputScalar>
void gemt(const char major, const size_t M, const size_t N, const InputScalar* a, size_t lda, OutputScalar* b, size_t ldb) {
// 1x1 transpose is just copy
if (M == 1 && N == 1) { *b = *a; return; }
// get the interior 4x4 blocks, and the extra skirting
const size_t Fblock = (major == 'R') ? N/4 : M/4;
const size_t Frem = (major == 'R') ? N%4 : M%4;
const size_t Sblock = (major == 'R') ? M/4 : N/4;
const size_t Srem = (major == 'R') ? M%4 : N%4;
// if less than 4x4, invoke the block transpose immediately
if (M < 4 && N < 4) { transposeBlock(Frem, Srem, a, lda, b, ldb); return; }
// transpose 4x4 blocks
const InputScalar* aptr = a;
OutputScalar* bptr = b;
for (size_t second = 0; second < Sblock; ++second) {
aptr = a + second*lda;
bptr = b + second;
for (size_t first = 0; first < Fblock; ++first) {
transposeBlock(4, 4, aptr, lda, bptr, ldb);
//transpose4x4(aptr, lda, bptr, ldb);
aptr+=4;
bptr+=4*ldb;
}
// transpose trailing blocks on primary dimension
transposeBlock(Frem, 4, aptr, lda, bptr, ldb);
}
// transpose trailing blocks on secondary dimension
aptr = a + 4*Sblock*lda;
bptr = b + 4*Sblock;
for (size_t first = 0; first < Fblock; ++first) {
transposeBlock(4, Srem, aptr, lda, bptr, ldb);
aptr+=4;
bptr+=4*ldb;
}
// transpose bottom right-hand corner
transposeBlock(Frem, Srem, aptr, lda, bptr, ldb);
}
#ifdef __SSE2__
/*
* SSE2 supported fast copy, transpose and cast
*/
#include <emmintrin.h>
template <>
void transpose4x4<float, float>(const float* src, size_t lda, float* dst, size_t ldb) {
__m128 row0, row1, row2, row3;
row0 = _mm_loadu_ps(src);
row1 = _mm_loadu_ps(src+lda);
row2 = _mm_loadu_ps(src+2*lda);
row3 = _mm_loadu_ps(src+3*lda);
_MM_TRANSPOSE4_PS(row0, row1, row2, row3);
_mm_storeu_ps(dst, row0);
_mm_storeu_ps(dst+ldb, row1);
_mm_storeu_ps(dst+2*ldb, row2);
_mm_storeu_ps(dst+3*ldb, row3);
}
#endif
//! @}
#endif