Как преобразовать вид массива в матрицу opencv?

Я использую opencv v2.2 для сопоставления некоторых шаблонов на ndarrays, и у меня возникли большие проблемы с утечками памяти при использовании их метода обернутых cv.fromarray(), Вместо того, чтобы подключить утечки памяти, я избежал fromarray() функция и используется cv.SetData прямо так:

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])

Это, кажется, решить утечки памяти и foo_cv кажется, что он освобождается должным образом, когда он выходит из области видимости. Тем не менее, теперь у меня есть проблема, где, если foo_numpy это просто фрагмент / просмотр большего массива, мне не разрешено foo_numpy.data (невозможно получить односегментный буфер для несмежного массива). На данный момент я работаю над этим, делая foo_numpy.copy() если foo_numpy.base != None, что позволяет получить буфер для новой копии. Но я чувствую, что это не нужно, срез имеет __array_struct__ а также __array_interface__ так что я должен быть в состоянии просто шагнуть с соответствующими размерами ступеней? Я не уверен, как сделать это хорошим способом, потому что основой этого также может быть представление о другом большем массиве до бесконечности.

1 ответ

Я думаю, что проблема с тем, что вы пытались сделать, состоит в том, что данные массива вас интересуют (т.е. foo_np_view) на самом деле хранится только в одном месте, т.е. foo_np.dataи OpenCV SetData Метод не предоставляет никакого способа указать настройки шага, которые позволили бы вам пропустить байты, которые не являются частью foo_np_view,

Вы можете, однако, обойти эту проблему, используя Numpy's tostring() метод, который превращает массив (или представления в нем) в байтовую строку:

>>> 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 )

Воссоздание исходной проблемы:

>>> 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

С использованием tostring() метод (см. ниже для объяснения настройки шага):

>>> 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

Значение w * d * foo_np_view.dtype.itemsize дает нам значение шага, идентичное значению foo_np_view.copy(), что необходимо, поскольку строковые представления вида и его копии идентичны:

>>> foo_np_view.copy().tostring() == foo_np_view.tostring()
True
>>> foo_np_view.copy().strides[0] == w * d * foo_np_view.dtype.itemsize
True
Другие вопросы по тегам