opencv/modules/python/src2/cv2.cpp
Igor Wodiany e2499e5b2f
Move vector_size_t and vector_vector_Mat
These two typdefs are not compiled when BUILD_opencv_dnn is set to
false, however there are other modules that uses these typedef so
it may cause build errors. Moving typedef to the python module
ensures they are always defined.
2017-10-14 19:06:15 +01:00

1675 lines
46 KiB
C++

#if defined(_MSC_VER) && (_MSC_VER >= 1800)
// eliminating duplicated round() declaration
#define HAVE_ROUND 1
#endif
#include <Python.h>
#define MODULESTR "cv2"
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <numpy/ndarrayobject.h>
#include "pyopencv_generated_include.h"
#include "opencv2/core/types_c.h"
#include "opencv2/opencv_modules.hpp"
#include "pycompat.hpp"
static PyObject* opencv_error = 0;
static int failmsg(const char *fmt, ...)
{
char str[1000];
va_list ap;
va_start(ap, fmt);
vsnprintf(str, sizeof(str), fmt, ap);
va_end(ap);
PyErr_SetString(PyExc_TypeError, str);
return 0;
}
struct ArgInfo
{
const char * name;
bool outputarg;
// more fields may be added if necessary
ArgInfo(const char * name_, bool outputarg_)
: name(name_)
, outputarg(outputarg_) {}
// to match with older pyopencv_to function signature
operator const char *() const { return name; }
};
class PyAllowThreads
{
public:
PyAllowThreads() : _state(PyEval_SaveThread()) {}
~PyAllowThreads()
{
PyEval_RestoreThread(_state);
}
private:
PyThreadState* _state;
};
class PyEnsureGIL
{
public:
PyEnsureGIL() : _state(PyGILState_Ensure()) {}
~PyEnsureGIL()
{
PyGILState_Release(_state);
}
private:
PyGILState_STATE _state;
};
#define ERRWRAP2(expr) \
try \
{ \
PyAllowThreads allowThreads; \
expr; \
} \
catch (const cv::Exception &e) \
{ \
PyErr_SetString(opencv_error, e.what()); \
return 0; \
}
using namespace cv;
typedef std::vector<uchar> vector_uchar;
typedef std::vector<char> vector_char;
typedef std::vector<int> vector_int;
typedef std::vector<float> vector_float;
typedef std::vector<double> vector_double;
typedef std::vector<size_t> vector_size_t;
typedef std::vector<Point> vector_Point;
typedef std::vector<Point2f> vector_Point2f;
typedef std::vector<Point3f> vector_Point3f;
typedef std::vector<Vec2f> vector_Vec2f;
typedef std::vector<Vec3f> vector_Vec3f;
typedef std::vector<Vec4f> vector_Vec4f;
typedef std::vector<Vec6f> vector_Vec6f;
typedef std::vector<Vec4i> vector_Vec4i;
typedef std::vector<Rect> vector_Rect;
typedef std::vector<Rect2d> vector_Rect2d;
typedef std::vector<KeyPoint> vector_KeyPoint;
typedef std::vector<Mat> vector_Mat;
typedef std::vector<std::vector<Mat> > vector_vector_Mat;
typedef std::vector<UMat> vector_UMat;
typedef std::vector<DMatch> vector_DMatch;
typedef std::vector<String> vector_String;
typedef std::vector<Scalar> vector_Scalar;
typedef std::vector<std::vector<char> > vector_vector_char;
typedef std::vector<std::vector<Point> > vector_vector_Point;
typedef std::vector<std::vector<Point2f> > vector_vector_Point2f;
typedef std::vector<std::vector<Point3f> > vector_vector_Point3f;
typedef std::vector<std::vector<DMatch> > vector_vector_DMatch;
typedef std::vector<std::vector<KeyPoint> > vector_vector_KeyPoint;
static PyObject* failmsgp(const char *fmt, ...)
{
char str[1000];
va_list ap;
va_start(ap, fmt);
vsnprintf(str, sizeof(str), fmt, ap);
va_end(ap);
PyErr_SetString(PyExc_TypeError, str);
return 0;
}
class NumpyAllocator : public MatAllocator
{
public:
NumpyAllocator() { stdAllocator = Mat::getStdAllocator(); }
~NumpyAllocator() {}
UMatData* allocate(PyObject* o, int dims, const int* sizes, int type, size_t* step) const
{
UMatData* u = new UMatData(this);
u->data = u->origdata = (uchar*)PyArray_DATA((PyArrayObject*) o);
npy_intp* _strides = PyArray_STRIDES((PyArrayObject*) o);
for( int i = 0; i < dims - 1; i++ )
step[i] = (size_t)_strides[i];
step[dims-1] = CV_ELEM_SIZE(type);
u->size = sizes[0]*step[0];
u->userdata = o;
return u;
}
UMatData* allocate(int dims0, const int* sizes, int type, void* data, size_t* step, int flags, UMatUsageFlags usageFlags) const
{
if( data != 0 )
{
// issue #6969: CV_Error(Error::StsAssert, "The data should normally be NULL!");
// probably this is safe to do in such extreme case
return stdAllocator->allocate(dims0, sizes, type, data, step, flags, usageFlags);
}
PyEnsureGIL gil;
int depth = CV_MAT_DEPTH(type);
int cn = CV_MAT_CN(type);
const int f = (int)(sizeof(size_t)/8);
int typenum = depth == CV_8U ? NPY_UBYTE : depth == CV_8S ? NPY_BYTE :
depth == CV_16U ? NPY_USHORT : depth == CV_16S ? NPY_SHORT :
depth == CV_32S ? NPY_INT : depth == CV_32F ? NPY_FLOAT :
depth == CV_64F ? NPY_DOUBLE : f*NPY_ULONGLONG + (f^1)*NPY_UINT;
int i, dims = dims0;
cv::AutoBuffer<npy_intp> _sizes(dims + 1);
for( i = 0; i < dims; i++ )
_sizes[i] = sizes[i];
if( cn > 1 )
_sizes[dims++] = cn;
PyObject* o = PyArray_SimpleNew(dims, _sizes, typenum);
if(!o)
CV_Error_(Error::StsError, ("The numpy array of typenum=%d, ndims=%d can not be created", typenum, dims));
return allocate(o, dims0, sizes, type, step);
}
bool allocate(UMatData* u, int accessFlags, UMatUsageFlags usageFlags) const
{
return stdAllocator->allocate(u, accessFlags, usageFlags);
}
void deallocate(UMatData* u) const
{
if(!u)
return;
PyEnsureGIL gil;
CV_Assert(u->urefcount >= 0);
CV_Assert(u->refcount >= 0);
if(u->refcount == 0)
{
PyObject* o = (PyObject*)u->userdata;
Py_XDECREF(o);
delete u;
}
}
const MatAllocator* stdAllocator;
};
NumpyAllocator g_numpyAllocator;
template<typename T> static
bool pyopencv_to(PyObject* obj, T& p, const char* name = "<unknown>");
template<typename T> static
PyObject* pyopencv_from(const T& src);
enum { ARG_NONE = 0, ARG_MAT = 1, ARG_SCALAR = 2 };
// special case, when the convertor needs full ArgInfo structure
static bool pyopencv_to(PyObject* o, Mat& m, const ArgInfo info)
{
bool allowND = true;
if(!o || o == Py_None)
{
if( !m.data )
m.allocator = &g_numpyAllocator;
return true;
}
if( PyInt_Check(o) )
{
double v[] = {static_cast<double>(PyInt_AsLong((PyObject*)o)), 0., 0., 0.};
m = Mat(4, 1, CV_64F, v).clone();
return true;
}
if( PyFloat_Check(o) )
{
double v[] = {PyFloat_AsDouble((PyObject*)o), 0., 0., 0.};
m = Mat(4, 1, CV_64F, v).clone();
return true;
}
if( PyTuple_Check(o) )
{
int i, sz = (int)PyTuple_Size((PyObject*)o);
m = Mat(sz, 1, CV_64F);
for( i = 0; i < sz; i++ )
{
PyObject* oi = PyTuple_GET_ITEM(o, i);
if( PyInt_Check(oi) )
m.at<double>(i) = (double)PyInt_AsLong(oi);
else if( PyFloat_Check(oi) )
m.at<double>(i) = (double)PyFloat_AsDouble(oi);
else
{
failmsg("%s is not a numerical tuple", info.name);
m.release();
return false;
}
}
return true;
}
if( !PyArray_Check(o) )
{
failmsg("%s is not a numpy array, neither a scalar", info.name);
return false;
}
PyArrayObject* oarr = (PyArrayObject*) o;
bool needcopy = false, needcast = false;
int typenum = PyArray_TYPE(oarr), new_typenum = typenum;
int type = typenum == NPY_UBYTE ? CV_8U :
typenum == NPY_BYTE ? CV_8S :
typenum == NPY_USHORT ? CV_16U :
typenum == NPY_SHORT ? CV_16S :
typenum == NPY_INT ? CV_32S :
typenum == NPY_INT32 ? CV_32S :
typenum == NPY_FLOAT ? CV_32F :
typenum == NPY_DOUBLE ? CV_64F : -1;
if( type < 0 )
{
if( typenum == NPY_INT64 || typenum == NPY_UINT64 || typenum == NPY_LONG )
{
needcopy = needcast = true;
new_typenum = NPY_INT;
type = CV_32S;
}
else
{
failmsg("%s data type = %d is not supported", info.name, typenum);
return false;
}
}
#ifndef CV_MAX_DIM
const int CV_MAX_DIM = 32;
#endif
int ndims = PyArray_NDIM(oarr);
if(ndims >= CV_MAX_DIM)
{
failmsg("%s dimensionality (=%d) is too high", info.name, ndims);
return false;
}
int size[CV_MAX_DIM+1];
size_t step[CV_MAX_DIM+1];
size_t elemsize = CV_ELEM_SIZE1(type);
const npy_intp* _sizes = PyArray_DIMS(oarr);
const npy_intp* _strides = PyArray_STRIDES(oarr);
bool ismultichannel = ndims == 3 && _sizes[2] <= CV_CN_MAX;
for( int i = ndims-1; i >= 0 && !needcopy; i-- )
{
// these checks handle cases of
// a) multi-dimensional (ndims > 2) arrays, as well as simpler 1- and 2-dimensional cases
// b) transposed arrays, where _strides[] elements go in non-descending order
// c) flipped arrays, where some of _strides[] elements are negative
// the _sizes[i] > 1 is needed to avoid spurious copies when NPY_RELAXED_STRIDES is set
if( (i == ndims-1 && _sizes[i] > 1 && (size_t)_strides[i] != elemsize) ||
(i < ndims-1 && _sizes[i] > 1 && _strides[i] < _strides[i+1]) )
needcopy = true;
}
if( ismultichannel && _strides[1] != (npy_intp)elemsize*_sizes[2] )
needcopy = true;
if (needcopy)
{
if (info.outputarg)
{
failmsg("Layout of the output array %s is incompatible with cv::Mat (step[ndims-1] != elemsize or step[1] != elemsize*nchannels)", info.name);
return false;
}
if( needcast ) {
o = PyArray_Cast(oarr, new_typenum);
oarr = (PyArrayObject*) o;
}
else {
oarr = PyArray_GETCONTIGUOUS(oarr);
o = (PyObject*) oarr;
}
_strides = PyArray_STRIDES(oarr);
}
// Normalize strides in case NPY_RELAXED_STRIDES is set
size_t default_step = elemsize;
for ( int i = ndims - 1; i >= 0; --i )
{
size[i] = (int)_sizes[i];
if ( size[i] > 1 )
{
step[i] = (size_t)_strides[i];
default_step = step[i] * size[i];
}
else
{
step[i] = default_step;
default_step *= size[i];
}
}
// handle degenerate case
if( ndims == 0) {
size[ndims] = 1;
step[ndims] = elemsize;
ndims++;
}
if( ismultichannel )
{
ndims--;
type |= CV_MAKETYPE(0, size[2]);
}
if( ndims > 2 && !allowND )
{
failmsg("%s has more than 2 dimensions", info.name);
return false;
}
m = Mat(ndims, size, type, PyArray_DATA(oarr), step);
m.u = g_numpyAllocator.allocate(o, ndims, size, type, step);
m.addref();
if( !needcopy )
{
Py_INCREF(o);
}
m.allocator = &g_numpyAllocator;
return true;
}
template<>
bool pyopencv_to(PyObject* o, Mat& m, const char* name)
{
return pyopencv_to(o, m, ArgInfo(name, 0));
}
template <typename T>
bool pyopencv_to(PyObject *o, Ptr<T>& p, const char *name)
{
if (!o || o == Py_None)
return true;
p = makePtr<T>();
return pyopencv_to(o, *p, name);
}
template<>
PyObject* pyopencv_from(const Mat& m)
{
if( !m.data )
Py_RETURN_NONE;
Mat temp, *p = (Mat*)&m;
if(!p->u || p->allocator != &g_numpyAllocator)
{
temp.allocator = &g_numpyAllocator;
ERRWRAP2(m.copyTo(temp));
p = &temp;
}
PyObject* o = (PyObject*)p->u->userdata;
Py_INCREF(o);
return o;
}
template<typename _Tp, int m, int n>
PyObject* pyopencv_from(const Matx<_Tp, m, n>& matx)
{
return pyopencv_from(Mat(matx));
}
template<typename T>
PyObject* pyopencv_from(const cv::Ptr<T>& p)
{
if (!p)
Py_RETURN_NONE;
return pyopencv_from(*p);
}
typedef struct {
PyObject_HEAD
UMat* um;
} cv2_UMatWrapperObject;
static bool PyObject_IsUMat(PyObject *o);
// UMatWrapper init - try to map arguments from python to UMat constructors
static int UMatWrapper_init(cv2_UMatWrapperObject *self, PyObject *args, PyObject *kwds)
{
self->um = NULL;
{
// constructor ()
const char *kwlist[] = {NULL};
if (PyArg_ParseTupleAndKeywords(args, kwds, "", (char**) kwlist)) {
self->um = new UMat();
return 0;
}
PyErr_Clear();
}
{
// constructor (rows, cols, type)
const char *kwlist[] = {"rows", "cols", "type", NULL};
int rows, cols, type;
if (PyArg_ParseTupleAndKeywords(args, kwds, "iii", (char**) kwlist, &rows, &cols, &type)) {
self->um = new UMat(rows, cols, type);
return 0;
}
PyErr_Clear();
}
{
// constructor (m, rowRange, colRange)
const char *kwlist[] = {"m", "rowRange", "colRange", NULL};
PyObject *obj = NULL;
int y0 = -1, y1 = -1, x0 = -1, x1 = -1;
if (PyArg_ParseTupleAndKeywords(args, kwds, "O(ii)|(ii)", (char**) kwlist, &obj, &y0, &y1, &x0, &x1) && PyObject_IsUMat(obj)) {
UMat *um_other = ((cv2_UMatWrapperObject *) obj)->um;
Range rowRange(y0, y1);
Range colRange = (x0 >= 0 && x1 >= 0) ? Range(x0, x1) : Range::all();
self->um = new UMat(*um_other, rowRange, colRange);
return 0;
}
PyErr_Clear();
}
{
// constructor (m)
const char *kwlist[] = {"m", NULL};
PyObject *obj = NULL;
if (PyArg_ParseTupleAndKeywords(args, kwds, "O", (char**) kwlist, &obj)) {
// constructor (UMat m)
if (PyObject_IsUMat(obj)) {
UMat *um_other = ((cv2_UMatWrapperObject *) obj)->um;
self->um = new UMat(*um_other);
return 0;
}
// python specific constructor from array like object
Mat m;
if (pyopencv_to(obj, m, ArgInfo("UMatWrapper.np_mat", 0))) {
self->um = new UMat();
m.copyTo(*self->um);
return 0;
}
}
PyErr_Clear();
}
PyErr_SetString(PyExc_TypeError, "no matching UMat constructor found/supported");
return -1;
}
static void UMatWrapper_dealloc(cv2_UMatWrapperObject* self)
{
if (self->um)
delete self->um;
#if PY_MAJOR_VERSION >= 3
Py_TYPE(self)->tp_free((PyObject*)self);
#else
self->ob_type->tp_free((PyObject*)self);
#endif
}
// UMatWrapper.get() - returns numpy array by transferring UMat data to Mat and than wrapping it to numpy array
// (using numpy allocator - and so without unnecessary copy)
static PyObject * UMatWrapper_get(cv2_UMatWrapperObject* self)
{
Mat m;
m.allocator = &g_numpyAllocator;
self->um->copyTo(m);
return pyopencv_from(m);
}
// UMatWrapper.handle() - returns the OpenCL handle of the UMat object
static PyObject * UMatWrapper_handle(cv2_UMatWrapperObject* self, PyObject *args, PyObject *kwds)
{
const char *kwlist[] = {"accessFlags", NULL};
int accessFlags;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", (char**) kwlist, &accessFlags))
return 0;
return PyLong_FromVoidPtr(self->um->handle(accessFlags));
}
// UMatWrapper.isContinuous() - returns true if the matrix data is continuous
static PyObject * UMatWrapper_isContinuous(cv2_UMatWrapperObject* self)
{
return PyBool_FromLong(self->um->isContinuous());
}
// UMatWrapper.isContinuous() - returns true if the matrix is a submatrix of another matrix
static PyObject * UMatWrapper_isSubmatrix(cv2_UMatWrapperObject* self)
{
return PyBool_FromLong(self->um->isSubmatrix());
}
// UMatWrapper.context() - returns the OpenCL context used by OpenCV UMat
static PyObject * UMatWrapper_context(cv2_UMatWrapperObject*)
{
return PyLong_FromVoidPtr(cv::ocl::Context::getDefault().ptr());
}
// UMatWrapper.context() - returns the OpenCL queue used by OpenCV UMat
static PyObject * UMatWrapper_queue(cv2_UMatWrapperObject*)
{
return PyLong_FromVoidPtr(cv::ocl::Queue::getDefault().ptr());
}
static PyObject * UMatWrapper_offset_getter(cv2_UMatWrapperObject* self, void*)
{
return PyLong_FromSsize_t(self->um->offset);
}
static PyMethodDef UMatWrapper_methods[] = {
{"get", (PyCFunction)UMatWrapper_get, METH_NOARGS,
"Returns numpy array"
},
{"handle", (PyCFunction)UMatWrapper_handle, METH_VARARGS | METH_KEYWORDS,
"Returns UMat native handle"
},
{"isContinuous", (PyCFunction)UMatWrapper_isContinuous, METH_NOARGS,
"Returns true if the matrix data is continuous"
},
{"isSubmatrix", (PyCFunction)UMatWrapper_isSubmatrix, METH_NOARGS,
"Returns true if the matrix is a submatrix of another matrix"
},
{"context", (PyCFunction)UMatWrapper_context, METH_NOARGS | METH_STATIC,
"Returns OpenCL context handle"
},
{"queue", (PyCFunction)UMatWrapper_queue, METH_NOARGS | METH_STATIC,
"Returns OpenCL queue handle"
},
{NULL, NULL, 0, NULL} /* Sentinel */
};
static PyGetSetDef UMatWrapper_getset[] = {
{(char*) "offset", (getter) UMatWrapper_offset_getter, NULL, NULL, NULL},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
static PyTypeObject cv2_UMatWrapperType = {
#if PY_MAJOR_VERSION >= 3
PyVarObject_HEAD_INIT(NULL, 0)
#else
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
#endif
"cv2.UMat", /* tp_name */
sizeof(cv2_UMatWrapperObject), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)UMatWrapper_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"OpenCV 3 UMat wrapper. Used for T-API support.", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
UMatWrapper_methods, /* tp_methods */
0, /* tp_members */
UMatWrapper_getset, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)UMatWrapper_init, /* tp_init */
0, /* tp_alloc */
PyType_GenericNew, /* tp_new */
0, /* tp_free */
0, /* tp_is_gc */
0, /* tp_bases */
0, /* tp_mro */
0, /* tp_cache */
0, /* tp_subclasses */
0, /* tp_weaklist */
0, /* tp_del */
0, /* tp_version_tag */
#if PY_MAJOR_VERSION >= 3
0, /* tp_finalize */
#endif
};
static bool PyObject_IsUMat(PyObject *o) {
return (o != NULL) && PyObject_TypeCheck(o, &cv2_UMatWrapperType);
}
static bool pyopencv_to(PyObject* o, UMat& um, const ArgInfo info) {
if (PyObject_IsUMat(o)) {
um = *((cv2_UMatWrapperObject *) o)->um;
return true;
}
Mat m;
if (!pyopencv_to(o, m, info)) {
return false;
}
m.copyTo(um);
return true;
}
template<>
bool pyopencv_to(PyObject* o, UMat& um, const char* name)
{
return pyopencv_to(o, um, ArgInfo(name, 0));
}
template<>
PyObject* pyopencv_from(const UMat& m) {
PyObject *o = PyObject_CallObject((PyObject *) &cv2_UMatWrapperType, NULL);
*((cv2_UMatWrapperObject *) o)->um = m;
return o;
}
template<>
bool pyopencv_to(PyObject *o, Scalar& s, const char *name)
{
if(!o || o == Py_None)
return true;
if (PySequence_Check(o)) {
PyObject *fi = PySequence_Fast(o, name);
if (fi == NULL)
return false;
if (4 < PySequence_Fast_GET_SIZE(fi))
{
failmsg("Scalar value for argument '%s' is longer than 4", name);
return false;
}
for (Py_ssize_t i = 0; i < PySequence_Fast_GET_SIZE(fi); i++) {
PyObject *item = PySequence_Fast_GET_ITEM(fi, i);
if (PyFloat_Check(item) || PyInt_Check(item)) {
s[(int)i] = PyFloat_AsDouble(item);
} else {
failmsg("Scalar value for argument '%s' is not numeric", name);
return false;
}
}
Py_DECREF(fi);
} else {
if (PyFloat_Check(o) || PyInt_Check(o)) {
s[0] = PyFloat_AsDouble(o);
} else {
failmsg("Scalar value for argument '%s' is not numeric", name);
return false;
}
}
return true;
}
template<>
PyObject* pyopencv_from(const Scalar& src)
{
return Py_BuildValue("(dddd)", src[0], src[1], src[2], src[3]);
}
template<>
PyObject* pyopencv_from(const bool& value)
{
return PyBool_FromLong(value);
}
template<>
bool pyopencv_to(PyObject* obj, bool& value, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
int _val = PyObject_IsTrue(obj);
if(_val < 0)
return false;
value = _val > 0;
return true;
}
template<>
PyObject* pyopencv_from(const size_t& value)
{
return PyLong_FromSize_t(value);
}
template<>
bool pyopencv_to(PyObject* obj, size_t& value, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
value = (int)PyLong_AsUnsignedLong(obj);
return value != (size_t)-1 || !PyErr_Occurred();
}
template<>
PyObject* pyopencv_from(const int& value)
{
return PyInt_FromLong(value);
}
template<>
bool pyopencv_to(PyObject* obj, int& value, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
if(PyInt_Check(obj))
value = (int)PyInt_AsLong(obj);
else if(PyLong_Check(obj))
value = (int)PyLong_AsLong(obj);
else
return false;
return value != -1 || !PyErr_Occurred();
}
template<>
PyObject* pyopencv_from(const uchar& value)
{
return PyInt_FromLong(value);
}
template<>
bool pyopencv_to(PyObject* obj, uchar& value, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
int ivalue = (int)PyInt_AsLong(obj);
value = cv::saturate_cast<uchar>(ivalue);
return ivalue != -1 || !PyErr_Occurred();
}
template<>
PyObject* pyopencv_from(const double& value)
{
return PyFloat_FromDouble(value);
}
template<>
bool pyopencv_to(PyObject* obj, double& value, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
if(!!PyInt_CheckExact(obj))
value = (double)PyInt_AS_LONG(obj);
else
value = PyFloat_AsDouble(obj);
return !PyErr_Occurred();
}
template<>
PyObject* pyopencv_from(const float& value)
{
return PyFloat_FromDouble(value);
}
template<>
bool pyopencv_to(PyObject* obj, float& value, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
if(!!PyInt_CheckExact(obj))
value = (float)PyInt_AS_LONG(obj);
else
value = (float)PyFloat_AsDouble(obj);
return !PyErr_Occurred();
}
template<>
PyObject* pyopencv_from(const int64& value)
{
return PyLong_FromLongLong(value);
}
template<>
PyObject* pyopencv_from(const String& value)
{
return PyString_FromString(value.empty() ? "" : value.c_str());
}
template<>
bool pyopencv_to(PyObject* obj, String& value, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
char* str = PyString_AsString(obj);
if(!str)
return false;
value = String(str);
return true;
}
template<>
bool pyopencv_to(PyObject* obj, Size& sz, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
return PyArg_ParseTuple(obj, "ii", &sz.width, &sz.height) > 0;
}
template<>
PyObject* pyopencv_from(const Size& sz)
{
return Py_BuildValue("(ii)", sz.width, sz.height);
}
template<>
bool pyopencv_to(PyObject* obj, Size_<float>& sz, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
return PyArg_ParseTuple(obj, "ff", &sz.width, &sz.height) > 0;
}
template<>
PyObject* pyopencv_from(const Size_<float>& sz)
{
return Py_BuildValue("(ff)", sz.width, sz.height);
}
template<>
bool pyopencv_to(PyObject* obj, Rect& r, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
return PyArg_ParseTuple(obj, "iiii", &r.x, &r.y, &r.width, &r.height) > 0;
}
template<>
PyObject* pyopencv_from(const Rect& r)
{
return Py_BuildValue("(iiii)", r.x, r.y, r.width, r.height);
}
template<>
bool pyopencv_to(PyObject* obj, Rect2d& r, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
return PyArg_ParseTuple(obj, "dddd", &r.x, &r.y, &r.width, &r.height) > 0;
}
template<>
PyObject* pyopencv_from(const Rect2d& r)
{
return Py_BuildValue("(dddd)", r.x, r.y, r.width, r.height);
}
template<>
bool pyopencv_to(PyObject* obj, Range& r, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
if(PyObject_Size(obj) == 0)
{
r = Range::all();
return true;
}
return PyArg_ParseTuple(obj, "ii", &r.start, &r.end) > 0;
}
template<>
PyObject* pyopencv_from(const Range& r)
{
return Py_BuildValue("(ii)", r.start, r.end);
}
template<>
bool pyopencv_to(PyObject* obj, Point& p, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
if(!!PyComplex_CheckExact(obj))
{
Py_complex c = PyComplex_AsCComplex(obj);
p.x = saturate_cast<int>(c.real);
p.y = saturate_cast<int>(c.imag);
return true;
}
return PyArg_ParseTuple(obj, "ii", &p.x, &p.y) > 0;
}
template<>
bool pyopencv_to(PyObject* obj, Point2f& p, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
if(!!PyComplex_CheckExact(obj))
{
Py_complex c = PyComplex_AsCComplex(obj);
p.x = saturate_cast<float>(c.real);
p.y = saturate_cast<float>(c.imag);
return true;
}
return PyArg_ParseTuple(obj, "ff", &p.x, &p.y) > 0;
}
template<>
bool pyopencv_to(PyObject* obj, Point2d& p, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
if(!!PyComplex_CheckExact(obj))
{
Py_complex c = PyComplex_AsCComplex(obj);
p.x = saturate_cast<double>(c.real);
p.y = saturate_cast<double>(c.imag);
return true;
}
return PyArg_ParseTuple(obj, "dd", &p.x, &p.y) > 0;
}
template<>
bool pyopencv_to(PyObject* obj, Point3f& p, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
return PyArg_ParseTuple(obj, "fff", &p.x, &p.y, &p.z) > 0;
}
template<>
bool pyopencv_to(PyObject* obj, Point3d& p, const char* name)
{
(void)name;
if(!obj || obj == Py_None)
return true;
return PyArg_ParseTuple(obj, "ddd", &p.x, &p.y, &p.z) > 0;
}
template<>
PyObject* pyopencv_from(const Point& p)
{
return Py_BuildValue("(ii)", p.x, p.y);
}
template<>
PyObject* pyopencv_from(const Point2f& p)
{
return Py_BuildValue("(dd)", p.x, p.y);
}
template<>
PyObject* pyopencv_from(const Point3f& p)
{
return Py_BuildValue("(ddd)", p.x, p.y, p.z);
}
template<>
bool pyopencv_to(PyObject* obj, Vec3d& v, const char* name)
{
(void)name;
if(!obj)
return true;
return PyArg_ParseTuple(obj, "ddd", &v[0], &v[1], &v[2]) > 0;
}
template<>
PyObject* pyopencv_from(const Vec3d& v)
{
return Py_BuildValue("(ddd)", v[0], v[1], v[2]);
}
template<>
PyObject* pyopencv_from(const Vec2d& v)
{
return Py_BuildValue("(dd)", v[0], v[1]);
}
template<>
PyObject* pyopencv_from(const Point2d& p)
{
return Py_BuildValue("(dd)", p.x, p.y);
}
template<>
PyObject* pyopencv_from(const Point3d& p)
{
return Py_BuildValue("(ddd)", p.x, p.y, p.z);
}
template<typename _Tp> struct pyopencvVecConverter
{
static bool to(PyObject* obj, std::vector<_Tp>& value, const ArgInfo info)
{
typedef typename DataType<_Tp>::channel_type _Cp;
if(!obj || obj == Py_None)
return true;
if (PyArray_Check(obj))
{
Mat m;
pyopencv_to(obj, m, info);
m.copyTo(value);
}
if (!PySequence_Check(obj))
return false;
PyObject *seq = PySequence_Fast(obj, info.name);
if (seq == NULL)
return false;
int i, j, n = (int)PySequence_Fast_GET_SIZE(seq);
value.resize(n);
int type = traits::Type<_Tp>::value;
int depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type);
PyObject** items = PySequence_Fast_ITEMS(seq);
for( i = 0; i < n; i++ )
{
PyObject* item = items[i];
PyObject* seq_i = 0;
PyObject** items_i = &item;
_Cp* data = (_Cp*)&value[i];
if( channels == 2 && PyComplex_CheckExact(item) )
{
Py_complex c = PyComplex_AsCComplex(obj);
data[0] = saturate_cast<_Cp>(c.real);
data[1] = saturate_cast<_Cp>(c.imag);
continue;
}
if( channels > 1 )
{
if( PyArray_Check(item))
{
Mat src;
pyopencv_to(item, src, info);
if( src.dims != 2 || src.channels() != 1 ||
((src.cols != 1 || src.rows != channels) &&
(src.cols != channels || src.rows != 1)))
break;
Mat dst(src.rows, src.cols, depth, data);
src.convertTo(dst, type);
if( dst.data != (uchar*)data )
break;
continue;
}
seq_i = PySequence_Fast(item, info.name);
if( !seq_i || (int)PySequence_Fast_GET_SIZE(seq_i) != channels )
{
Py_XDECREF(seq_i);
break;
}
items_i = PySequence_Fast_ITEMS(seq_i);
}
for( j = 0; j < channels; j++ )
{
PyObject* item_ij = items_i[j];
if( PyInt_Check(item_ij))
{
int v = (int)PyInt_AsLong(item_ij);
if( v == -1 && PyErr_Occurred() )
break;
data[j] = saturate_cast<_Cp>(v);
}
else if( PyLong_Check(item_ij))
{
int v = (int)PyLong_AsLong(item_ij);
if( v == -1 && PyErr_Occurred() )
break;
data[j] = saturate_cast<_Cp>(v);
}
else if( PyFloat_Check(item_ij))
{
double v = PyFloat_AsDouble(item_ij);
if( PyErr_Occurred() )
break;
data[j] = saturate_cast<_Cp>(v);
}
else
break;
}
Py_XDECREF(seq_i);
if( j < channels )
break;
}
Py_DECREF(seq);
return i == n;
}
static PyObject* from(const std::vector<_Tp>& value)
{
if(value.empty())
return PyTuple_New(0);
int type = traits::Type<_Tp>::value;
int depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type);
Mat src((int)value.size(), channels, depth, (uchar*)&value[0]);
return pyopencv_from(src);
}
};
template<typename _Tp>
bool pyopencv_to(PyObject* obj, std::vector<_Tp>& value, const ArgInfo info)
{
return pyopencvVecConverter<_Tp>::to(obj, value, info);
}
template<typename _Tp>
PyObject* pyopencv_from(const std::vector<_Tp>& value)
{
return pyopencvVecConverter<_Tp>::from(value);
}
template<typename _Tp> static inline bool pyopencv_to_generic_vec(PyObject* obj, std::vector<_Tp>& value, const ArgInfo info)
{
if(!obj || obj == Py_None)
return true;
if (!PySequence_Check(obj))
return false;
PyObject *seq = PySequence_Fast(obj, info.name);
if (seq == NULL)
return false;
int i, n = (int)PySequence_Fast_GET_SIZE(seq);
value.resize(n);
PyObject** items = PySequence_Fast_ITEMS(seq);
for( i = 0; i < n; i++ )
{
PyObject* item = items[i];
if(!pyopencv_to(item, value[i], info))
break;
}
Py_DECREF(seq);
return i == n;
}
template<typename _Tp> static inline PyObject* pyopencv_from_generic_vec(const std::vector<_Tp>& value)
{
int i, n = (int)value.size();
PyObject* seq = PyList_New(n);
for( i = 0; i < n; i++ )
{
PyObject* item = pyopencv_from(value[i]);
if(!item)
break;
PyList_SET_ITEM(seq, i, item);
}
if( i < n )
{
Py_DECREF(seq);
return 0;
}
return seq;
}
template<>
PyObject* pyopencv_from(const std::pair<int, double>& src)
{
return Py_BuildValue("(id)", src.first, src.second);
}
template<typename _Tp, typename _Tr> struct pyopencvVecConverter<std::pair<_Tp, _Tr> >
{
static bool to(PyObject* obj, std::vector<std::pair<_Tp, _Tr> >& value, const ArgInfo info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
static PyObject* from(const std::vector<std::pair<_Tp, _Tr> >& value)
{
return pyopencv_from_generic_vec(value);
}
};
template<typename _Tp> struct pyopencvVecConverter<std::vector<_Tp> >
{
static bool to(PyObject* obj, std::vector<std::vector<_Tp> >& value, const ArgInfo info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
static PyObject* from(const std::vector<std::vector<_Tp> >& value)
{
return pyopencv_from_generic_vec(value);
}
};
template<> struct pyopencvVecConverter<Mat>
{
static bool to(PyObject* obj, std::vector<Mat>& value, const ArgInfo info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
static PyObject* from(const std::vector<Mat>& value)
{
return pyopencv_from_generic_vec(value);
}
};
template<> struct pyopencvVecConverter<KeyPoint>
{
static bool to(PyObject* obj, std::vector<KeyPoint>& value, const ArgInfo info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
static PyObject* from(const std::vector<KeyPoint>& value)
{
return pyopencv_from_generic_vec(value);
}
};
template<> struct pyopencvVecConverter<DMatch>
{
static bool to(PyObject* obj, std::vector<DMatch>& value, const ArgInfo info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
static PyObject* from(const std::vector<DMatch>& value)
{
return pyopencv_from_generic_vec(value);
}
};
template<> struct pyopencvVecConverter<String>
{
static bool to(PyObject* obj, std::vector<String>& value, const ArgInfo info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
static PyObject* from(const std::vector<String>& value)
{
return pyopencv_from_generic_vec(value);
}
};
template<>
bool pyopencv_to(PyObject *obj, TermCriteria& dst, const char *name)
{
(void)name;
if(!obj)
return true;
return PyArg_ParseTuple(obj, "iid", &dst.type, &dst.maxCount, &dst.epsilon) > 0;
}
template<>
PyObject* pyopencv_from(const TermCriteria& src)
{
return Py_BuildValue("(iid)", src.type, src.maxCount, src.epsilon);
}
template<>
bool pyopencv_to(PyObject *obj, RotatedRect& dst, const char *name)
{
(void)name;
if(!obj)
return true;
return PyArg_ParseTuple(obj, "(ff)(ff)f", &dst.center.x, &dst.center.y, &dst.size.width, &dst.size.height, &dst.angle) > 0;
}
template<>
PyObject* pyopencv_from(const RotatedRect& src)
{
return Py_BuildValue("((ff)(ff)f)", src.center.x, src.center.y, src.size.width, src.size.height, src.angle);
}
template<>
PyObject* pyopencv_from(const Moments& m)
{
return Py_BuildValue("{s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d,s:d}",
"m00", m.m00, "m10", m.m10, "m01", m.m01,
"m20", m.m20, "m11", m.m11, "m02", m.m02,
"m30", m.m30, "m21", m.m21, "m12", m.m12, "m03", m.m03,
"mu20", m.mu20, "mu11", m.mu11, "mu02", m.mu02,
"mu30", m.mu30, "mu21", m.mu21, "mu12", m.mu12, "mu03", m.mu03,
"nu20", m.nu20, "nu11", m.nu11, "nu02", m.nu02,
"nu30", m.nu30, "nu21", m.nu21, "nu12", m.nu12, "nu03", m.nu03);
}
#include "pyopencv_custom_headers.h"
static void OnMouse(int event, int x, int y, int flags, void* param)
{
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
PyObject *o = (PyObject*)param;
PyObject *args = Py_BuildValue("iiiiO", event, x, y, flags, PyTuple_GetItem(o, 1));
PyObject *r = PyObject_Call(PyTuple_GetItem(o, 0), args, NULL);
if (r == NULL)
PyErr_Print();
else
Py_DECREF(r);
Py_DECREF(args);
PyGILState_Release(gstate);
}
#ifdef HAVE_OPENCV_HIGHGUI
static PyObject *pycvSetMouseCallback(PyObject*, PyObject *args, PyObject *kw)
{
const char *keywords[] = { "window_name", "on_mouse", "param", NULL };
char* name;
PyObject *on_mouse;
PyObject *param = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|O", (char**)keywords, &name, &on_mouse, &param))
return NULL;
if (!PyCallable_Check(on_mouse)) {
PyErr_SetString(PyExc_TypeError, "on_mouse must be callable");
return NULL;
}
if (param == NULL) {
param = Py_None;
}
ERRWRAP2(setMouseCallback(name, OnMouse, Py_BuildValue("OO", on_mouse, param)));
Py_RETURN_NONE;
}
#endif
static void OnChange(int pos, void *param)
{
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
PyObject *o = (PyObject*)param;
PyObject *args = Py_BuildValue("(i)", pos);
PyObject *r = PyObject_Call(PyTuple_GetItem(o, 0), args, NULL);
if (r == NULL)
PyErr_Print();
Py_DECREF(args);
PyGILState_Release(gstate);
}
#ifdef HAVE_OPENCV_HIGHGUI
static PyObject *pycvCreateTrackbar(PyObject*, PyObject *args)
{
PyObject *on_change;
char* trackbar_name;
char* window_name;
int *value = new int;
int count;
if (!PyArg_ParseTuple(args, "ssiiO", &trackbar_name, &window_name, value, &count, &on_change))
return NULL;
if (!PyCallable_Check(on_change)) {
PyErr_SetString(PyExc_TypeError, "on_change must be callable");
return NULL;
}
ERRWRAP2(createTrackbar(trackbar_name, window_name, value, count, OnChange, Py_BuildValue("OO", on_change, Py_None)));
Py_RETURN_NONE;
}
static void OnButtonChange(int state, void *param)
{
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
PyObject *o = (PyObject*)param;
PyObject *args;
if(PyTuple_GetItem(o, 1) != NULL)
{
args = Py_BuildValue("(iO)", state, PyTuple_GetItem(o,1));
}
else
{
args = Py_BuildValue("(i)", state);
}
PyObject *r = PyObject_Call(PyTuple_GetItem(o, 0), args, NULL);
if (r == NULL)
PyErr_Print();
Py_DECREF(args);
PyGILState_Release(gstate);
}
static PyObject *pycvCreateButton(PyObject*, PyObject *args, PyObject *kw)
{
const char* keywords[] = {"buttonName", "onChange", "userData", "buttonType", "initialButtonState", NULL};
PyObject *on_change;
PyObject *userdata = NULL;
char* button_name;
int button_type = 0;
int initial_button_state = 0;
if (!PyArg_ParseTupleAndKeywords(args, kw, "sO|Oii", (char**)keywords, &button_name, &on_change, &userdata, &button_type, &initial_button_state))
return NULL;
if (!PyCallable_Check(on_change)) {
PyErr_SetString(PyExc_TypeError, "onChange must be callable");
return NULL;
}
if (userdata == NULL) {
userdata = Py_None;
}
ERRWRAP2(createButton(button_name, OnButtonChange, Py_BuildValue("OO", on_change, userdata), button_type, initial_button_state != 0));
Py_RETURN_NONE;
}
#endif
///////////////////////////////////////////////////////////////////////////////////////
static int convert_to_char(PyObject *o, char *dst, const char *name = "no_name")
{
if (PyString_Check(o) && PyString_Size(o) == 1) {
*dst = PyString_AsString(o)[0];
return 1;
} else {
(*dst) = 0;
return failmsg("Expected single character string for argument '%s'", name);
}
}
#if PY_MAJOR_VERSION >= 3
#define MKTYPE2(NAME) pyopencv_##NAME##_specials(); if (!to_ok(&pyopencv_##NAME##_Type)) return NULL;
#else
#define MKTYPE2(NAME) pyopencv_##NAME##_specials(); if (!to_ok(&pyopencv_##NAME##_Type)) return
#endif
#ifdef __GNUC__
# pragma GCC diagnostic ignored "-Wunused-parameter"
# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
#include "pyopencv_generated_types.h"
#include "pyopencv_generated_funcs.h"
static PyMethodDef special_methods[] = {
#ifdef HAVE_OPENCV_HIGHGUI
{"createTrackbar", pycvCreateTrackbar, METH_VARARGS, "createTrackbar(trackbarName, windowName, value, count, onChange) -> None"},
{"createButton", (PyCFunction)pycvCreateButton, METH_VARARGS | METH_KEYWORDS, "createButton(buttonName, onChange [, userData, buttonType, initialButtonState]) -> None"},
{"setMouseCallback", (PyCFunction)pycvSetMouseCallback, METH_VARARGS | METH_KEYWORDS, "setMouseCallback(windowName, onMouse [, param]) -> None"},
#endif
{NULL, NULL},
};
/************************************************************************/
/* Module init */
struct ConstDef
{
const char * name;
long val;
};
static void init_submodule(PyObject * root, const char * name, PyMethodDef * methods, ConstDef * consts)
{
// traverse and create nested submodules
std::string s = name;
size_t i = s.find('.');
while (i < s.length() && i != std::string::npos)
{
size_t j = s.find('.', i);
if (j == std::string::npos)
j = s.length();
std::string short_name = s.substr(i, j-i);
std::string full_name = s.substr(0, j);
i = j+1;
PyObject * d = PyModule_GetDict(root);
PyObject * submod = PyDict_GetItemString(d, short_name.c_str());
if (submod == NULL)
{
submod = PyImport_AddModule(full_name.c_str());
PyDict_SetItemString(d, short_name.c_str(), submod);
}
if (short_name != "")
root = submod;
}
// populate module's dict
PyObject * d = PyModule_GetDict(root);
for (PyMethodDef * m = methods; m->ml_name != NULL; ++m)
{
PyObject * method_obj = PyCFunction_NewEx(m, NULL, NULL);
PyDict_SetItemString(d, m->ml_name, method_obj);
Py_DECREF(method_obj);
}
for (ConstDef * c = consts; c->name != NULL; ++c)
{
PyDict_SetItemString(d, c->name, PyInt_FromLong(c->val));
}
}
#include "pyopencv_generated_ns_reg.h"
static int to_ok(PyTypeObject *to)
{
to->tp_alloc = PyType_GenericAlloc;
to->tp_new = PyType_GenericNew;
to->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
return (PyType_Ready(to) == 0);
}
#if PY_MAJOR_VERSION >= 3
extern "C" CV_EXPORTS PyObject* PyInit_cv2();
static struct PyModuleDef cv2_moduledef =
{
PyModuleDef_HEAD_INIT,
MODULESTR,
"Python wrapper for OpenCV.",
-1, /* size of per-interpreter state of the module,
or -1 if the module keeps state in global variables. */
special_methods
};
PyObject* PyInit_cv2()
#else
extern "C" CV_EXPORTS void initcv2();
void initcv2()
#endif
{
import_array();
#include "pyopencv_generated_type_reg.h"
#if PY_MAJOR_VERSION >= 3
PyObject* m = PyModule_Create(&cv2_moduledef);
#else
PyObject* m = Py_InitModule(MODULESTR, special_methods);
#endif
init_submodules(m); // from "pyopencv_generated_ns_reg.h"
PyObject* d = PyModule_GetDict(m);
PyDict_SetItemString(d, "__version__", PyString_FromString(CV_VERSION));
opencv_error = PyErr_NewException((char*)MODULESTR".error", NULL, NULL);
PyDict_SetItemString(d, "error", opencv_error);
//Registering UMatWrapper python class in cv2 module:
if (PyType_Ready(&cv2_UMatWrapperType) < 0)
#if PY_MAJOR_VERSION >= 3
return NULL;
#else
return;
#endif
#if PY_MAJOR_VERSION >= 3
#define PUBLISH_OBJECT(name, type) Py_INCREF(&type);\
PyModule_AddObject(m, name, (PyObject *)&type);
#else
// Unrolled Py_INCREF(&type) without (PyObject*) cast
// due to "warning: dereferencing type-punned pointer will break strict-aliasing rules"
#define PUBLISH_OBJECT(name, type) _Py_INC_REFTOTAL _Py_REF_DEBUG_COMMA (&type)->ob_refcnt++;\
PyModule_AddObject(m, name, (PyObject *)&type);
#endif
PUBLISH_OBJECT("UMat", cv2_UMatWrapperType);
#include "pyopencv_generated_type_publish.h"
#define PUBLISH(I) PyDict_SetItemString(d, #I, PyInt_FromLong(I))
//#define PUBLISHU(I) PyDict_SetItemString(d, #I, PyLong_FromUnsignedLong(I))
#define PUBLISH2(I, value) PyDict_SetItemString(d, #I, PyLong_FromLong(value))
PUBLISH(CV_8U);
PUBLISH(CV_8UC1);
PUBLISH(CV_8UC2);
PUBLISH(CV_8UC3);
PUBLISH(CV_8UC4);
PUBLISH(CV_8S);
PUBLISH(CV_8SC1);
PUBLISH(CV_8SC2);
PUBLISH(CV_8SC3);
PUBLISH(CV_8SC4);
PUBLISH(CV_16U);
PUBLISH(CV_16UC1);
PUBLISH(CV_16UC2);
PUBLISH(CV_16UC3);
PUBLISH(CV_16UC4);
PUBLISH(CV_16S);
PUBLISH(CV_16SC1);
PUBLISH(CV_16SC2);
PUBLISH(CV_16SC3);
PUBLISH(CV_16SC4);
PUBLISH(CV_32S);
PUBLISH(CV_32SC1);
PUBLISH(CV_32SC2);
PUBLISH(CV_32SC3);
PUBLISH(CV_32SC4);
PUBLISH(CV_32F);
PUBLISH(CV_32FC1);
PUBLISH(CV_32FC2);
PUBLISH(CV_32FC3);
PUBLISH(CV_32FC4);
PUBLISH(CV_64F);
PUBLISH(CV_64FC1);
PUBLISH(CV_64FC2);
PUBLISH(CV_64FC3);
PUBLISH(CV_64FC4);
#if PY_MAJOR_VERSION >= 3
return m;
#endif
}