427d03ab516d827b5bb6dc4785a8638fc2296859
[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 static CvScalar PyObject_to_CvScalar(PyObject * obj){
120         CvScalar val;
121         CvScalar * ptr;
122     CvPoint2D32f *ptr2D32f;
123         CvPoint *pt_ptr;
124         void * vptr;
125         if( SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvScalar, 0 ) != -1)
126         {
127                 ptr = (CvScalar *) vptr;
128                 return *ptr;
129         }
130         if( SWIG_ConvertPtr(obj, (void**)&ptr2D32f, SWIGTYPE_p_CvPoint2D32f, 0) != -1) {
131         return cvScalar(ptr2D32f->x, ptr2D32f->y);
132     }
133     if( SWIG_ConvertPtr(obj, (void**)&pt_ptr, SWIGTYPE_p_CvPoint, 0) != -1) {
134         return cvScalar(pt_ptr->x, pt_ptr->y);
135     }
136         if(PyObject_AsDoubleArray(obj, val.val, 4)!=-1){
137                 return val;
138         }
139         return cvScalar(-1,-1,-1,-1); 
140 }
141
142 /* if python sequence type, convert to CvMat or CvMatND */
143 static CvArr * PyObject_to_CvArr(PyObject * obj, bool * freearg){
144         CvArr * cvarr;
145         *freearg = false;
146
147         // check if OpenCV type
148         if( PySwigObject_Check(obj) ){
149                 SWIG_ConvertPtr(obj, &cvarr, 0, SWIG_POINTER_EXCEPTION);
150         }
151         else if(PyList_Check(obj) || PyTuple_Check(obj)){
152                 cvarr = PySequence_to_CvArr( obj );
153                 *freearg = (cvarr != NULL);
154         }
155         else if(PyLong_Check(obj) && PyLong_AsLong(obj)==0){
156                 return NULL;
157         }
158         else {
159                 SWIG_ConvertPtr(obj, (void**)&cvarr, 0, SWIG_POINTER_EXCEPTION);
160         }
161         return cvarr;
162 }
163
164 static int PyObject_GetElemType(PyObject * obj){
165         void *vptr;
166         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint, 0) != -1) return CV_32SC2;   
167         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvSize, 0) != -1) return CV_32SC2;    
168         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvRect, 0) != -1) return CV_32SC4;    
169         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvSize2D32f, 0) != -1) return CV_32FC2;       
170         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint2D32f, 0) != -1) return CV_32FC2;      
171         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint3D32f, 0) != -1) return CV_32FC3;      
172         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint2D64f, 0) != -1) return CV_64FC2;      
173         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvPoint3D64f, 0) != -1) return CV_64FC3;      
174         if(SWIG_ConvertPtr(obj, &vptr, SWIGTYPE_p_CvScalar, 0) != -1) return CV_64FC4;  
175         if(PyTuple_Check(obj) || PyList_Check(obj)) return CV_MAKE_TYPE(CV_32F, PySequence_Size( obj ));
176         if(PyLong_Check(obj)) return CV_32S;
177         return CV_32F;
178 }
179
180 // Would like this to convert Python lists to CvMat
181 // Also lists of CvPoints, CvScalars, CvMats? etc
182 static CvArr * PySequence_to_CvArr( PyObject * obj ){
183         int dims[CV_MAX_DIM] = {1,1,1};
184         int ndim=0;
185         int cvtype;
186         PyObject * item;
187         
188         // figure out dimensions
189         for(item = obj; 
190                 (PyTuple_Check(item) || PyList_Check(item));
191                 item = PySequence_GetItem(item, 0))
192         {
193                 dims[ndim] = PySequence_Size( item ); 
194                 ndim++;
195         }
196
197         
198         if(ndim==0){
199                 PyErr_SetString(PyExc_TypeError, "Cannot convert an empty python object to a CvArr");
200                 return NULL;
201         }
202         
203         cvtype = PyObject_GetElemType(item);
204         // collapse last dim into NCH if we found a single channel, but the last dim is <=3
205         if(CV_MAT_CN(cvtype)==1 && dims[ndim-1]>1 && dims[ndim-1]<4){
206                 cvtype=CV_MAKE_TYPE(cvtype, dims[ndim-1]);
207                 dims[ndim-1]=1; 
208                 ndim--;
209         }
210         
211         if(cvtype==-1){
212                 PyErr_SetString(PyExc_TypeError, "Could not determine OpenCV element type of Python sequence");
213                 return NULL;
214         }
215         
216         // CvMat
217         if(ndim<=2){
218                 CvMat *m = cvCreateMat(dims[0], dims[1], cvtype);
219                 for(int i=0; i<dims[0]; i++){
220                         PyObject * rowobj = PySequence_GetItem(obj, i);
221                         if( dims[1] > 1 ){
222                                 // double check size
223                                 assert((PyTuple_Check(rowobj) || PyList_Check(rowobj)) && 
224                                                 PySequence_Size(rowobj) == dims[1]);
225
226                                 for(int j=0; j<dims[1]; j++){
227                                         PyObject * colobj = PySequence_GetItem(rowobj, j);
228                                         cvSet2D( m, i, j, PyObject_to_CvScalar( colobj ) );
229                                 }
230                         }
231                         else{
232                                 cvSet1D(m, i, PyObject_to_CvScalar( rowobj ) );
233                         }
234                 }
235                 return (CvArr *) m;
236         }
237
238         // CvMatND
239         PyErr_SetString(PyExc_TypeError, "Cannot convert Python Object to CvArr -- ndim > 3");
240         return NULL;
241         
242 }
243 %}