Update to 2.0.0 tree from current Fremantle build
[opencv] / interfaces / swig / python / pyhelpers.i
index 75ff68e..169f92c 100644 (file)
@@ -1,71 +1,72 @@
 /* These functions need the SWIG_* functions defined in the wrapper */
 %{
 
+#include "pyhelpers.h"
+
 static CvArr * PyObject_to_CvArr(PyObject * obj, bool * freearg);
-static CvArr * PySequence_to_CvArr( PyObject * obj );
 
 // convert a python sequence/array/list object into a c-array
 #define PyObject_AsArrayImpl(func, ctype, ptype)                              \
-       int func(PyObject * obj, ctype * array, int len){                         \
-       void * mat_vptr=NULL;                                                     \
-       void * im_vptr=NULL;                                                      \
-       if(PyNumber_Check(obj)){                                                  \
-               memset( array, 0, sizeof(ctype)*len );                                \
-               array[0] = PyObject_As##ptype( obj );                                 \
-       }                                                                         \
-       else if(PyList_Check(obj) || PyTuple_Check(obj)){                         \
-               int seqsize = PySequence_Size(obj);                                   \
-               for(int i=0; i<len && i<seqsize; i++){                                \
-                       if(i<seqsize){                                                    \
-                   array[i] =  PyObject_As##ptype( PySequence_GetItem(obj, i) ); \
-                       }                                                                 \
-                       else{                                                             \
-                               array[i] = 0;                                                 \
-                       }                                                                 \
-               }                                                                     \
-       }                                                                         \
-       else if( SWIG_ConvertPtr(obj, &mat_vptr, SWIGTYPE_p_CvMat, 0)!=-1 ||      \
-                SWIG_ConvertPtr(obj, &im_vptr, SWIGTYPE_p__IplImage, 0)!=-1)     \
-       {                                                                         \
-               CvMat * mat = (CvMat *) mat_vptr;                                     \
-               CvMat stub;                                                           \
-               if(im_vptr) mat = cvGetMat(im_vptr, &stub);                           \
-               if( mat->rows!=1 && mat->cols!=1 ){                                   \
-                       PyErr_SetString( PyExc_TypeError,                                 \
-                            "PyObject_As*Array: CvArr must be row or column vector" );   \
-                       return -1;                                                        \
-               }                                                                     \
-               if( mat->rows==1 && mat->cols==1 ){                                   \
-                       CvScalar val;                                                     \
-                       if( len!=CV_MAT_CN(mat->type) ){                                  \
-                               PyErr_SetString( PyExc_TypeError,                             \
-                               "PyObject_As*Array: CvArr channels != length" );              \
-                               return -1;                                                    \
-                       }                                                                 \
-                       val = cvGet1D(mat, 0);                                            \
-                       for(int i=0; i<len; i++){                                         \
-                               array[i] = (ctype) val.val[i];                                \
-                       }                                                                 \
-               }                                                                     \
-               else{                                                                 \
-                       mat = cvReshape(mat, &stub, -1, mat->rows*mat->cols);             \
-                       if( mat->rows != len ){                                           \
-                               PyErr_SetString( PyExc_TypeError,                             \
-                                "PyObject_As*Array: CvArr rows or cols must equal length" ); \
-                                return -1;                                                   \
-                       }                                                                 \
-                       for(int i=0; i<len; i++){                                         \
-                               CvScalar val = cvGet1D(mat, i);                               \
-                               array[i] = (ctype) val.val[0];                                \
-                       }                                                                 \
-               }                                                                     \
-       }                                                                         \
-       else{                                                                     \
-               PyErr_SetString( PyExc_TypeError,                                     \
-                               "PyObject_As*Array: Expected a number, sequence or CvArr" );  \
-               return -1;                                                            \
-       }                                                                         \
-       return 0;                                                                 \
+  int func(PyObject * obj, ctype * array, int len){                         \
+  void * mat_vptr=NULL;                                                     \
+  void * im_vptr=NULL;                                                      \
+  if(PyNumber_Check(obj)){                                                  \
+    memset( array, 0, sizeof(ctype)*len );                                \
+    array[0] = PyObject_As##ptype( obj );                                 \
+  }                                                                         \
+  else if(PyList_Check(obj) || PyTuple_Check(obj)){                         \
+    int seqsize = PySequence_Size(obj);                                   \
+    for(int i=0; i<len && i<seqsize; i++){                                \
+      if(i<seqsize){                                                    \
+              array[i] =  PyObject_As##ptype( PySequence_GetItem(obj, i) ); \
+      }                                                                 \
+      else{                                                             \
+        array[i] = 0;                                                 \
+      }                                                                 \
+    }                                                                     \
+  }                                                                         \
+  else if( SWIG_ConvertPtr(obj, &mat_vptr, SWIGTYPE_p_CvMat, 0)!=-1 ||      \
+           SWIG_ConvertPtr(obj, &im_vptr, SWIGTYPE_p__IplImage, 0)!=-1)     \
+  {                                                                         \
+    CvMat * mat = (CvMat *) mat_vptr;                                     \
+    CvMat stub;                                                           \
+    if(im_vptr) mat = cvGetMat(im_vptr, &stub);                           \
+    if( mat->rows!=1 && mat->cols!=1 ){                                   \
+      PyErr_SetString( PyExc_TypeError,                                 \
+           "PyObject_As*Array: CvArr must be row or column vector" );   \
+      return -1;                                                        \
+    }                                                                     \
+    if( mat->rows==1 && mat->cols==1 ){                                   \
+      CvScalar val;                                                     \
+      if( len!=CV_MAT_CN(mat->type) ){                                  \
+        PyErr_SetString( PyExc_TypeError,                             \
+        "PyObject_As*Array: CvArr channels != length" );              \
+        return -1;                                                    \
+      }                                                                 \
+      val = cvGet1D(mat, 0);                                            \
+      for(int i=0; i<len; i++){                                         \
+        array[i] = (ctype) val.val[i];                                \
+      }                                                                 \
+    }                                                                     \
+    else{                                                                 \
+      mat = cvReshape(mat, &stub, -1, mat->rows*mat->cols);             \
+      if( mat->rows != len ){                                           \
+        PyErr_SetString( PyExc_TypeError,                             \
+         "PyObject_As*Array: CvArr rows or cols must equal length" ); \
+         return -1;                                                   \
+      }                                                                 \
+      for(int i=0; i<len; i++){                                         \
+        CvScalar val = cvGet1D(mat, i);                               \
+        array[i] = (ctype) val.val[0];                                \
+      }                                                                 \
+    }                                                                     \
+  }                                                                         \
+  else{                                                                     \
+    PyErr_SetString( PyExc_TypeError,                                     \
+        "PyObject_As*Array: Expected a number, sequence or CvArr" );  \
+    return -1;                                                            \
+  }                                                                         \
+  return 0;                                                                 \
 }
 
 PyObject_AsArrayImpl( PyObject_AsFloatArray, float, Double );
@@ -73,181 +74,166 @@ PyObject_AsArrayImpl( PyObject_AsDoubleArray, double, Double );
 PyObject_AsArrayImpl( PyObject_AsLongArray, int, Long );
 
 static CvPoint PyObject_to_CvPoint(PyObject * obj){
-       CvPoint val;
-       CvPoint *ptr;
-       CvPoint2D32f * ptr2D32f;
-       CvScalar * scalar;
-
-       if( SWIG_ConvertPtr(obj, (void**)&ptr, SWIGTYPE_p_CvPoint, 0) != -1) {
-               return *ptr;
-       }
-       if( SWIG_ConvertPtr(obj, (void**)&ptr2D32f, SWIGTYPE_p_CvPoint2D32f, 0) != -1) {
-               return cvPointFrom32f( *ptr2D32f );
-       }
-       if( SWIG_ConvertPtr(obj, (void**)&scalar, SWIGTYPE_p_CvScalar, 0) != -1) {
-               return cvPointFrom32f(cvPoint2D32f( scalar->val[0], scalar->val[1] ));
-       }
-       if(PyObject_AsLongArray(obj, (int *) &val, 2) != -1){
-               return val;
-       }
-
-       PyErr_SetString( PyExc_TypeError, "could not convert to CvPoint");
-       return cvPoint(0,0);
+  CvPoint val;
+  CvPoint *ptr;
+  CvPoint2D32f * ptr2D32f;
+  CvScalar * scalar;
+
+  if( SWIG_ConvertPtr(obj, (void**)&ptr, SWIGTYPE_p_CvPoint, 0) != -1) {
+    return *ptr;
+  }
+  if( SWIG_ConvertPtr(obj, (void**)&ptr2D32f, SWIGTYPE_p_CvPoint2D32f, 0) != -1) {
+    return cvPointFrom32f( *ptr2D32f );
+  }
+  if( SWIG_ConvertPtr(obj, (void**)&scalar, SWIGTYPE_p_CvScalar, 0) != -1) {
+    return cvPointFrom32f(cvPoint2D32f( scalar->val[0], scalar->val[1] ));
+  }
+  if(PyObject_AsLongArray(obj, (int *) &val, 2) != -1){
+    return val;
+  }
+
+  PyErr_SetString( PyExc_TypeError, "could not convert to CvPoint");
+  return cvPoint(0,0);
 }
 
 static CvPoint2D32f PyObject_to_CvPoint2D32f(PyObject * obj){
     CvPoint2D32f val;
     CvPoint2D32f *ptr2D32f;
-       CvPoint *ptr;
-       CvScalar * scalar;
+  CvPoint *ptr;
+  CvScalar * scalar;
     if( SWIG_ConvertPtr(obj, (void**)&ptr2D32f, SWIGTYPE_p_CvPoint2D32f, 0) != -1) {
-               return *ptr2D32f;
-       }
-       if( SWIG_ConvertPtr(obj, (void**)&ptr, SWIGTYPE_p_CvPoint, 0) != -1) {
-               return cvPointTo32f(*ptr);
-       }
-       if( SWIG_ConvertPtr(obj, (void**)&scalar, SWIGTYPE_p_CvScalar, 0) != -1) {
-               return cvPoint2D32f( scalar->val[0], scalar->val[1] );
-       }
-       if(PyObject_AsFloatArray(obj, (float *) &val, 2) != -1){
-               return val;
-       }
-       PyErr_SetString(PyExc_TypeError, "could not convert to CvPoint2D32f");
-       return cvPoint2D32f(0,0);
+    return *ptr2D32f;
+  }
+  if( SWIG_ConvertPtr(obj, (void**)&ptr, SWIGTYPE_p_CvPoint, 0) != -1) {
+    return cvPointTo32f(*ptr);
+  }
+  if( SWIG_ConvertPtr(obj, (void**)&scalar, SWIGTYPE_p_CvScalar, 0) != -1) {
+    return cvPoint2D32f( scalar->val[0], scalar->val[1] );
+  }
+  if(PyObject_AsFloatArray(obj, (float *) &val, 2) != -1){
+    return val;
+  }
+  PyErr_SetString(PyExc_TypeError, "could not convert to CvPoint2D32f");
+  return cvPoint2D32f(0,0);
 }
 
 /* Check if this object can be interpreted as a CvScalar */
 static bool CvScalar_Check(PyObject * obj){
-       void * vptr;
+  void * vptr;
     CvScalar val;
-       return SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvScalar,     0 ) != -1 ||
-              SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint2D32f, 0 ) != -1 ||
+  return SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvScalar,     0 ) != -1 ||
+         SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint2D32f, 0 ) != -1 ||
            SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint,      0 ) != -1 ||
-              PyObject_AsDoubleArray(obj, val.val, 4) !=-1;
+         PyObject_AsDoubleArray(obj, val.val, 4) !=-1;
 }
 
 static CvScalar PyObject_to_CvScalar(PyObject * obj){
-       CvScalar val;
-       CvScalar * ptr;
+  CvScalar val;
+  CvScalar * ptr;
     CvPoint2D32f *ptr2D32f;
-       CvPoint *pt_ptr;
-       void * vptr;
-       if( SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvScalar, 0 ) != -1)
-       {
-               ptr = (CvScalar *) vptr;
-               return *ptr;
-       }
-       if( SWIG_ConvertPtr(obj, (void**)&ptr2D32f, SWIGTYPE_p_CvPoint2D32f, 0) != -1) {
+  CvPoint *pt_ptr;
+  void * vptr;
+  if( SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvScalar, 0 ) != -1)
+  {
+    ptr = (CvScalar *) vptr;
+    return *ptr;
+  }
+  if( SWIG_ConvertPtr(obj, (void**)&ptr2D32f, SWIGTYPE_p_CvPoint2D32f, 0) != -1) {
         return cvScalar(ptr2D32f->x, ptr2D32f->y);
     }
     if( SWIG_ConvertPtr(obj, (void**)&pt_ptr, SWIGTYPE_p_CvPoint, 0) != -1) {
         return cvScalar(pt_ptr->x, pt_ptr->y);
     }
-       if(PyObject_AsDoubleArray(obj, val.val, 4)!=-1){
-               return val;
-       }
-       return cvScalar(-1,-1,-1,-1); 
+  if(PyObject_AsDoubleArray(obj, val.val, 4)!=-1){
+    return val;
+  }
+  return cvScalar(-1,-1,-1,-1); 
 }
 
-/* if python sequence type, convert to CvMat or CvMatND */
-static CvArr * PyObject_to_CvArr(PyObject * obj, bool * freearg){
-       CvArr * cvarr;
-       *freearg = false;
-
-       // check if OpenCV type
-       if( PySwigObject_Check(obj) ){
-               SWIG_ConvertPtr(obj, &cvarr, 0, SWIG_POINTER_EXCEPTION);
-       }
-       else if(PyList_Check(obj) || PyTuple_Check(obj)){
-               cvarr = PySequence_to_CvArr( obj );
-               *freearg = (cvarr != NULL);
-       }
-       else if(PyLong_Check(obj) && PyLong_AsLong(obj)==0){
-               return NULL;
-       }
-       else {
-               SWIG_ConvertPtr(obj, (void**)&cvarr, 0, SWIG_POINTER_EXCEPTION);
-       }
-       return cvarr;
+static int CvArr_Check( PyObject * obj )
+{
+       void *ptr;
+       if( obj == Py_None ||
+           SWIG_IsOK( SWIG_ConvertPtr(obj, &ptr, SWIGTYPE_p_void,       0) ) ||
+           SWIG_IsOK( SWIG_ConvertPtr(obj, &ptr, SWIGTYPE_p_CvMat,       0) ) ||
+        SWIG_IsOK( SWIG_ConvertPtr(obj, &ptr, SWIGTYPE_p_CvSeq,       0) ) ||
+        SWIG_IsOK( SWIG_ConvertPtr(obj, &ptr, SWIGTYPE_p_CvContour,   0) ) ||
+        SWIG_IsOK( SWIG_ConvertPtr(obj, &ptr, SWIGTYPE_p_CvSparseMat, 0) ) ||
+        SWIG_IsOK( SWIG_ConvertPtr(obj, &ptr, SWIGTYPE_p_CvMatND,     0) ) ||
+        PyObject_HasAttrString(obj, "__array_interface__") ||
+        PySequence_Check(obj) ) 
+    { 
+        return 1;
+       }
+    PyErr_Clear();
+    return 0;
 }
 
-static int PyObject_GetElemType(PyObject * obj){
-       void *vptr;
-       if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint, 0) != -1) return CV_32SC2;   
-       if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvSize, 0) != -1) return CV_32SC2;    
-       if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvRect, 0) != -1) return CV_32SC4;    
-       if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvSize2D32f, 0) != -1) return CV_32FC2;       
-       if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint2D32f, 0) != -1) return CV_32FC2;      
-       if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint3D32f, 0) != -1) return CV_32FC3;      
-       if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint2D64f, 0) != -1) return CV_64FC2;      
-       if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint3D64f, 0) != -1) return CV_64FC3;      
-       if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvScalar, 0) != -1) return CV_64FC4;  
-       if(PyTuple_Check(obj) || PyList_Check(obj)) return CV_MAKE_TYPE(CV_32F, PySequence_Size( obj ));
-       if(PyLong_Check(obj)) return CV_32S;
-       return CV_32F;
+/* if python sequence type, convert to CvMat or CvMatND */
+static CvArr * PyObject_to_CvArr (PyObject * obj, bool * freearg)
+{
+  CvArr * cvarr = NULL;
+  *freearg = false;
+
+  if ( obj == Py_None )
+  {
+    // Interpret None as NULL pointer 
+    return NULL;
+  }
+  else if( SWIG_IsOK( SWIG_ConvertPtr(obj, (void **)& cvarr, SWIGTYPE_p_void,       0) ) ||
+      SWIG_IsOK( SWIG_ConvertPtr (obj, (void** )& cvarr, SWIGTYPE_p_CvMat, 0) ) ||
+      SWIG_IsOK( SWIG_ConvertPtr (obj, (void **)& cvarr, SWIGTYPE_p_CvSeq, 0) ) ||
+      SWIG_IsOK( SWIG_ConvertPtr (obj, (void **)& cvarr, SWIGTYPE_p_CvContour, 0) ) ||
+      SWIG_IsOK( SWIG_ConvertPtr (obj, (void **)& cvarr, SWIGTYPE_p_CvSparseMat, 0) ) ||
+      SWIG_IsOK( SWIG_ConvertPtr (obj, (void **)& cvarr, SWIGTYPE_p_CvMatND, 0) ))
+  {
+    // we got a directly wrapped void * pointer, OpenCV array or sequence type
+    return cvarr;
+  }
+  else if (PyObject_HasAttrString (obj, "__array_interface__"))
+  {
+    // if we didn't get our own datatype, let's see if it supports the array protocol
+    // array protocol is great because we just have to create another header but can
+    // use the original data without copying
+    cvarr = PyArray_to_CvArr (obj);
+    *freearg = (cvarr != NULL);
+  }
+  else if (PySequence_Check (obj))
+  {
+    // our next bet is a tuple or list of tuples or lists this has to be copied over, however
+    cvarr = PySequence_to_CvArr (obj);
+    *freearg = (cvarr != NULL);
+  }
+  else if (PyLong_Check (obj) && PyLong_AsLong (obj) == 0)
+  {
+    // Interpret a '0' integer as a NULL pointer
+    * freearg = false;
+    return NULL;
+  }
+  else 
+  {
+    // TODO, throw an error here
+    return NULL;
+  }
+  
+  return cvarr;
 }
 
-// Would like this to convert Python lists to CvMat
-// Also lists of CvPoints, CvScalars, CvMats? etc
-static CvArr * PySequence_to_CvArr( PyObject * obj ){
-       int dims[CV_MAX_DIM] = {1,1,1};
-       int ndim=0;
-       int cvtype;
-       PyObject * item;
-       
-       // figure out dimensions
-       for(item = obj; 
-               (PyTuple_Check(item) || PyList_Check(item));
-               item = PySequence_GetItem(item, 0))
-       {
-               dims[ndim] = PySequence_Size( item ); 
-               ndim++;
-       }
-
-       
-       if(ndim==0){
-               PyErr_SetString(PyExc_TypeError, "Cannot convert an empty python object to a CvArr");
-               return NULL;
-       }
-       
-       cvtype = PyObject_GetElemType(item);
-       // collapse last dim into NCH if we found a single channel, but the last dim is <=3
-       if(CV_MAT_CN(cvtype)==1 && dims[ndim-1]>1 && dims[ndim-1]<4){
-               cvtype=CV_MAKE_TYPE(cvtype, dims[ndim-1]);
-               dims[ndim-1]=1; 
-               ndim--;
-       }
-       
-       if(cvtype==-1){
-               PyErr_SetString(PyExc_TypeError, "Could not determine OpenCV element type of Python sequence");
-               return NULL;
-       }
-       
-       // CvMat
-       if(ndim<=2){
-               CvMat *m = cvCreateMat(dims[0], dims[1], cvtype);
-               for(int i=0; i<dims[0]; i++){
-                       PyObject * rowobj = PySequence_GetItem(obj, i);
-                       if( dims[1] > 1 ){
-                               // double check size
-                               assert((PyTuple_Check(rowobj) || PyList_Check(rowobj)) && 
-                                               PySequence_Size(rowobj) == dims[1]);
-
-                               for(int j=0; j<dims[1]; j++){
-                                       PyObject * colobj = PySequence_GetItem(rowobj, j);
-                                       cvSet2D( m, i, j, PyObject_to_CvScalar( colobj ) );
-                               }
-                       }
-                       else{
-                               cvSet1D(m, i, PyObject_to_CvScalar( rowobj ) );
-                       }
-               }
-               return (CvArr *) m;
-       }
 
-       // CvMatND
-       PyErr_SetString(PyExc_TypeError, "Cannot convert Python Object to CvArr -- ndim > 3");
-       return NULL;
-       
+static int PyObject_GetElemType(PyObject * obj){
+  void *vptr;
+  if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint, 0) != -1) return CV_32SC2; 
+  if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvSize, 0) != -1) return CV_32SC2;  
+  if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvRect, 0) != -1) return CV_32SC4;  
+  if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvSize2D32f, 0) != -1) return CV_32FC2; 
+  if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint2D32f, 0) != -1) return CV_32FC2;  
+  if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint3D32f, 0) != -1) return CV_32FC3;  
+  if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint2D64f, 0) != -1) return CV_64FC2;  
+  if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint3D64f, 0) != -1) return CV_64FC3;  
+  if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvScalar, 0) != -1) return CV_64FC4;  
+  if(PyTuple_Check(obj) || PyList_Check(obj)) return CV_MAKE_TYPE(CV_32F, PySequence_Size( obj ));
+  if(PyLong_Check(obj)) return CV_32S;
+  return CV_32F;
 }
+
 %}