module_opencv3.cpp
Go to the documentation of this file.
00001 // Taken from opencv/modules/python/src2/cv2.cpp
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     // more fields may be added if necessary
00031 
00032     ArgInfo(const char * name_, bool outputarg_)
00033         : name(name_)
00034         , outputarg(outputarg_) {}
00035 
00036     // to match with older pyopencv_to function signature
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             // probably this is safe to do in such extreme case
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 // special case, when the convertor needs full ArgInfo structure
00170 static bool pyopencv_to(PyObject* o, Mat& m, const ArgInfo info)
00171 {
00172       // to avoid PyArray_Check() to crash even with valid array
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         // these checks handle cases of
00272         //  a) multi-dimensional (ndims > 2) arrays, as well as simpler 1- and 2-dimensional cases
00273         //  b) transposed arrays, where _strides[] elements go in non-descending order
00274         //  c) flipped arrays, where some of _strides[] elements are negative
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     // handle degenerate case
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 }


cv_bridge
Author(s): Patrick Mihelich, James Bowman
autogenerated on Thu Jun 6 2019 21:23:27