Skip to content

Commit 6a81d86

Browse files
committed
Fix ndarray_to_mat to copy if needed
Fixes #16
1 parent 9e4649f commit 6a81d86

File tree

1 file changed

+26
-1
lines changed

1 file changed

+26
-1
lines changed

src/convert.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ Mat ndarray_to_mat(ndarray_obj_t *ndarray)
6060
// We have an ndarray_obj_t, so these checks have already been done.
6161

6262
// https://github.com/opencv/opencv/blob/aee828ac6ed3e45d7ca359d125349a570ca4e098/modules/python/src2/cv2_convert.cpp#L130-L172
63+
bool needcopy = false;
6364
int type = ndarray_type_to_mat_depth(ndarray->dtype);
6465

6566
int ndims = ndarray->ndim;
@@ -71,17 +72,41 @@ Mat ndarray_to_mat(ndarray_obj_t *ndarray)
7172
_strides[i] = ndarray->strides[ULAB_MAX_DIMS - ndarray->ndim + i];
7273
}
7374

74-
// https://github.com/opencv/opencv/blob/aee828ac6ed3e45d7ca359d125349a570ca4e098/modules/python/src2/cv2_convert.cpp#L176-L221
75+
// https://github.com/opencv/opencv/blob/aee828ac6ed3e45d7ca359d125349a570ca4e098/modules/python/src2/cv2_convert.cpp#L176-L241
7576
bool ismultichannel = ndims == 3;
7677

78+
for( int i = ndims-1; i >= 0 && !needcopy; i-- )
79+
{
80+
// these checks handle cases of
81+
// a) multi-dimensional (ndims > 2) arrays, as well as simpler 1- and 2-dimensional cases
82+
// b) transposed arrays, where _strides[] elements go in non-descending order
83+
// c) flipped arrays, where some of _strides[] elements are negative
84+
// the _sizes[i] > 1 is needed to avoid spurious copies when NPY_RELAXED_STRIDES is set
85+
if( (i == ndims-1 && _sizes[i] > 1 && (size_t)_strides[i] != elemsize) ||
86+
(i < ndims-1 && _sizes[i] > 1 && _strides[i] < _strides[i+1]) )
87+
needcopy = true;
88+
}
89+
7790
if (ismultichannel)
7891
{
7992
int channels = ndims >= 1 ? (int)_sizes[ndims - 1] : 1;
8093
ndims--;
8194
type |= CV_MAKETYPE(0, channels);
95+
96+
if (ndims >= 1 && _strides[ndims - 1] != (size_t)elemsize*_sizes[ndims])
97+
needcopy = true;
98+
8299
elemsize = CV_ELEM_SIZE(type);
83100
}
84101

102+
if (needcopy)
103+
{
104+
ndarray = ndarray_from_mp_obj(ndarray_copy(ndarray), 0);
105+
for (int i = 0; i < ndarray->ndim; i++) {
106+
_strides[i] = ndarray->strides[ULAB_MAX_DIMS - ndarray->ndim + i];
107+
}
108+
}
109+
85110
// https://github.com/opencv/opencv/blob/aee828ac6ed3e45d7ca359d125349a570ca4e098/modules/python/src2/cv2_convert.cpp#L243-L261
86111
int size[CV_MAX_DIM+1] = {};
87112
size_t step[CV_MAX_DIM+1] = {};

0 commit comments

Comments
 (0)