#define MODULESTR "cv"
+#define PYTHON_NUMPY 1
+
static PyObject *opencv_error;
struct memtrack_t {
return PyInt_FromLong(cva->a->cols);
}
+#if PYTHON_NUMPY
+#include "numpy/ndarrayobject.h"
+
+// A PyArrayInterface, with an associated python object that should be DECREF'ed on release
+struct arrayTrack {
+ PyArrayInterface s;
+ PyObject *o;
+};
+
+static void arrayTrackDtor(void *p)
+{
+ struct arrayTrack *at = (struct arrayTrack *)p;
+ delete at->s.shape;
+ delete at->s.strides;
+ if (at->s.descr)
+ Py_DECREF(at->s.descr);
+ Py_DECREF(at->o);
+}
+
+// Fill in fields of PyArrayInterface s using mtype. This code is common
+// to cvmat and cvmatnd
+
+static void arrayinterface_common(PyArrayInterface *s, int mtype)
+{
+ s->two = 2;
+
+ switch (CV_MAT_DEPTH(mtype)) {
+ case CV_8U:
+ s->typekind = 'u';
+ s->itemsize = 1;
+ break;
+ case CV_8S:
+ s->typekind = 'i';
+ s->itemsize = 1;
+ break;
+ case CV_16U:
+ s->typekind = 'u';
+ s->itemsize = 2;
+ break;
+ case CV_16S:
+ s->typekind = 'i';
+ s->itemsize = 2;
+ break;
+ case CV_32S:
+ s->typekind = 'i';
+ s->itemsize = 4;
+ break;
+ case CV_32F:
+ s->typekind = 'f';
+ s->itemsize = 4;
+ break;
+ case CV_64F:
+ s->typekind = 'f';
+ s->itemsize = 8;
+ break;
+ default:
+ assert(0);
+ }
+
+ s->flags = NPY_WRITEABLE | NPY_NOTSWAPPED;
+}
+
+static PyObject *cvmat_array_struct(cvmat_t *cva)
+{
+ CvMat *m;
+ convert_to_CvMat((PyObject *)cva, &m, "");
+
+ arrayTrack *at = new arrayTrack;
+ PyArrayInterface *s = &at->s;
+
+ at->o = cva->data;
+ Py_INCREF(at->o);
+
+ arrayinterface_common(s, m->type);
+
+ if (CV_MAT_CN(m->type) == 1) {
+ s->nd = 2;
+ s->shape = new npy_intp[2];
+ s->shape[0] = m->rows;
+ s->shape[1] = m->cols;
+ s->strides = new npy_intp[2];
+ s->strides[0] = m->step;
+ s->strides[1] = s->itemsize;
+ } else {
+ s->nd = 3;
+ s->shape = new npy_intp[3];
+ s->shape[0] = m->rows;
+ s->shape[1] = m->cols;
+ s->shape[2] = CV_MAT_CN(m->type);
+ s->strides = new npy_intp[3];
+ s->strides[0] = m->step;
+ s->strides[1] = s->itemsize * CV_MAT_CN(m->type);
+ s->strides[2] = s->itemsize;
+ }
+ s->data = (void*)(m->data.ptr);
+ s->descr = PyList_New(1);
+ char typestr[10];
+ sprintf(typestr, "<%c%d", s->typekind, s->itemsize);
+ PyList_SetItem(s->descr, 0, Py_BuildValue("(ss)", "x", typestr));
+
+ return PyCObject_FromVoidPtr(s, arrayTrackDtor);
+}
+
+static PyObject *cvmatnd_array_struct(cvmatnd_t *cva)
+{
+ CvMatND *m;
+ convert_to_CvMatND((PyObject *)cva, &m, "");
+
+ arrayTrack *at = new arrayTrack;
+ PyArrayInterface *s = &at->s;
+
+ at->o = cva->data;
+ Py_INCREF(at->o);
+
+ arrayinterface_common(s, m->type);
+
+ int i;
+ if (CV_MAT_CN(m->type) == 1) {
+ s->nd = m->dims;
+ s->shape = new npy_intp[s->nd];
+ for (i = 0; i < s->nd; i++)
+ s->shape[i] = m->dim[i].size;
+ s->strides = new npy_intp[s->nd];
+ for (i = 0; i < (s->nd - 1); i++)
+ s->strides[i] = m->dim[i].step;
+ s->strides[s->nd - 1] = s->itemsize;
+ } else {
+ s->nd = m->dims + 1;
+ s->shape = new npy_intp[s->nd];
+ for (i = 0; i < (s->nd - 1); i++)
+ s->shape[i] = m->dim[i].size;
+ s->shape[s->nd - 1] = CV_MAT_CN(m->type);
+
+ s->strides = new npy_intp[s->nd];
+ for (i = 0; i < (s->nd - 2); i++)
+ s->strides[i] = m->dim[i].step;
+ s->strides[s->nd - 2] = s->itemsize * CV_MAT_CN(m->type);
+ s->strides[s->nd - 1] = s->itemsize;
+ }
+ s->data = (void*)(m->data.ptr);
+ s->descr = PyList_New(1);
+ char typestr[10];
+ sprintf(typestr, "<%c%d", s->typekind, s->itemsize);
+ PyList_SetItem(s->descr, 0, Py_BuildValue("(ss)", "x", typestr));
+
+ return PyCObject_FromVoidPtr(s, arrayTrackDtor);
+}
+#endif
+
static PyGetSetDef cvmat_getseters[] = {
{(char*)"type", (getter)cvmat_gettype, (setter)NULL, (char*)"type", NULL},
{(char*)"step", (getter)cvmat_getstep, (setter)NULL, (char*)"step", NULL},
{(char*)"cols", (getter)cvmat_getcols, (setter)NULL, (char*)"cols", NULL},
{(char*)"width", (getter)cvmat_getcols, (setter)NULL, (char*)"width", NULL},
{(char*)"height", (getter)cvmat_getrows, (setter)NULL, (char*)"height", NULL},
+#if PYTHON_NUMPY
+ {(char*)"__array_struct__", (getter)cvmat_array_struct, (setter)NULL, (char*)"__array_struct__", NULL},
+#endif
{NULL} /* Sentinel */
};
{NULL, NULL}
};
+static PyGetSetDef cvmatnd_getseters[] = {
+#if PYTHON_NUMPY
+ {(char*)"__array_struct__", (getter)cvmatnd_array_struct, (setter)NULL, (char*)"__array_struct__", NULL},
+#endif
+ {NULL} /* Sentinel */
+};
+
static PyMappingMethods cvmatnd_as_map = {
NULL,
&cvarr_GetItem,
cvmatnd_Type.tp_as_mapping = &cvmatnd_as_map;
cvmatnd_Type.tp_repr = cvmatnd_repr;
cvmatnd_Type.tp_methods = cvmatnd_methods;
+ cvmatnd_Type.tp_getset = cvmatnd_getseters;
}
static int is_cvmatnd(PyObject *o)
static PyObject* cvseq_map_getitem(PyObject *o, PyObject *item)
{
- cvseq_t *ps = (cvseq_t*)o;
if (PyInt_Check(item)) {
long i = PyInt_AS_LONG(item);
if (i < 0)
return 1;
}
+#if 0 // not used
static int convert_to_CvPoint3D32fPTR(PyObject *o, CvPoint3D32f **p, const char *name = "no_name")
{
PyObject *fi = PySequence_Fast(o, name);
Py_DECREF(fi);
return 1;
}
+#endif
static int convert_to_CvStarDetectorParams(PyObject *o, CvStarDetectorParams *dst, const char *name = "no_name")
{
CvMatND *mat = m->a;
assert(mat->dim[0].step != 0);
-#if 1
+#if 0
PyObject *data = PyString_FromStringAndSize((char*)(mat->data.ptr), mat->dim[0].size * mat->dim[0].step);
#else
memtrack_t *o = PyObject_NEW(memtrack_t, &memtrack_Type);
- size_t gap = mat->data.ptr - (uchar*)mat->refcount;
- o->ptr = mat->refcount;
- o->size = gap + mat->rows * mat->step;
- PyObject *data = PyBuffer_FromReadWriteObject((PyObject*)o, (size_t)gap, mat->rows * mat->step);
+ o->ptr = cvPtr1D(mat, 0);
+ o->size = cvmatnd_size(mat);
+ PyObject *data = PyBuffer_FromReadWriteObject((PyObject*)o, (size_t)0, o->size);
if (data == NULL)
return NULL;
#endif
m->data = data;
m->offset = 0;
- cvDecRefData(mat); // Ref count should be zero here, so this is a release
+ // cvDecRefData(mat); // Ref count should be zero here, so this is a release
return (PyObject*)m;
}
return pythonize_CvMatND(m);
}
+#if PYTHON_NUMPY
+static PyObject *pycvfromarray(PyObject *self, PyObject *args)
+{
+ PyObject *o;
+ if (!PyArg_ParseTuple(args, "O", &o)) {
+ return NULL;
+ }
+
+ PyObject *ao = PyObject_GetAttrString(o, "__array_struct__");
+ if ((ao == NULL) || !PyCObject_Check(ao)) {
+ PyErr_SetString(PyExc_TypeError, "object does not have array interface");
+ return NULL;
+ }
+ PyArrayInterface *pai = (PyArrayInterface*)PyCObject_AsVoidPtr(ao);
+ if (pai->two != 2) {
+ PyErr_SetString(PyExc_TypeError, "object does not have array interface");
+ return NULL;
+ }
+
+ cvmatnd_t *m = PyObject_NEW(cvmatnd_t, &cvmatnd_Type);
+ int type = -1;
+
+ switch (pai->typekind) {
+ case 'i':
+ if (pai->itemsize == 1)
+ type = CV_8SC1;
+ else if (pai->itemsize == 2)
+ type = CV_16SC1;
+ else if (pai->itemsize == 4)
+ type = CV_32SC1;
+ break;
+
+ case 'u':
+ if (pai->itemsize == 1)
+ type = CV_8UC1;
+ else if (pai->itemsize == 2)
+ type = CV_16UC1;
+ break;
+
+ case 'f':
+ if (pai->itemsize == 4)
+ type = CV_32FC1;
+ else if (pai->itemsize == 8)
+ type = CV_64FC1;
+ break;
+ }
+ ERRWRAP(m->a = cvCreateMatND(pai->nd, pai->shape, type));
+ m->a->data.ptr = (uchar*)pai->data;
+ return pythonize_CvMatND(m);
+}
+#endif
+
static PyObject *pycvCreateHist(PyObject *self, PyObject *args)
{
PyObject *dims;
static PyMethodDef methods[] = {
+#if PYTHON_NUMPY
+ {"fromarray", pycvfromarray, METH_VARARGS, "fromarray(array) -> cvmatnd"},
+#endif
+
{"CreateHist", pycvCreateHist, METH_VARARGS, "CreateHist(dims, type, ranges, uniform = 1) -> hist"},
{"CreateImage", pycvCreateImage, METH_VARARGS, "CreateImage(size, depth, channels) -> image"},
{"CreateImageHeader", pycvCreateImageHeader, METH_VARARGS, "CreateImageHeader(size, depth, channels) -> image"},
import hashlib
import os
import getopt
+import operator
+import functools
import cv
class AreaTests(OpenCVTests):
+ def test_numpy(self):
+ if 'fromarray' in dir(cv):
+ import numpy
+ for t in [cv.CV_16UC1, cv.CV_32SC1, cv.CV_32FC1]:
+ for d in [ (8,), (1,7), (2,3,4), (7,9,2,1,8), (1,2,3,4,5,6,7,8) ]:
+ total = reduce(operator.__mul__, d)
+ m = cv.CreateMatND(d, t)
+ for i in range(total):
+ cv.Set1D(m, i, i)
+ na = numpy.asarray(m).reshape((total,))
+ self.assertEqual(list(na), range(total))
+
+ # now do numpy -> cvmat, and verify
+ m2 = cv.fromarray(na)
+
+ # Check that new cvmat m2 contains same counting sequence
+ for i in range(total):
+ self.assertEqual(cv.Get1D(m, i)[0], i)
+
+ im = cv.CreateMatND([2, 13], cv.CV_16UC1)
+ cv.SetZero(im)
+ im[0,0] = 3
+ a = numpy.asarray(im)
+ cvmatnd = cv.fromarray(a)
+ self.assertEqual(cv.GetDims(cvmatnd), (2, 13))
+
+ # im, a and cvmatnd all point to the same data, so...
+ a[0, 1] = 77
+ self.assertEqual(im[0, 1], 77)
+ cvmatnd[1, 0] = 12
+ self.assertEqual(a[1, 0], 12)
+
+ im = cv.CreateMatND([2, 13], cv.CV_16UC3)
+ self.assertEqual(numpy.asarray(im).shape, (2, 13, 3))
+ else:
+ print "SKIPPING test_numpy - numpy support not built"
+
def failing_test_exception(self):
- a = cv.CreateImage((640,480), cv.IPL_DEPTH_8U, 1)
- b = cv.CreateImage((640,480), cv.IPL_DEPTH_8U, 1)
+ a = cv.CreateImage((640, 480), cv.IPL_DEPTH_8U, 1)
+ b = cv.CreateImage((640, 480), cv.IPL_DEPTH_8U, 1)
self.assertRaises(cv.error, lambda: cv.Laplace(a, b))
def test_cvmat_accessors(self):