From f18d2cb90091f948f0e9ce408d8ace3d6a68358c Mon Sep 17 00:00:00 2001 From: jamesb Date: Tue, 30 Mar 2010 22:05:30 +0000 Subject: [PATCH] #150 ReshapeMatND: test, implementaton, doc git-svn-id: https://code.ros.org/svn/opencv/trunk@2950 73c94f0f-984f-4a5f-82bc-2d8db8d8ee08 --- opencv/doc/cxcore_array_operations.tex | 22 ++++++- opencv/doc/latex2sphinx/go | 1 - opencv/interfaces/python/api | 4 +- opencv/interfaces/python/cv.cpp | 85 +++++++++++++------------- opencv/tests/python/test.py | 20 +++++- 5 files changed, 84 insertions(+), 48 deletions(-) diff --git a/opencv/doc/cxcore_array_operations.tex b/opencv/doc/cxcore_array_operations.tex index c8c34072..4a36bf55 100644 --- a/opencv/doc/cxcore_array_operations.tex +++ b/opencv/doc/cxcore_array_operations.tex @@ -2905,13 +2905,15 @@ Changes the shape of a multi-dimensional array without copying the data. \cvarg{newSizes}{Array of new dimension sizes. Only $\texttt{newDims}-1$ values are used, because the total number of elements must remain the same. Thus, if $\texttt{newDims} = 1$, \texttt{newSizes} array is not used.} \else +\cvarg{newCn}{New number of channels. $\texttt{newCn} = 0$ means that the number of channels remains unchanged.} \cvarg{newDims}{List of new dimensions.} \fi \end{description} -The function is an advanced version of \cvCPyCross{Reshape} that can work with multi-dimensional arrays as well (though it can work with ordinary images and matrices) and change the number of dimensions. \ifC +The function is an advanced version of \cvCPyCross{Reshape} that can work with multi-dimensional arrays as well (though it can work with ordinary images and matrices) and change the number of dimensions. + Below are the two samples from the \cvCPyCross{Reshape} description rewritten using \cvCPyCross{ReshapeMatND}: \begin{lstlisting} @@ -2931,6 +2933,24 @@ row = (CvMat*)cvReshapeND(mat, &row_header, 0, 1, 0); \end{lstlisting} \fi +\ifPy +Returns a new \cross{CvMatND} that shares the same data as \texttt{arr} +but has different dimensions or number of channels. The only requirement +is that the total length of the data is unchanged. + +\begin{lstlisting} +>>> import cv +>>> mat = cv.CreateMatND([24], cv.CV_32FC1) +>>> print cv.GetDims(cv.ReshapeMatND(mat, 0, [8, 3])) +(8, 3) +>>> m2 = cv.ReshapeMatND(mat, 4, [3, 2]) +>>> print cv.GetDims(m2) +(3, 2) +>>> print m2.channels +4 +\end{lstlisting} +\fi + \ifC \cvfunc{cvRound, cvFloor, cvCeil}\label{cvRound} diff --git a/opencv/doc/latex2sphinx/go b/opencv/doc/latex2sphinx/go index b991b07d..c0ed40de 100644 --- a/opencv/doc/latex2sphinx/go +++ b/opencv/doc/latex2sphinx/go @@ -1,7 +1,6 @@ #!/bin/bash LANGUAGES="c cpp py" -LANGUAGES="py" mkdir -p $LANGUAGES tput clear diff --git a/opencv/interfaces/python/api b/opencv/interfaces/python/api index 69502d38..b0ebc371 100644 --- a/opencv/interfaces/python/api +++ b/opencv/interfaces/python/api @@ -1765,7 +1765,7 @@ InitLineIterator line_iterator /doconly CvArr image CvPoint pt1 CvPoint pt2 - int line_iterator /O + iter line_iterator /O int connectivity 8 int left_to_right 0 LoadImageM /doconly @@ -1777,7 +1777,7 @@ LoadImage /doconly ReshapeMatND /doconly CvMat arr int newCn - int newDims + ints newDims Reshape /doconly CvArr arr int newCn diff --git a/opencv/interfaces/python/cv.cpp b/opencv/interfaces/python/cv.cpp index 774d210e..5728d1eb 100644 --- a/opencv/interfaces/python/cv.cpp +++ b/opencv/interfaces/python/cv.cpp @@ -122,6 +122,7 @@ static int convert_to_CvMatND(PyObject *o, CvMatND **dst, const char *name = "no static PyObject *what_data(PyObject *o); static PyObject *FROM_CvMat(CvMat *r); static PyObject *FROM_ROCvMatPTR(ROCvMat *r); +static PyObject *shareDataND(PyObject *donor, CvMatND *pdonor, CvMatND *precipient); #define FROM_double(r) PyFloat_FromDouble(r) #define FROM_float(r) PyFloat_FromDouble(r) @@ -337,6 +338,7 @@ static void iplimage_setorigin(iplimage_t *cva, PyObject *v) static PyGetSetDef iplimage_getseters[] = { {(char*)"nChannels", (getter)iplimage_getnChannels, (setter)NULL, (char*)"nChannels", NULL}, + {(char*)"channels", (getter)iplimage_getnChannels, (setter)NULL, (char*)"nChannels", NULL}, {(char*)"width", (getter)iplimage_getwidth, (setter)NULL, (char*)"width", NULL}, {(char*)"height", (getter)iplimage_getheight, (setter)NULL, (char*)"height", NULL}, {(char*)"depth", (getter)iplimage_getdepth, (setter)NULL, (char*)"depth", NULL}, @@ -473,6 +475,11 @@ static PyObject *cvmat_getcols(cvmat_t *cva) return PyInt_FromLong(cva->a->cols); } +static PyObject *cvmat_getchannels(cvmat_t *cva) +{ + return PyInt_FromLong(CV_MAT_CN(cva->a->type)); +} + #if PYTHON_USE_NUMPY #include "numpy/ndarrayobject.h" @@ -627,6 +634,7 @@ static PyGetSetDef cvmat_getseters[] = { {(char*)"step", (getter)cvmat_getstep, (setter)NULL, (char*)"step", NULL}, {(char*)"rows", (getter)cvmat_getrows, (setter)NULL, (char*)"rows", NULL}, {(char*)"cols", (getter)cvmat_getcols, (setter)NULL, (char*)"cols", NULL}, + {(char*)"channels",(getter)cvmat_getchannels, (setter)NULL, (char*)"channels", NULL}, {(char*)"width", (getter)cvmat_getcols, (setter)NULL, (char*)"width", NULL}, {(char*)"height", (getter)cvmat_getrows, (setter)NULL, (char*)"height", NULL}, #if PYTHON_USE_NUMPY @@ -778,10 +786,16 @@ static struct PyMethodDef cvmatnd_methods[] = {NULL, NULL} }; +static PyObject *cvmatnd_getchannels(cvmatnd_t *cva) +{ + return PyInt_FromLong(CV_MAT_CN(cva->a->type)); +} + static PyGetSetDef cvmatnd_getseters[] = { #if PYTHON_USE_NUMPY {(char*)"__array_struct__", (getter)cvmatnd_array_struct, (setter)NULL, (char*)"__array_struct__", NULL}, #endif + {(char*)"channels",(getter)cvmatnd_getchannels, (setter)NULL, (char*)"channels", NULL}, {NULL} /* Sentinel */ }; @@ -3204,7 +3218,7 @@ static PyObject *pycvReshapeMatND(PyObject *self, PyObject *args) int new_cn = 0; PyObject *new_dims = NULL; - if (!PyArg_ParseTuple(args, "O|iO", &o, &new_cn, &new_dims)) + if (!PyArg_ParseTuple(args, "OiO", &o, &new_cn, &new_dims)) return NULL; CvMatND *cva; @@ -3216,49 +3230,25 @@ static PyObject *pycvReshapeMatND(PyObject *self, PyObject *args) return NULL; } -#if 0 - if ((dims.count + 1) <= 2) { - CvMat *m = cvCreateMatHeader(100, 100, 1); // these args do not matter, because overwritten - if (new_dims != NULL) { - printf("newcn=%d newdims=%d newSizes=%p\n", new_cn, dims.count + 1, dims.i); - ERRWRAP(cvReshapeND(cva, m, new_cn, dims.count + 1, dims.i)); - } else { - ERRWRAP(cvReshapeND(cva, m, new_cn, 0, NULL)); - } + if (new_cn == 0) + new_cn = CV_MAT_CN(cvGetElemType(cva)); - cvmat_t *om = PyObject_NEW(cvmat_t, &cvmat_Type); - om->a = m; - om->data = what_data(o); - Py_INCREF(om->data); - om->offset = 0; - return (PyObject*)om; - } else { - int dummy[1] = { 1 }; - CvMatND *m = cvCreateMatNDHeader(1, dummy, 1); // these args do not matter, because overwritten - if (new_dims != NULL) { - printf("newcn=%d newdims=%d newSizes=%p\n", new_cn, dims.count + 1, dims.i); - ERRWRAP(cvReshapeND(cva, m, new_cn, dims.count + 1, dims.i)); - } else { - ERRWRAP(cvReshapeND(cva, m, new_cn, 0, NULL)); - } + int i; + int count = CV_MAT_CN(cvGetElemType(cva)); + for (i = 0; i < cva->dims; i++) + count *= cva->dim[i].size; - cvmatnd_t *om = PyObject_NEW(cvmatnd_t, &cvmatnd_Type); - om->a = m; - om->data = what_data(o); - Py_INCREF(om->data); - om->offset = 0; - return (PyObject*)om; - } -#else - { - int size[] = { 2, 2, 2 }; - CvMatND* mat = cvCreateMatND(3, size, CV_32F); - CvMat row_header; - CvArr *row; - row = cvReshapeND(mat, &row_header, 0, 1, 0); + int newcount = new_cn; + for (i = 0; i < dims.count; i++) + newcount *= dims.i[i]; + + if (count != newcount) { + PyErr_SetString(PyExc_TypeError, "Total number of elements must be unchanged"); + return NULL; } - Py_RETURN_NONE; -#endif + + CvMatND *pn = cvCreateMatNDHeader(dims.count, dims.i, CV_MAKETYPE(CV_MAT_TYPE(cva->type), new_cn)); + return shareDataND(o, cva, pn); } static void OnMouse(int event, int x, int y, int flags, void* param) @@ -3658,6 +3648,19 @@ static PyObject *shareData(PyObject *donor, CvArr *pdonor, CvMat *precipient) return recipient; } +static PyObject *shareDataND(PyObject *donor, CvMatND *pdonor, CvMatND *precipient) +{ + PyObject *recipient = (PyObject*)PyObject_NEW(cvmatnd_t, &cvmatnd_Type); + ((cvmatnd_t*)recipient)->a = precipient; + ((cvmatnd_t*)recipient)->offset = 0; + + PyObject *arr_data; + arr_data = ((cvmatnd_t*)donor)->data; + ((cvmatnd_t*)recipient)->data = arr_data; + Py_INCREF(arr_data); + return recipient; +} + static PyObject *pycvGetHuMoments(PyObject *self, PyObject *args) { CvMoments* moments; diff --git a/opencv/tests/python/test.py b/opencv/tests/python/test.py index 1e3c2d50..d87c6e1a 100644 --- a/opencv/tests/python/test.py +++ b/opencv/tests/python/test.py @@ -680,10 +680,12 @@ class FunctionTests(OpenCVTests): self.assert_((nc * nr * nd) == elems) # Now test ReshapeMatND - mat = cv.CreateMatND([24], cv.CV_32F) + mat = cv.CreateMatND([24], cv.CV_32FC1) cv.Set(mat, 1.0) - self.assertEqual(cv.GetDims(cv.ReshapeMatND(mat, 0, [])), (24, 1)) - self.assertEqual(cv.GetDims(cv.ReshapeMatND(mat, 0, [1])), (6, 4)) + self.assertEqual(cv.GetDims(cv.ReshapeMatND(mat, 0, [24, 1])), (24, 1)) + self.assertEqual(cv.GetDims(cv.ReshapeMatND(mat, 0, [6, 4])), (6, 4)) + self.assertEqual(cv.GetDims(cv.ReshapeMatND(mat, 24, [1])), (1,)) + self.assertRaises(TypeError, lambda: cv.ReshapeMatND(mat, 12, [1])) def test_Save(self): for o in [ cv.CreateImage((128,128), cv.IPL_DEPTH_8U, 1), cv.CreateMat(16, 16, cv.CV_32FC1) ]: @@ -813,6 +815,18 @@ class AreaTests(OpenCVTests): cv.AddS(ones, 7, r) self.assert_(numpy.alltrue(r == (8 * ones))) + # create arrays, use them in OpenCV and replace the the array + # looking for leaks + def randdim(): + return [random.randrange(1,6) for i in range(random.randrange(1, 6))] + as = [numpy.ones(randdim()).astype(numpy.uint8) for i in range(10)] + cs = [cv.fromarray(a, True) for a in as] + for i in range(1000): + as[random.randrange(10)] = numpy.ones(randdim()).astype(numpy.uint8) + cs[random.randrange(10)] = cv.fromarray(as[random.randrange(10)], True) + for j in range(10): + self.assert_(all([c == chr(1) for c in cs[j].tostring()])) + else: print "SKIPPING test_numpy - numpy support not built" -- 2.39.2