Broadcast One Channel in Numpy Array into Three Channels

Broadcast one channel in Numpy array into three channels

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
(114L,)
>>> # Apply mask to all channels
>>> pixels = img[mask]
>>> pixels.shape
(114L, 3L)
>>> np.all(pixels[:, 0] == one_channel)
True

How to convert a 1 channel image into a 3 channel with opencv2?

Here's a way of doing that in Python:

img = cv2.imread("D:\\img.jpg")
gray = cv2.cvtColor(img, cv.CV_BGR2GRAY)

img2 = np.zeros_like(img)
img2[:,:,0] = gray
img2[:,:,1] = gray
img2[:,:,2] = gray

cv2.circle(img2, (10,10), 5, (255,255,0))
cv2.imshow("colour again", img2)
cv2.waitKey()

Here's the complete code for OpenCV3:

import cv2
import numpy as np
img = cv2.imread('10524.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img2 = np.zeros_like(img)
img2[:,:,0] = gray
img2[:,:,1] = gray
img2[:,:,2] = gray
cv2.imwrite('10524.jpg', img2)

Get the second channel from a three channels image as a Numpy array

If you are asking about a usage convention, in image processing for machine learning, I usually see each image flattened so that each image is one long row, in row-major order followed by channel order. Numpy has obj.flatten() command to make this easy. Then to retrieve the middle channel, Numpy slicing or indexing can be used. Each processed batch has many images (rows), and each image is one very long flattened row.

Example:

b = a.flatten()  
print(b)
# output array([1, 2, 3, 4, 5, 6, 7, 8, 9])
channel2 = b[3:6]
print(channel2)
# output array([4, 5, 6])

For other use cases, there may be a different convention.

Longer example using a 3x3 image array with 3 channels.

Note numerical values are in row-major order followed by channel order.

img_a = np.arange(0, 27).reshape(3, 3, 3) 
''' output
array([[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8]],

[[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]],

[[18, 19, 20],
[21, 22, 23],
[24, 25, 26]]])
'''
# Flatten into one long row
row_a = img_a.flatten()
# output array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
# 17, 18, 19, 20, 21, 22, 23, 24, 25, 26])

# Select middle channel using Numpy slicing
channel_mid = row_a[9:18]
# output array([ 9, 10, 11, 12, 13, 14, 15, 16, 17])

# Convert middle channel back into a matrix shape (if needed).
matrix_mid = channel_mid.reshape(3, 3)
''' output
array([[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]])
'''

How to convert a 1 channel image into a 3 channel with PIL?

Here's one way without looking too hard at the docs..

fake image:

im = Image.new('P', (16,4), 127)

Get the (pixel) size of the single band image; create a new 3-band image of the same size; use zip to create pixel tuples from the original; put that into the new image..

w, h = im.size
ima = Image.new('RGB', (w,h))
data = zip(im.getdata(), im.getdata(), im.getdata())
ima.putdata(list(data))

Or even possibly

new = im.convert(mode='RGB')

convert a grayscale image to a 3-channel image

You can use np.stack to accomplish this much more concisely:

img = np.array([[1, 2], [3, 4]])
stacked_img = np.stack((img,)*3, axis=-1)
print(stacked_img)
# array([[[1, 1, 1],
# [2, 2, 2]],
# [[3, 3, 3],
# [4, 4, 4]]])

ValueError: could not broadcast input array from shape (300,300,3) into shape (300,300)

Since I was able to identify the problem after some discussion in the comments, I will post it as an answer.

At the line

training_images = np.array([i[0] for i in training_data]).reshape(-1, IMAGE_SIZE, IMAGE_SIZE, 1)

you are attempting to reshape 3-channel RGB images into single channel (greyscale) images, which is not possible (and also not something you want to do, since you want to keep the colours), hence the ValueError. This part was only necessary before you removed img = img.convert('L'), in order to give the training data the proper shape for the model, which had an input shape of (IMAGE_SIZE, IMAGE_SIZE, 1).

Now that you are working with RGB images, the reshape can be removed, since the images will already have the correct shape (IMAGE_SIZE, IMAGE_SIZE, 3) as returned by load_data(). However, as explained in nneonneo's answer, your model will need to be modified to be able to handle the new input shape.

Convert multi-channel PyAudio into NumPy array

It appears to be interleaved sample-by-sample, with left channel first. With signal on left channel input and silence on right channel, I get:

result = [0.2776, -0.0002,  0.2732, -0.0002,  0.2688, -0.0001,  0.2643, -0.0003,  0.2599, ...

So to separate it out into a stereo stream, reshape into a 2D array:

result = np.fromstring(in_data, dtype=np.float32)
result = np.reshape(result, (frames_per_buffer, 2))

Now to access the left channel, use result[:, 0], and for right channel, use result[:, 1].

def decode(in_data, channels):
"""
Convert a byte stream into a 2D numpy array with
shape (chunk_size, channels)

Samples are interleaved, so for a stereo stream with left channel
of [L0, L1, L2, ...] and right channel of [R0, R1, R2, ...], the output
is ordered as [L0, R0, L1, R1, ...]
"""
# TODO: handle data type as parameter, convert between pyaudio/numpy types
result = np.fromstring(in_data, dtype=np.float32)

chunk_length = len(result) / channels
assert chunk_length == int(chunk_length)

result = np.reshape(result, (chunk_length, channels))
return result


def encode(signal):
"""
Convert a 2D numpy array into a byte stream for PyAudio

Signal should be a numpy array with shape (chunk_size, channels)
"""
interleaved = signal.flatten()

# TODO: handle data type as parameter, convert between pyaudio/numpy types
out_data = interleaved.astype(np.float32).tostring()
return out_data

numpy filter across dimensions for specific values

I'm sure you can use select for masking, and ravel to get 1-D array:

array = np.array([[[0,0,0],[128,128,128]],
[[128,128,128],[255,255,0]]
])

label = np.select([(array==(0,0,0)).all(-1), # all make sure all channels are identical
(array==(255,255,0)).all(-1)],
[1,2], 0)

print(label.ravel())

Output:

array([1, 0, 0, 2])


Related Topics



Leave a reply



Submit