@@ -8,8 +8,88 @@ namespace cvnp
88
99 namespace detail
1010 {
11+ // #define DEBUG_ALLOCATOR
12+
13+ #ifdef DEBUG_ALLOCATOR
14+ int nbAllocations = 0 ;
15+ #endif
16+
1117 namespace py = pybind11;
12-
18+
19+ // Translated from cv2_numpy.cpp in OpenCV source code
20+ class CvnpAllocator : public cv ::MatAllocator
21+ {
22+ public:
23+ CvnpAllocator () = default ;
24+ ~CvnpAllocator () = default ;
25+
26+ // Attaches a numpy array object to a cv::Mat
27+ static void attach_nparray (cv::Mat &m, pybind11::array& a)
28+ {
29+ static CvnpAllocator instance;
30+
31+ cv::UMatData* u = new cv::UMatData (&instance);
32+ u->data = u->origdata = (uchar*)a.mutable_data (0 );
33+ u->size = a.size ();
34+ u->userdata = a.inc_ref ().ptr ();
35+ u->refcount = 1 ;
36+
37+ #ifdef DEBUG_ALLOCATOR
38+ ++nbAllocations;
39+ printf (" CvnpAllocator::attach_nparray(py::array) nbAllocations=%d\n " , nbAllocations);
40+ #endif
41+
42+ m.u = u;
43+ m.allocator = &instance;
44+ }
45+
46+ cv::UMatData* allocate (int dims0, const int * sizes, int type, void * data, size_t * step, cv::AccessFlag flags, cv::UMatUsageFlags usageFlags) const override
47+ {
48+ throw py::value_error (" CvnpAllocator::allocate \" standard\" should never happen" );
49+ // return stdAllocator->allocate(dims0, sizes, type, data, step, flags, usageFlags);
50+ }
51+
52+ bool allocate (cv::UMatData* u, cv::AccessFlag accessFlags, cv::UMatUsageFlags usageFlags) const override
53+ {
54+ throw py::value_error (" CvnpAllocator::allocate \" copy\" should never happen" );
55+ // return stdAllocator->allocate(u, accessFlags, usageFlags);
56+ }
57+
58+ void deallocate (cv::UMatData* u) const override
59+ {
60+ if (!u)
61+ {
62+ #ifdef DEBUG_ALLOCATOR
63+ printf (" CvnpAllocator::deallocate() with null ptr!!! nbAllocations=%d\n " , nbAllocations);
64+ #endif
65+ return ;
66+ }
67+
68+ // This function can be called from anywhere, so need the GIL
69+ py::gil_scoped_acquire gil;
70+ assert (u->urefcount >= 0 );
71+ assert (u->refcount >= 0 );
72+ if (u->refcount == 0 )
73+ {
74+ PyObject* o = (PyObject*)u->userdata ;
75+ Py_XDECREF (o);
76+ delete u;
77+ #ifdef DEBUG_ALLOCATOR
78+ --nbAllocations;
79+ printf (" CvnpAllocator::deallocate() nbAllocations=%d\n " , nbAllocations);
80+ #endif
81+ }
82+ else
83+ {
84+ #ifdef DEBUG_ALLOCATOR
85+ printf (" CvnpAllocator::deallocate() - not doing anything since urefcount=%d nbAllocations=%d\n " ,
86+ u->urefcount ,
87+ nbAllocations);
88+ #endif
89+ }
90+ }
91+ };
92+
1393 py::dtype determine_np_dtype (int cv_depth)
1494 {
1595 for (auto format_synonym : cvnp::sTypeSynonyms )
@@ -127,10 +207,15 @@ namespace cvnp
127207 int type = detail::determine_cv_type (a, depth);
128208 cv::Size size = detail::determine_cv_size (a);
129209 cv::Mat m (size, type, is_not_empty ? a.mutable_data (0 ) : nullptr );
210+
211+ if (is_not_empty) {
212+ detail::CvnpAllocator::attach_nparray (m, a); // , ndims, size, type, step);
213+ }
214+
130215 return m;
131216 }
132217
133- // this version tries to handles strides and submatrices
218+ // this version tries to handle strides and sub-matrices
134219 // this is WIP, currently broken, and not used
135220 cv::Mat nparray_to_mat_with_strides_broken (pybind11::array& a)
136221 {
0 commit comments