mirror of
https://github.com/opencv/opencv.git
synced 2024-12-04 08:49:14 +08:00
e2499e5b2f
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.
1675 lines
46 KiB
C++
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, ¶m))
|
|
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
|
|
}
|