00001
00002
00003 #include "module.hpp"
00004
00005 #include "opencv2/core/types_c.h"
00006
00007 #include "opencv2/opencv_modules.hpp"
00008
00009 #include "pycompat.hpp"
00010
00011 static PyObject* opencv_error = 0;
00012
00013 static int failmsg(const char *fmt, ...)
00014 {
00015 char str[1000];
00016
00017 va_list ap;
00018 va_start(ap, fmt);
00019 vsnprintf(str, sizeof(str), fmt, ap);
00020 va_end(ap);
00021
00022 PyErr_SetString(PyExc_TypeError, str);
00023 return 0;
00024 }
00025
00026 struct ArgInfo
00027 {
00028 const char * name;
00029 bool outputarg;
00030
00031
00032 ArgInfo(const char * name_, bool outputarg_)
00033 : name(name_)
00034 , outputarg(outputarg_) {}
00035
00036
00037 operator const char *() const { return name; }
00038 };
00039
00040 class PyAllowThreads
00041 {
00042 public:
00043 PyAllowThreads() : _state(PyEval_SaveThread()) {}
00044 ~PyAllowThreads()
00045 {
00046 PyEval_RestoreThread(_state);
00047 }
00048 private:
00049 PyThreadState* _state;
00050 };
00051
00052 class PyEnsureGIL
00053 {
00054 public:
00055 PyEnsureGIL() : _state(PyGILState_Ensure()) {}
00056 ~PyEnsureGIL()
00057 {
00058 PyGILState_Release(_state);
00059 }
00060 private:
00061 PyGILState_STATE _state;
00062 };
00063
00064 #define ERRWRAP2(expr) \
00065 try \
00066 { \
00067 PyAllowThreads allowThreads; \
00068 expr; \
00069 } \
00070 catch (const cv::Exception &e) \
00071 { \
00072 PyErr_SetString(opencv_error, e.what()); \
00073 return 0; \
00074 }
00075
00076 using namespace cv;
00077
00078 static PyObject* failmsgp(const char *fmt, ...)
00079 {
00080 char str[1000];
00081
00082 va_list ap;
00083 va_start(ap, fmt);
00084 vsnprintf(str, sizeof(str), fmt, ap);
00085 va_end(ap);
00086
00087 PyErr_SetString(PyExc_TypeError, str);
00088 return 0;
00089 }
00090
00091 class NumpyAllocator : public MatAllocator
00092 {
00093 public:
00094 NumpyAllocator() { stdAllocator = Mat::getStdAllocator(); }
00095 ~NumpyAllocator() {}
00096
00097 UMatData* allocate(PyObject* o, int dims, const int* sizes, int type, size_t* step) const
00098 {
00099 UMatData* u = new UMatData(this);
00100 u->data = u->origdata = (uchar*)PyArray_DATA((PyArrayObject*) o);
00101 npy_intp* _strides = PyArray_STRIDES((PyArrayObject*) o);
00102 for( int i = 0; i < dims - 1; i++ )
00103 step[i] = (size_t)_strides[i];
00104 step[dims-1] = CV_ELEM_SIZE(type);
00105 u->size = sizes[0]*step[0];
00106 u->userdata = o;
00107 return u;
00108 }
00109
00110 UMatData* allocate(int dims0, const int* sizes, int type, void* data, size_t* step, int flags, UMatUsageFlags usageFlags) const
00111 {
00112 if( data != 0 )
00113 {
00114 CV_Error(Error::StsAssert, "The data should normally be NULL!");
00115
00116 return stdAllocator->allocate(dims0, sizes, type, data, step, flags, usageFlags);
00117 }
00118 PyEnsureGIL gil;
00119
00120 int depth = CV_MAT_DEPTH(type);
00121 int cn = CV_MAT_CN(type);
00122 const int f = (int)(sizeof(size_t)/8);
00123 int typenum = depth == CV_8U ? NPY_UBYTE : depth == CV_8S ? NPY_BYTE :
00124 depth == CV_16U ? NPY_USHORT : depth == CV_16S ? NPY_SHORT :
00125 depth == CV_32S ? NPY_INT : depth == CV_32F ? NPY_FLOAT :
00126 depth == CV_64F ? NPY_DOUBLE : f*NPY_ULONGLONG + (f^1)*NPY_UINT;
00127 int i, dims = dims0;
00128 cv::AutoBuffer<npy_intp> _sizes(dims + 1);
00129 for( i = 0; i < dims; i++ )
00130 _sizes[i] = sizes[i];
00131 if( cn > 1 )
00132 _sizes[dims++] = cn;
00133 PyObject* o = PyArray_SimpleNew(dims, _sizes, typenum);
00134 if(!o)
00135 CV_Error_(Error::StsError, ("The numpy array of typenum=%d, ndims=%d can not be created", typenum, dims));
00136 return allocate(o, dims0, sizes, type, step);
00137 }
00138
00139 bool allocate(UMatData* u, int accessFlags, UMatUsageFlags usageFlags) const
00140 {
00141 return stdAllocator->allocate(u, accessFlags, usageFlags);
00142 }
00143
00144 void deallocate(UMatData* u) const
00145 {
00146 if(u)
00147 {
00148 PyEnsureGIL gil;
00149 PyObject* o = (PyObject*)u->userdata;
00150 Py_XDECREF(o);
00151 delete u;
00152 }
00153 }
00154
00155 const MatAllocator* stdAllocator;
00156 };
00157
00158 NumpyAllocator g_numpyAllocator;
00159
00160
00161 template<typename T> static
00162 bool pyopencv_to(PyObject* obj, T& p, const char* name = "<unknown>");
00163
00164 template<typename T> static
00165 PyObject* pyopencv_from(const T& src);
00166
00167 enum { ARG_NONE = 0, ARG_MAT = 1, ARG_SCALAR = 2 };
00168
00169
00170 static bool pyopencv_to(PyObject* o, Mat& m, const ArgInfo info)
00171 {
00172
00173 do_numpy_import( );
00174
00175
00176 bool allowND = true;
00177 if(!o || o == Py_None)
00178 {
00179 if( !m.data )
00180 m.allocator = &g_numpyAllocator;
00181 return true;
00182 }
00183
00184 if( PyInt_Check(o) )
00185 {
00186 double v[] = {(double)PyInt_AsLong((PyObject*)o), 0., 0., 0.};
00187 m = Mat(4, 1, CV_64F, v).clone();
00188 return true;
00189 }
00190 if( PyFloat_Check(o) )
00191 {
00192 double v[] = {PyFloat_AsDouble((PyObject*)o), 0., 0., 0.};
00193 m = Mat(4, 1, CV_64F, v).clone();
00194 return true;
00195 }
00196 if( PyTuple_Check(o) )
00197 {
00198 int i, sz = (int)PyTuple_Size((PyObject*)o);
00199 m = Mat(sz, 1, CV_64F);
00200 for( i = 0; i < sz; i++ )
00201 {
00202 PyObject* oi = PyTuple_GET_ITEM(o, i);
00203 if( PyInt_Check(oi) )
00204 m.at<double>(i) = (double)PyInt_AsLong(oi);
00205 else if( PyFloat_Check(oi) )
00206 m.at<double>(i) = (double)PyFloat_AsDouble(oi);
00207 else
00208 {
00209 failmsg("%s is not a numerical tuple", info.name);
00210 m.release();
00211 return false;
00212 }
00213 }
00214 return true;
00215 }
00216
00217 if( !PyArray_Check(o) )
00218 {
00219 failmsg("%s is not a numpy array, neither a scalar", info.name);
00220 return false;
00221 }
00222
00223 PyArrayObject* oarr = (PyArrayObject*) o;
00224
00225 bool needcopy = false, needcast = false;
00226 int typenum = PyArray_TYPE(oarr), new_typenum = typenum;
00227 int type = typenum == NPY_UBYTE ? CV_8U :
00228 typenum == NPY_BYTE ? CV_8S :
00229 typenum == NPY_USHORT ? CV_16U :
00230 typenum == NPY_SHORT ? CV_16S :
00231 typenum == NPY_INT ? CV_32S :
00232 typenum == NPY_INT32 ? CV_32S :
00233 typenum == NPY_FLOAT ? CV_32F :
00234 typenum == NPY_DOUBLE ? CV_64F : -1;
00235
00236 if( type < 0 )
00237 {
00238 if( typenum == NPY_INT64 || typenum == NPY_UINT64 || type == NPY_LONG )
00239 {
00240 needcopy = needcast = true;
00241 new_typenum = NPY_INT;
00242 type = CV_32S;
00243 }
00244 else
00245 {
00246 failmsg("%s data type = %d is not supported", info.name, typenum);
00247 return false;
00248 }
00249 }
00250
00251 #ifndef CV_MAX_DIM
00252 const int CV_MAX_DIM = 32;
00253 #endif
00254
00255 int ndims = PyArray_NDIM(oarr);
00256 if(ndims >= CV_MAX_DIM)
00257 {
00258 failmsg("%s dimensionality (=%d) is too high", info.name, ndims);
00259 return false;
00260 }
00261
00262 int size[CV_MAX_DIM+1];
00263 size_t step[CV_MAX_DIM+1];
00264 size_t elemsize = CV_ELEM_SIZE1(type);
00265 const npy_intp* _sizes = PyArray_DIMS(oarr);
00266 const npy_intp* _strides = PyArray_STRIDES(oarr);
00267 bool ismultichannel = ndims == 3 && _sizes[2] <= CV_CN_MAX;
00268
00269 for( int i = ndims-1; i >= 0 && !needcopy; i-- )
00270 {
00271
00272
00273
00274
00275 if( (i == ndims-1 && (size_t)_strides[i] != elemsize) ||
00276 (i < ndims-1 && _strides[i] < _strides[i+1]) )
00277 needcopy = true;
00278 }
00279
00280 if( ismultichannel && _strides[1] != (npy_intp)elemsize*_sizes[2] )
00281 needcopy = true;
00282
00283 if (needcopy)
00284 {
00285 if (info.outputarg)
00286 {
00287 failmsg("Layout of the output array %s is incompatible with cv::Mat (step[ndims-1] != elemsize or step[1] != elemsize*nchannels)", info.name);
00288 return false;
00289 }
00290
00291 if( needcast ) {
00292 o = PyArray_Cast(oarr, new_typenum);
00293 oarr = (PyArrayObject*) o;
00294 }
00295 else {
00296 oarr = PyArray_GETCONTIGUOUS(oarr);
00297 o = (PyObject*) oarr;
00298 }
00299
00300 _strides = PyArray_STRIDES(oarr);
00301 }
00302
00303 for(int i = 0; i < ndims; i++)
00304 {
00305 size[i] = (int)_sizes[i];
00306 step[i] = (size_t)_strides[i];
00307 }
00308
00309
00310 if( ndims == 0) {
00311 size[ndims] = 1;
00312 step[ndims] = elemsize;
00313 ndims++;
00314 }
00315
00316 if( ismultichannel )
00317 {
00318 ndims--;
00319 type |= CV_MAKETYPE(0, size[2]);
00320 }
00321
00322 if( ndims > 2 && !allowND )
00323 {
00324 failmsg("%s has more than 2 dimensions", info.name);
00325 return false;
00326 }
00327
00328 m = Mat(ndims, size, type, PyArray_DATA(oarr), step);
00329 m.u = g_numpyAllocator.allocate(o, ndims, size, type, step);
00330 m.addref();
00331
00332 if( !needcopy )
00333 {
00334 Py_INCREF(o);
00335 }
00336 m.allocator = &g_numpyAllocator;
00337
00338 return true;
00339 }
00340
00341 template<>
00342 bool pyopencv_to(PyObject* o, Mat& m, const char* name)
00343 {
00344 return pyopencv_to(o, m, ArgInfo(name, 0));
00345 }
00346
00347 PyObject* pyopencv_from(const Mat& m)
00348 {
00349 if( !m.data )
00350 Py_RETURN_NONE;
00351 Mat temp, *p = (Mat*)&m;
00352 if(!p->u || p->allocator != &g_numpyAllocator)
00353 {
00354 temp.allocator = &g_numpyAllocator;
00355 ERRWRAP2(m.copyTo(temp));
00356 p = &temp;
00357 }
00358 PyObject* o = (PyObject*)p->u->userdata;
00359 Py_INCREF(o);
00360 return o;
00361 }
00362
00363 int convert_to_CvMat2(const PyObject* o, cv::Mat& m)
00364 {
00365 pyopencv_to(const_cast<PyObject*>(o), m, "unknown");
00366 return 0;
00367 }