Abdul Fatir - 2 years ago 212
Python Question

Copy channels in Numpy array

I have a RGB image

`img`
which is of shape
`(2560L, 1920L, 3L)`
and another single channel image
`mask`
which is of shape
`(2560L, 1920L)`
. Now, I want to make this
`mask`
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
`numpy`
?

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))
(15L, 12L)
(15L, 12L, 3L)
``````

``````>>> 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
(114L,)
>>> # Apply mask to all channels