Ask Your Question
1

cv2 bindings incompatible with numpy.dstack function?

asked 2012-07-15 10:35:30 -0600

Tristan gravatar image

updated 2012-07-16 07:09:29 -0600

Andrey Pavlenko gravatar image

Hi,

scratched my head for an hour or so on something rather annoying. When trying to turn a single channel image into a 3 channels one using numpy.dstack, the resulting array seems to upset the cv2 bindings.I finally found cv2.merge to work around that, but I just wanted to ask if this was expected.

Also any numpy expert with an explanation as to why dstack'd arrays might upset cv2 bindings (I suspect something with the internal representation)?

Also this might save some time to someone else :)

As you can see with the following code, cv2.merge gives a perfectly usable array, whereas the result of numpy.dstack doesn't get much love from cv2 (numpy is happy with it though).


tristan@tristan-laptop:/tmp$ python
Python 2.7.3 (default, Apr 20 2012, 22:44:07) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> np.version.full_version
'1.6.2'
>>> import cv2
>>> cv2.__version__
'2.4.2'
>>> channel = np.arange(240 * 320, dtype=np.uint8).reshape(240, 320, 1)
>>> cv2.convertScaleAbs(channel)
array([[  0,   1,   2, ...,  61,  62,  63],
       [ 64,  65,  66, ..., 125, 126, 127],
       [128, 129, 130, ..., 189, 190, 191],
       ..., 
       [ 64,  65,  66, ..., 125, 126, 127],
       [128, 129, 130, ..., 189, 190, 191],
       [192, 193, 194, ..., 253, 254, 255]], dtype=uint8)
>>> merged = cv2.merge([channel for i in range(3)])
>>> stacked = np.dstack([channel for i in range(3)])
>>> np.all(stacked == merged)
True
>>> stacked.ndim, stacked.shape, stacked.dtype
(3, (240, 320, 3), dtype('uint8'))
>>> merged.ndim, merged.shape, merged.dtype
(3, (240, 320, 3), dtype('uint8'))
>>> cv2.convertScaleAbs(merged)
array([[[  0,   0,   0],
        [  1,   1,   1],
        [  2,   2,   2],
        ..., 
#[... more print array output skipped ...]
>>> cv2.convertScaleAbs(stacked)
OpenCV Error: Assertion failed (src.dims <= 2 && esz <= (size_t)32) in transpose, file /tmp/buildd/ros-fuerte-opencv2-2.4.2-0precise-20120704-1846/modules/core/src/matrix.cpp, line 1877
terminate called after throwing an instance of 'cv::Exception'
  what():  /tmp/buildd/ros-fuerte-opencv2-2.4.2-0precise-20120704-1846/modules/core/src/matrix.cpp:1877: error: (-215) src.dims <= 2 && esz <= (size_t)32 in function transpose

Aborted (core dumped)
edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
4

answered 2012-07-16 14:01:04 -0600

blue gravatar image

The problem is the way dstack constructs the array:

In [1]: import cv2

In [2]: channel = np.arange(240 * 320, dtype=np.uint8).reshape(240, 320, 1)

In [3]: merged = cv2.merge([channel for i in range(3)])

In [4]: stacked = np.dstack([channel for i in range(3)])

In [5]: stacked.strides
Out[5]: (1, 240, 76800)

In [6]: merged.strides
Out[6]: (960, 3, 1)

In order to reshape and stack the arrays in them manner you requested, numpy only modifies the strides through the array, it does not move the data around. merge appears to actually move the data around.

I think OpenCV can represent arrays stored in this fashion, but the python wrappers for OpenCV do not perform this translation.

See here for more information about numpy's strided array storage.

edit flag offensive delete link more

Comments

Great answer!

Philipp Wagner gravatar imagePhilipp Wagner ( 2012-07-16 14:41:29 -0600 )edit

Question Tools

Stats

Asked: 2012-07-15 10:35:30 -0600

Seen: 5,313 times

Last updated: Jul 16 '12