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