Abdul Fatir Abdul Fatir - 2 years ago 212
Python Question

Copy channels in Numpy array

I have a RGB image

which is of shape
(2560L, 1920L, 3L)
and another single channel image
which is of shape
(2560L, 1920L)
. Now, I want to make this
of shape
(2560L, 1920L, 3L)
i.e. I want to copy this single channel data into all the three channels.

I'm doing it as follows.

np.array([[[j,j,j] for j in i] for i in mask])

Is there a faster way of doing this using

val val
Answer Source

If you absolutely want to have the mask being (2560, 1920, 3), you can simply expand it along an axis (there are several ways to do that, but this one is quite straightforward):

>>> mask = np.random.random_integers(0, 255, (15, 12))
>>> mask_3d = mask[:, :, None] * np.ones(3, dtype=int)[None, None, :]
>>> mask.shape
(15L, 12L)
>>> mask_3d.shape
(15L, 12L, 3L)

However, in general, you can use these broadcasts directly. For instance, if you want to multiply your image by your mask:

>>> img = np.random.random_integers(0, 255, (15, 12, 3))
>>> img.shape
(15L, 12L, 3L)
>>> converted = img * mask[:, :, None]
>>> converted.shape
(15L, 12L, 3L)

So you never have to create the (n, m, 3) mask: broadcasting is done on the fly by manipulating the strides of the mask array, rather than creating a bigger, redundant one. Most of the numpy operations support this kind of broadcasting: binary operations (as above), but also indexing:

>>> # Take the lower part of the image
>>> mask = np.tri(15, 12, dtype=bool)
>>> # Apply mask to first channel
>>> one_channel = img[:, :, 0][mask]
>>> one_channel.shape
>>> # Apply mask to all channels
>>> pixels = img[mask]
>>> pixels.shape
(114L, 3L)
>>> np.all(pixels[:, 0] == one_channel)
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download