Я думаю, что проблема с тем, что вы пытались сделать, заключается в том, что интересующие вас массивы данных (т.е. foo_np_view
) на самом деле хранятся только в одном месте, т.е. foo_np.data
, и метод OpenCV SetData
. не предоставляет никакого способа указать настройки шага, которые позволили бы вам пропускать байты, которые не являются частью foo_np_view
.
Однако вы можете обойти эту проблему, используя метод tostring()
Numpy, который превращает массив (или представления в нем) в байтовую строку:
>>> 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