Ask Your Question
1

cv2 bindings incompatible with numpy.dstack function?

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

Tristan gravatar image Tristan
13 3

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

Andrey Pavlenko gravatar image Andrey Pavlenko
2294 3 15 37

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)
delete close flag offensive retag edit

1 Answer

Sort by ยป oldest newest most voted
4

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

blue gravatar image blue
191 3

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.

link delete flag offensive edit

Comments

Great answer!

Philipp Wagner ( 2012-07-16 14:41:29 -0500 )edit

Login/Signup to Answer

Question tools

Follow

subscribe to rss feed

Stats

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

Seen: 707 times

Last updated: Jul 16 '12