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)
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.
Asked: 2012-07-15 10:35:30 -0500
Seen: 359 times
Last updated: Jul 16 '12
can't imread or imwrite in python
Initialize numpy array (cv2 python) and PerspectiveTransform
Problem using opencv with python in mac os x 10.6.8
Python binding plays video very slow
How to display fullscreen in Python on Linux? (setWindowProperty doesn't work)
cv2.perspectiveTransform() with Python
cv.Remap (dst.size() == mapx.size()) assertion question
how to understand which functions available in python bindings?