Update to 2.0.0 tree from current Fremantle build
[opencv] / interfaces / swig / octave / adapters.i
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 // 2008-04-07, Xavier Delacour <xavier.delacour@gmail.com>
43
44
45 // The trouble here is that Octave arrays are in Fortran order, while OpenCV 
46 // arrays are in C order. Neither Octave nor OpenCV seem to provide n-dim
47 // transpose, so we do that here.
48
49 // For images, we also scale the result to lie within [0-1].
50
51
52 // * add support for sparse matrices
53
54 // * add support for complex matrices
55
56 // * add support for roi and coi, or complain if either is set
57
58 // * test case for channel==1
59 // * test case for channel=={2,3,4}
60 // * test case for 2 dim, 1 dim, n dim cases
61
62 %{
63
64 class ndim_iterator {
65   int nd;
66   int dims[CV_MAX_DIM];
67   int step[CV_MAX_DIM];
68   int curr[CV_MAX_DIM];
69   uchar* _data;
70   int _type;
71   bool done;
72  public:
73   ndim_iterator() {}
74   ndim_iterator(CvMat* m) {
75     int c = CV_MAT_CN(m->type);
76     int elem_size = CV_ELEM_SIZE1(m->type);
77     nd = c == 1 ? 2 : 3;
78     dims[0] = m->rows;
79     dims[1] = m->cols;
80     dims[2] = c;
81     step[0] = m->step;
82     step[1] = c * elem_size;
83     step[2] = elem_size;
84     curr[0] = curr[1] = curr[2] = 0;
85     _data = m->data.ptr;
86     _type = m->type;
87     done = false;
88   }
89   ndim_iterator(CvMatND* m) {
90     int c = CV_MAT_CN(m->type);
91     int elem_size = CV_ELEM_SIZE1(m->type);
92     nd = m->dims + (c == 1 ? 0 : 1);
93     for (int j = 0; j < m->dims; ++j) {
94       dims[j] = m->dim[j].size;
95       step[j] = m->dim[j].step;
96       curr[j] = 0;
97     }
98     if (c > 1) {
99       dims[m->dims] = c;
100       step[m->dims] = elem_size;
101       curr[m->dims] = 0;
102     }
103     _data = m->data.ptr;
104     _type = m->type;
105     done = false;
106   }
107   ndim_iterator(IplImage* img) {
108     nd = img->nChannels == 1 ? 2 : 3;
109     dims[0] = img->height;
110     dims[1] = img->width;
111     dims[2] = img->nChannels;
112
113     switch (img->depth) {
114     case IPL_DEPTH_8U: _type = CV_8U; break;
115     case IPL_DEPTH_8S: _type = CV_8S; break;
116     case IPL_DEPTH_16U: _type = CV_16U; break;
117     case IPL_DEPTH_16S: _type = CV_16S; break;
118     case IPL_DEPTH_32S: _type = CV_32S; break;
119     case IPL_DEPTH_32F: _type = CV_32F; break;
120     case IPL_DEPTH_1U: _type = CV_64F; break;
121     default:
122       error("unsupported image depth");
123       return;
124     }
125
126     int elem_size = CV_ELEM_SIZE1(_type);
127     step[0] = img->widthStep;
128     step[1] = img->nChannels * elem_size;
129     step[2] = elem_size;
130     curr[0] = curr[1] = curr[2] = 0;
131     _data = (uchar*)img->imageData;
132     done = false;
133   }
134   ndim_iterator(NDArray& nda) {
135     dim_vector d(nda.dims());
136     nd = d.length();
137     int last_step = sizeof(double);
138     for (int j = 0; j < d.length(); ++j) {
139       dims[j] = d(j);
140       step[j] = last_step;
141       last_step *= dims[j];
142       curr[j] = 0;
143     }
144     _data = (uchar*)const_cast<double*>(nda.data());
145     _type = CV_64F;
146     done = false;
147   }
148
149   operator bool () const {
150     return !done;
151   }
152   uchar* data() {
153     return _data;
154   }
155   int type() const {
156     return _type;
157   }
158   ndim_iterator& operator++ () {
159     int curr_dim = 0;
160     for (;;) {
161       _data += step[curr_dim];
162       if (++curr[curr_dim] < dims[curr_dim])
163         break;
164       curr[curr_dim] = 0;
165       _data -= step[curr_dim] * dims[curr_dim];
166       ++curr_dim;
167       if (curr_dim == nd) {
168         done = true;
169         break;
170       }
171     }
172     return *this;
173   }
174 };
175
176 template <class T1, class T2>
177   void transpose_copy_typed(ndim_iterator src_it, ndim_iterator dst_it, 
178                            double scale) {
179   assert(sizeof(T1) == CV_ELEM_SIZE1(src_it.type()));
180   assert(sizeof(T2) == CV_ELEM_SIZE1(dst_it.type()));
181   if (scale == 1) {
182     while (src_it) {
183       *(T2*)dst_it.data() = (T2)*(T1*)src_it.data();
184       ++src_it;
185       ++dst_it;
186     }
187   } else {
188     while (src_it) {
189       *(T2*)dst_it.data() = (T2)(scale * (*(T1*)src_it.data()));
190       ++src_it;
191       ++dst_it;
192     }
193   }
194 }
195
196 template <class T1>
197 void transpose_copy2(ndim_iterator src_it, ndim_iterator dst_it, 
198                      double scale) {
199   switch (CV_MAT_DEPTH(dst_it.type())) {
200   case CV_8U: transpose_copy_typed<T1,unsigned char>(src_it,dst_it,scale); break;
201   case CV_8S: transpose_copy_typed<T1,signed char>(src_it,dst_it,scale); break;
202   case CV_16U: transpose_copy_typed<T1,unsigned short>(src_it,dst_it,scale); break;
203   case CV_16S: transpose_copy_typed<T1,signed short>(src_it,dst_it,scale); break;
204   case CV_32S: transpose_copy_typed<T1,signed int>(src_it,dst_it,scale); break;
205   case CV_32F: transpose_copy_typed<T1,float>(src_it,dst_it,scale); break;
206   case CV_64F: transpose_copy_typed<T1,double>(src_it,dst_it,scale); break;
207   default:
208     error("unsupported dest array type (supported types are CV_8U, CV_8S, "
209           "CV_16U, CV_16S, CV_32S, CV_32F, CV_64F)");
210   }
211 }
212
213 void transpose_copy(ndim_iterator src_it, ndim_iterator dst_it, 
214                     double scale = 1) {
215   switch (CV_MAT_DEPTH(src_it.type())) {
216   case CV_8U: transpose_copy2<unsigned char>(src_it,dst_it,scale); break;
217   case CV_8S: transpose_copy2<signed char>(src_it,dst_it,scale); break;
218   case CV_16U: transpose_copy2<unsigned short>(src_it,dst_it,scale); break;
219   case CV_16S: transpose_copy2<signed short>(src_it,dst_it,scale); break;
220   case CV_32S: transpose_copy2<signed int>(src_it,dst_it,scale); break;
221   case CV_32F: transpose_copy2<float>(src_it,dst_it,scale); break;
222   case CV_64F: transpose_copy2<double>(src_it,dst_it,scale); break;
223   default:
224     error("unsupported source array type (supported types are CV_8U, CV_8S, "
225           "CV_16U, CV_16S, CV_32S, CV_32F, CV_64F)");
226   }
227 }
228
229 octave_value cv2mat(CvArr* arr) {
230   dim_vector d;
231   NDArray nda;
232
233   if (CV_IS_MAT(arr)) {
234     // m x n x c
235     CvMat* m = (CvMat*)arr;
236
237     int c = CV_MAT_CN(m->type);
238     if (c == 1) {
239       d.resize(2);
240       d(0) = m->rows;
241       d(1) = m->cols;
242     } else {
243       d.resize(3);
244       d(0) = m->rows;
245       d(1) = m->cols;
246       d(2) = c;
247     }
248
249     nda = NDArray(d);
250     transpose_copy(m, nda);
251   }
252   else if (CV_IS_MATND(arr)) {
253     // m1 x m2 x ... x mn x c
254     CvMatND* m = (CvMatND*)arr;
255
256     int c = CV_MAT_CN(m->type);
257     if (c == 1) {
258       d.resize(m->dims);
259       for (int j = 0; j < m->dims; ++j)
260         d(j) = m->dim[j].size;
261     } else {
262       d.resize(m->dims + 1);
263       for (int j = 0; j < m->dims; ++j)
264         d(j) = m->dim[j].size;
265       d(m->dims) = c;
266     }
267
268     nda = NDArray(d);
269     transpose_copy(m, nda);
270   }
271   else if (CV_IS_IMAGE(arr)) {
272     // m x n x c
273     IplImage* img = (IplImage*)arr;
274
275     if (img->nChannels == 1) {
276       d.resize(2);
277       d(0) = img->height;
278       d(1) = img->width;
279     } else {
280       d.resize(3);
281       d(0) = img->height;
282       d(1) = img->width;
283       d(2) = img->nChannels;
284     }
285
286     nda = NDArray(d);
287     transpose_copy(img, nda);
288   }
289   else {
290     error("unsupported array type (supported types are CvMat, CvMatND, IplImage)");
291     return octave_value();
292   }
293
294   return nda;
295 }
296
297 octave_value mat2cv(const octave_value& ov, int type) {
298   NDArray nda(ov.array_value());
299   if (error_state)
300     return 0;
301
302   dim_vector d = ov.dims();
303   assert(d.length() > 0);
304
305   int nd = d.length();
306   int last_dim = d(d.length() - 1);
307   int c = CV_MAT_CN(type);
308   if (c != 1 && c != last_dim) {
309     error("last dimension and channel must agree, or channel must equal one");
310     return 0;
311   }
312   if (c > 1)
313     --nd;
314
315   if (nd == 2) {
316     CvMat *m = cvCreateMat(d(0), d(1), type);
317     transpose_copy(nda, m);
318     return SWIG_NewPointerObj(m, SWIGTYPE_p_CvMat, SWIG_POINTER_OWN);
319   }
320   else {
321     int tmp[CV_MAX_DIM];
322     for (int j = 0; j < nd; ++j)
323       tmp[j] = d(j);
324     CvMatND *m = cvCreateMatND(nd, tmp, type);
325     transpose_copy(nda, m);
326     return SWIG_NewPointerObj(m, SWIGTYPE_p_CvMatND, SWIG_POINTER_OWN);
327   }
328 }
329
330 octave_value cv2im(CvArr* arr) {
331   if (!CV_IS_IMAGE(arr) && !CV_IS_MAT(arr)) {
332     error("input is not an OpenCV image or 2D matrix");
333     return octave_value();
334   }
335
336   dim_vector d;
337   NDArray nda;
338
339   if (CV_IS_MAT(arr)) {
340     // m x n x c
341     CvMat* m = (CvMat*)arr;
342
343     int c = CV_MAT_CN(m->type);
344     if (c == 1) {
345       d.resize(2);
346       d(0) = m->rows;
347       d(1) = m->cols;
348     } else {
349       d.resize(3);
350       d(0) = m->rows;
351       d(1) = m->cols;
352       d(2) = c;
353     }
354
355     nda = NDArray(d);
356     transpose_copy(m, nda, 1/256.0);
357   }
358   else if (CV_IS_IMAGE(arr)) {
359     // m x n x c
360     IplImage* img = (IplImage*)arr;
361
362     if (img->nChannels == 1) {
363       d.resize(2);
364       d(0) = img->height;
365       d(1) = img->width;
366     } else {
367       d.resize(3);
368       d(0) = img->height;
369       d(1) = img->width;
370       d(2) = img->nChannels;
371     }
372
373     nda = NDArray(d);
374     transpose_copy(img, nda, 1/256.0);
375   }
376
377   return nda;
378 }
379
380 CvMat* im2cv(const octave_value& ov, int depth) {
381   NDArray nda(ov.array_value());
382   if (error_state)
383     return 0;
384
385   dim_vector d = ov.dims();
386   assert(d.length() > 0);
387
388   if (d.length() != 2 && d.length() != 3 && 
389       !(d.length() == 3 && d(2) <= 4)) {
390     error("input must be m x n or m x n x c matrix, where 1<=c<=4");
391     return 0;
392   }
393
394   int channels = d.length() == 2 ? 1 : d(2);
395   int type = CV_MAKETYPE(depth, channels);
396
397   CvMat *m = cvCreateMat(d(0), d(1), type);
398   transpose_copy(nda, m, 256);
399
400   return m;
401 }
402
403 %}
404
405 %newobject im2cv;
406
407 %feature("autodoc", 0) cv2mat;
408 %feature("autodoc", 0) mat2cv;
409 %feature("autodoc", 0) cv2im;
410 %feature("autodoc", 0) im2cv;
411
412 %docstring cv2mat {
413 @deftypefn {Loadable Function} @var{m1} = cv2mat (@var{m2})
414 Convert the CvMat, CvMatND, or IplImage @var{m2} into an Octave real matrix @var{m1}.
415 The dimensions @var{m1} are those of @var{m2}, plus an addition dimension 
416 if @var{m2} has more than one channel.
417 @end deftypefn
418 }
419
420 %docstring mat2cv {
421 @deftypefn {Loadable Function} @var{m1} = mat2cv (@var{m2}, @var{type})
422 Convert the Octave array @var{m2} into either a CvMat or a CvMatND of type
423 @var{type}.
424 @var{type} is one of CV_8UC(n), CV_8SC(n), CV_16UC(n), CV_16SC(n), CV_32SC(n), 
425 CV_32FC(n), CV_64FC(n), where n indicates channel and is between 1 and 4.
426 If the dimension of @var{m2} is equal to 2 (not counting channels),
427 a CvMat is returned. Otherwise, a CvMatND is returned.
428 @end deftypefn
429 }
430
431 %docstring cv2im {
432 @deftypefn {Loadable Function} @var{im} = cv2im (@var{I})
433 Convert the OpenCV image or 2D matrix @var{I} into an Octave image @var{im}.
434 @var{im} is a real matrix of dimension height x width or 
435 height x width x channels, with values within the interval [0,1]).
436 @end deftypefn
437 }
438
439 %docstring im2cv {
440 @deftypefn {Loadable Function} @var{I} = im2cv (@var{im}, @var{depth})
441 Convert the Octave image @var{im} into the OpenCV image @var{I} of depth
442 @var{depth}.
443 @var{im} is a real matrix of dimension height x width or 
444 height x width x channels, with values within the interval [0,1].
445 @var{depth} must be one of CV_8U, CV_8S, CV_16U, CV_16S, CV_32S, CV_32F, CV_64F.
446 @end deftypefn
447 }
448
449 octave_value cv2mat(CvArr* arr);
450 octave_value mat2cv(const octave_value& ov, int type);
451 octave_value cv2im(CvArr* arr);
452 CvMat* im2cv(const octave_value& ov, int depth);