Update the trunk to the OpenCV's CVS (2008-07-14)
[opencv] / interfaces / swig / python / pyhelpers.i
1 /* These functions need the SWIG_* functions defined in the wrapper */
2 %{
3
4 static CvArr * PyObject_to_CvArr(PyObject * obj, bool * freearg);
5 static CvArr * PySequence_to_CvArr( PyObject * obj );
6
7 // convert a python sequence/array/list object into a c-array
8 #define PyObject_AsArrayImpl(func, ctype, ptype)                              \
9         int func(PyObject * obj, ctype * array, int len){                         \
10         void * mat_vptr=NULL;                                                     \
11         void * im_vptr=NULL;                                                      \
12         if(PyNumber_Check(obj)){                                                  \
13                 memset( array, 0, sizeof(ctype)*len );                                \
14                 array[0] = PyObject_As##ptype( obj );                                 \
15         }                                                                         \
16         else if(PyList_Check(obj) || PyTuple_Check(obj)){                         \
17                 int seqsize = PySequence_Size(obj);                                   \
18                 for(int i=0; i<len && i<seqsize; i++){                                \
19                         if(i<seqsize){                                                    \
20                     array[i] =  PyObject_As##ptype( PySequence_GetItem(obj, i) ); \
21                         }                                                                 \
22                         else{                                                             \
23                                 array[i] = 0;                                                 \
24                         }                                                                 \
25                 }                                                                     \
26         }                                                                         \
27         else if( SWIG_ConvertPtr(obj, &mat_vptr, SWIGTYPE_p_CvMat, 0)!=-1 ||      \
28                  SWIG_ConvertPtr(obj, &im_vptr, SWIGTYPE_p__IplImage, 0)!=-1)     \
29         {                                                                         \
30                 CvMat * mat = (CvMat *) mat_vptr;                                     \
31                 CvMat stub;                                                           \
32                 if(im_vptr) mat = cvGetMat(im_vptr, &stub);                           \
33                 if( mat->rows!=1 && mat->cols!=1 ){                                   \
34                         PyErr_SetString( PyExc_TypeError,                                 \
35                              "PyObject_As*Array: CvArr must be row or column vector" );   \
36                         return -1;                                                        \
37                 }                                                                     \
38                 if( mat->rows==1 && mat->cols==1 ){                                   \
39                         CvScalar val;                                                     \
40                         if( len!=CV_MAT_CN(mat->type) ){                                  \
41                                 PyErr_SetString( PyExc_TypeError,                             \
42                                 "PyObject_As*Array: CvArr channels != length" );              \
43                                 return -1;                                                    \
44                         }                                                                 \
45                         val = cvGet1D(mat, 0);                                            \
46                         for(int i=0; i<len; i++){                                         \
47                                 array[i] = (ctype) val.val[i];                                \
48                         }                                                                 \
49                 }                                                                     \
50                 else{                                                                 \
51                         mat = cvReshape(mat, &stub, -1, mat->rows*mat->cols);             \
52                         if( mat->rows != len ){                                           \
53                                 PyErr_SetString( PyExc_TypeError,                             \
54                                  "PyObject_As*Array: CvArr rows or cols must equal length" ); \
55                                  return -1;                                                   \
56                         }                                                                 \
57                         for(int i=0; i<len; i++){                                         \
58                                 CvScalar val = cvGet1D(mat, i);                               \
59                                 array[i] = (ctype) val.val[0];                                \
60                         }                                                                 \
61                 }                                                                     \
62         }                                                                         \
63         else{                                                                     \
64                 PyErr_SetString( PyExc_TypeError,                                     \
65                                 "PyObject_As*Array: Expected a number, sequence or CvArr" );  \
66                 return -1;                                                            \
67         }                                                                         \
68         return 0;                                                                 \
69 }
70
71 PyObject_AsArrayImpl( PyObject_AsFloatArray, float, Double );
72 PyObject_AsArrayImpl( PyObject_AsDoubleArray, double, Double );
73 PyObject_AsArrayImpl( PyObject_AsLongArray, int, Long );
74
75 static CvPoint PyObject_to_CvPoint(PyObject * obj){
76         CvPoint val;
77         CvPoint *ptr;
78         CvPoint2D32f * ptr2D32f;
79         CvScalar * scalar;
80
81         if( SWIG_ConvertPtr(obj, (void**)&ptr, SWIGTYPE_p_CvPoint, 0) != -1) {
82                 return *ptr;
83         }
84         if( SWIG_ConvertPtr(obj, (void**)&ptr2D32f, SWIGTYPE_p_CvPoint2D32f, 0) != -1) {
85                 return cvPointFrom32f( *ptr2D32f );
86         }
87         if( SWIG_ConvertPtr(obj, (void**)&scalar, SWIGTYPE_p_CvScalar, 0) != -1) {
88                 return cvPointFrom32f(cvPoint2D32f( scalar->val[0], scalar->val[1] ));
89         }
90         if(PyObject_AsLongArray(obj, (int *) &val, 2) != -1){
91                 return val;
92         }
93
94         PyErr_SetString( PyExc_TypeError, "could not convert to CvPoint");
95         return cvPoint(0,0);
96 }
97
98 static CvPoint2D32f PyObject_to_CvPoint2D32f(PyObject * obj){
99     CvPoint2D32f val;
100     CvPoint2D32f *ptr2D32f;
101         CvPoint *ptr;
102         CvScalar * scalar;
103     if( SWIG_ConvertPtr(obj, (void**)&ptr2D32f, SWIGTYPE_p_CvPoint2D32f, 0) != -1) {
104                 return *ptr2D32f;
105         }
106         if( SWIG_ConvertPtr(obj, (void**)&ptr, SWIGTYPE_p_CvPoint, 0) != -1) {
107                 return cvPointTo32f(*ptr);
108         }
109         if( SWIG_ConvertPtr(obj, (void**)&scalar, SWIGTYPE_p_CvScalar, 0) != -1) {
110                 return cvPoint2D32f( scalar->val[0], scalar->val[1] );
111         }
112         if(PyObject_AsFloatArray(obj, (float *) &val, 2) != -1){
113                 return val;
114         }
115         PyErr_SetString(PyExc_TypeError, "could not convert to CvPoint2D32f");
116         return cvPoint2D32f(0,0);
117 }
118
119 /* Check if this object can be interpreted as a CvScalar */
120 static bool CvScalar_Check(PyObject * obj){
121         void * vptr;
122     CvScalar val;
123         return SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvScalar,     0 ) != -1 ||
124                SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint2D32f, 0 ) != -1 ||
125            SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint,      0 ) != -1 ||
126                PyObject_AsDoubleArray(obj, val.val, 4) !=-1;
127 }
128
129 static CvScalar PyObject_to_CvScalar(PyObject * obj){
130         CvScalar val;
131         CvScalar * ptr;
132     CvPoint2D32f *ptr2D32f;
133         CvPoint *pt_ptr;
134         void * vptr;
135         if( SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvScalar, 0 ) != -1)
136         {
137                 ptr = (CvScalar *) vptr;
138                 return *ptr;
139         }
140         if( SWIG_ConvertPtr(obj, (void**)&ptr2D32f, SWIGTYPE_p_CvPoint2D32f, 0) != -1) {
141         return cvScalar(ptr2D32f->x, ptr2D32f->y);
142     }
143     if( SWIG_ConvertPtr(obj, (void**)&pt_ptr, SWIGTYPE_p_CvPoint, 0) != -1) {
144         return cvScalar(pt_ptr->x, pt_ptr->y);
145     }
146         if(PyObject_AsDoubleArray(obj, val.val, 4)!=-1){
147                 return val;
148         }
149         return cvScalar(-1,-1,-1,-1); 
150 }
151
152 /* if python sequence type, convert to CvMat or CvMatND */
153 static CvArr * PyObject_to_CvArr(PyObject * obj, bool * freearg){
154         CvArr * cvarr;
155         *freearg = false;
156
157         // check if OpenCV type
158         if( PySwigObject_Check(obj) ){
159                 SWIG_ConvertPtr(obj, &cvarr, 0, SWIG_POINTER_EXCEPTION);
160         }
161         else if(PyList_Check(obj) || PyTuple_Check(obj)){
162                 cvarr = PySequence_to_CvArr( obj );
163                 *freearg = (cvarr != NULL);
164         }
165         else if(PyLong_Check(obj) && PyLong_AsLong(obj)==0){
166                 return NULL;
167         }
168         else {
169                 SWIG_ConvertPtr(obj, (void**)&cvarr, 0, SWIG_POINTER_EXCEPTION);
170         }
171         return cvarr;
172 }
173
174 static int PyObject_GetElemType(PyObject * obj){
175         void *vptr;
176         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint, 0) != -1) return CV_32SC2;   
177         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvSize, 0) != -1) return CV_32SC2;    
178         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvRect, 0) != -1) return CV_32SC4;    
179         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvSize2D32f, 0) != -1) return CV_32FC2;       
180         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint2D32f, 0) != -1) return CV_32FC2;      
181         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint3D32f, 0) != -1) return CV_32FC3;      
182         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint2D64f, 0) != -1) return CV_64FC2;      
183         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint3D64f, 0) != -1) return CV_64FC3;      
184         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvScalar, 0) != -1) return CV_64FC4;  
185         if(PyTuple_Check(obj) || PyList_Check(obj)) return CV_MAKE_TYPE(CV_32F, PySequence_Size( obj ));
186         if(PyLong_Check(obj)) return CV_32S;
187         return CV_32F;
188 }
189
190 // Would like this to convert Python lists to CvMat
191 // Also lists of CvPoints, CvScalars, CvMats? etc
192 static CvArr * PySequence_to_CvArr( PyObject * obj ){
193         int dims[CV_MAX_DIM] = {1,1,1};
194         int ndim=0;
195         int cvtype;
196         PyObject * item;
197         
198         // figure out dimensions
199         for(item = obj; 
200                 (PyTuple_Check(item) || PyList_Check(item));
201                 item = PySequence_GetItem(item, 0))
202         {
203                 dims[ndim] = PySequence_Size( item ); 
204                 ndim++;
205         }
206
207         
208         if(ndim==0){
209                 PyErr_SetString(PyExc_TypeError, "Cannot convert an empty python object to a CvArr");
210                 return NULL;
211         }
212         
213         cvtype = PyObject_GetElemType(item);
214         // collapse last dim into NCH if we found a single channel, but the last dim is <=3
215         if(CV_MAT_CN(cvtype)==1 && dims[ndim-1]>1 && dims[ndim-1]<4){
216                 cvtype=CV_MAKE_TYPE(cvtype, dims[ndim-1]);
217                 dims[ndim-1]=1; 
218                 ndim--;
219         }
220         
221         if(cvtype==-1){
222                 PyErr_SetString(PyExc_TypeError, "Could not determine OpenCV element type of Python sequence");
223                 return NULL;
224         }
225         
226         // CvMat
227         if(ndim<=2){
228                 CvMat *m = cvCreateMat(dims[0], dims[1], cvtype);
229                 for(int i=0; i<dims[0]; i++){
230                         PyObject * rowobj = PySequence_GetItem(obj, i);
231                         if( dims[1] > 1 ){
232                                 // double check size
233                                 assert((PyTuple_Check(rowobj) || PyList_Check(rowobj)) && 
234                                                 PySequence_Size(rowobj) == dims[1]);
235
236                                 for(int j=0; j<dims[1]; j++){
237                                         PyObject * colobj = PySequence_GetItem(rowobj, j);
238                                         cvSet2D( m, i, j, PyObject_to_CvScalar( colobj ) );
239                                 }
240                         }
241                         else{
242                                 cvSet1D(m, i, PyObject_to_CvScalar( rowobj ) );
243                         }
244                 }
245                 return (CvArr *) m;
246         }
247
248         // CvMatND
249         PyErr_SetString(PyExc_TypeError, "Cannot convert Python Object to CvArr -- ndim > 3");
250         return NULL;
251         
252 }
253 %}