Go to the documentation of this file.00001 #include <boost/python.hpp>
00002 #include <numpy/arrayobject.h>
00003 #include <complex>
00004 #include <algorithm>
00005
00006 #include <opencv2/core/core.hpp>
00007 #include <pano_py/opencv.h>
00008
00009 using namespace cv;
00010
00011 namespace{
00012
00013 static size_t REFCOUNT_OFFSET = (size_t)&(((PyObject*)0)->ob_refcnt) +
00014 (0x12345678 != *(const size_t*)"\x78\x56\x34\x12\0\0\0\0\0")*sizeof(int);
00015
00016 static inline PyObject* pyObjectFromRefcount(const int* refcount)
00017 {
00018 return (PyObject*)((size_t)refcount - REFCOUNT_OFFSET);
00019 }
00020
00021 static inline int* refcountFromPyObject(const PyObject* obj)
00022 {
00023 return (int*)((size_t)obj + REFCOUNT_OFFSET);
00024 }
00025
00026 class NumpyAllocator : public MatAllocator
00027 {
00028 public:
00029 NumpyAllocator(){}
00030 ~NumpyAllocator() {}
00031
00032 void allocate(int dims, const int* sizes, int type, int*& refcount,
00033 uchar*& datastart, uchar*& data, size_t* step)
00034 {
00035 int depth = CV_MAT_DEPTH(type);
00036 int cn = CV_MAT_CN(type);
00037 const int f = (int)(sizeof(size_t)/8);
00038 int typenum = depth == CV_8U ? NPY_UBYTE : depth == CV_8S ? NPY_BYTE :
00039 depth == CV_16U ? NPY_USHORT : depth == CV_16S ? NPY_SHORT :
00040 depth == CV_32S ? NPY_INT : depth == CV_32F ? NPY_FLOAT :
00041 depth == CV_64F ? NPY_DOUBLE : f*NPY_ULONGLONG + (f^1)*NPY_UINT;
00042
00043 npy_intp _sizes[CV_MAX_DIM+1];
00044 for( int i = 0; i < dims; i++ )
00045 _sizes[i] = sizes[i];
00046 if( cn > 1 ) {
00047 if( _sizes[dims-1] == 1 )
00048 _sizes[dims-1] = cn;
00049 else
00050 _sizes[dims++] = cn;
00051 }
00052
00053 PyObject* o = PyArray_SimpleNew(dims, _sizes, typenum);
00054 if(!o)
00055 CV_Error_(CV_StsError, ("The numpy array of typenum=%d, ndims=%d can not be created", typenum, dims));
00056 refcount = refcountFromPyObject(o);
00057 npy_intp* _strides = PyArray_STRIDES(o);
00058 for(int i = 0; i < dims - (cn > 1); i++ )
00059 step[i] = (size_t)_strides[i];
00060 datastart = data = (uchar*)PyArray_DATA(o);
00061 }
00062
00063 void deallocate(int* refcount, uchar* datastart, uchar* data)
00064 {
00065 if( !refcount )
00066 return;
00067 PyObject* o = pyObjectFromRefcount(refcount);
00068 Py_INCREF(o);
00069 Py_DECREF(o);
00070 }
00071 };
00072
00073 NumpyAllocator g_numpyAllocator;
00074
00075 }
00076
00077 namespace pano_py{
00078
00079 bool numpy_to_mat(const PyObject* o, cv::Mat& m, const char* name, bool allowND)
00080 {
00081 if(!o || o == Py_None)
00082 {
00083 if( !m.data )
00084 m.allocator = &g_numpyAllocator;
00085 return true;
00086 }
00087 if( !PyArray_Check(o) )
00088 {
00089 failmsg("%s is not a numpy array", name);
00090 return false;
00091 }
00092 int typenum = PyArray_TYPE(o);
00093 int type = typenum == NPY_UBYTE ? CV_8U : typenum == NPY_BYTE ? CV_8S :
00094 typenum == NPY_USHORT ? CV_16U : typenum == NPY_SHORT ? CV_16S :
00095 typenum == NPY_INT || typenum == NPY_LONG ? CV_32S :
00096 typenum == NPY_FLOAT ? CV_32F :
00097 typenum == NPY_DOUBLE ? CV_64F : -1;
00098
00099 if( type < 0 )
00100 {
00101 failmsg("%s data type = %d is not supported", name, typenum);
00102 return false;
00103 }
00104
00105 int ndims = PyArray_NDIM(o);
00106 if(ndims >= CV_MAX_DIM)
00107 {
00108 failmsg("%s dimensionality (=%d) is too high", name, ndims);
00109 return false;
00110 }
00111
00112 int size[CV_MAX_DIM+1];
00113 size_t step[CV_MAX_DIM+1], elemsize = CV_ELEM_SIZE1(type);
00114 const npy_intp* _sizes = PyArray_DIMS(o);
00115 const npy_intp* _strides = PyArray_STRIDES(o);
00116
00117 for(int i = 0; i < ndims; i++)
00118 {
00119 size[i] = (int)_sizes[i];
00120 step[i] = (size_t)_strides[i];
00121 }
00122
00123 if( ndims == 0 || step[ndims-1] > elemsize ) {
00124 size[ndims] = 1;
00125 step[ndims] = elemsize;
00126 ndims++;
00127 }
00128
00129 if( ndims == 3 && size[2] <= CV_CN_MAX && step[1] == elemsize*size[2] )
00130 {
00131 ndims--;
00132 type |= CV_MAKETYPE(0, size[2]);
00133 }
00134
00135 if( ndims > 2 && !allowND )
00136 {
00137 failmsg("%s has more than 2 dimensions", name);
00138 return false;
00139 }
00140
00141 m = Mat(ndims, size, type, PyArray_DATA(o), step);
00142
00143 if( m.data )
00144 {
00145 m.refcount = refcountFromPyObject(o);
00146 m.addref();
00147
00148 };
00149 m.allocator = &g_numpyAllocator;
00150 return true;
00151 }
00152 }
00153