How to convert numpy array to opencv matrix?

I use opencv v2.2 to do pattern matching on ndarrays and I had big problems with memory leaks when using their wrapped cv.fromarray() method. Instead of plugging in memory leaks, I avoided the fromarray() function and used cv.SetData directly, for example:

 assert foo_numpy.dtype == 'uint8' assert foo_numpy.ndim == 3 h, w = foo_numpy.shape[:2] foo_cv = cv.CreateMat(h, w, cv.CV_8UC3) cv.SetData(foo_cv, foo_numpy.data, foo_numpy.strides[0]) 

This seems to foo_cv memory leaks, and foo_cv seems to be freed properly when it goes out of scope. However, now I have a problem: if foo_numpy is just a fragment / view for a larger array, I am not allowed to foo_numpy.data (it is impossible to get a single-segment buffer for an unbiased array). I'm currently working on this by creating foo_numpy.copy() if foo_numpy.base != None , which allows foo_numpy.base != None to get a buffer on a new copy. But I have the feeling that this is not necessary, the slice has __array_struct__ and __array_interface__ , so I have to somehow somehow stagger it using the appropriate steps. I am not sure how to do it beautifully, because the base of this can also be a view on another larger ad infinitum array.

+4
source share
1 answer

I think the problem with what you were trying to do is that the data of the array you are interested in (i.e. foo_np_view ) is actually stored in only one place, i.e. foo_np.data , and the OpenCV SetData method SetData not allow you to specify step parameters that allow you to skip bytes that are not part of foo_np_view .

However, you can work around this problem by using the Numpys tostring() method, which turns the array (or views in it) into a byte string:

 >>> import numpy as np >>> import cv >>> foo_np = np.array( 255 * np.random.rand( 200 , 300 , 3 ), dtype = 'uint8' ) >>> foo_np_view = foo_np [ 50:150:2 , 10:290:5 , : ] >>> h,w,d = foo_np_view.shape >>> foo_cv = cv.CreateMat( h , w , cv.CV_8UC3 ) 

Recreating the original problem:

 >>> cv.SetData( foo_cv , foo_np_view.data, foo_np_view.strides[0] ) Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: cannot get single-segment buffer for discontiguous array 

Using the tostring() method (see explanation of step setup below):

 >>> cv.SetData( foo_cv , foo_np_view.tostring() , w * d * foo_np_view.dtype.itemsize ) >>> np.array_equal( np.asarray( foo_cv ) , foo_np_view ) True 

The value w * d * foo_np_view.dtype.itemsize gives us the step value identical to the value foo_np_view.copy() , which is necessary since the string representations of the view and its copies are identical:

 >>> foo_np_view.copy().tostring() == foo_np_view.tostring() True >>> foo_np_view.copy().strides[0] == w * d * foo_np_view.dtype.itemsize True 
+2
source

Source: https://habr.com/ru/post/1347021/


All Articles