RJ Uy
RJ Uy

Reputation: 397

Change RGB value to a single value by converting its RGB without a loop

Say I have a coloured image img. Now, I want to create a new NumPy array based on the RGB value of the image. I can do this by doing a loop, based on img values and compute the new array value based on the RGB values: say, newVal = R * val + G * val2 + B * val3. The newVal will then be appended to a NumPy array variable newNumpyVar.

Say I have this

img = [[[1 2 3] [0 0 1] [ 1 1 1]] [[0 0 0] [1 1 1] [ 0 0 0]]]

Its a 3 x 2 image. The results should be a 6 newVal array. 1st array is 1*1 + 2*2 + 3*3, 2nd array is = 0*1 + 0*2 + 1*3, 3rd is = 1*1 + 1*2 + 1*3 and so on.

I know that there is a way to do this in a NumPysh way. But I just don't know how.

Upvotes: 1

Views: 867

Answers (2)

Mad Physicist
Mad Physicist

Reputation: 114330

You are looking for a sum-product of your image with a list of weights. If you have an image img of shape (M, N, 3) and weights vR, vG, vB, you can do any of the following to get a weighted (M, N) image:

img @ [vR, vG, vB]
np.dot(img, [vR, vG, vB])
np.einsum('mnc,c->mn', img, [vR, vG, vB])
np.sum(img * [vR, vG, vB], axis=-1)

Upvotes: 1

GPhilo
GPhilo

Reputation: 19123

Simplest, but without control of how much each channel contributes (color_im is a numpy array):

gray_im = color_im.mean(axis=-1)

With weights:

gray_im = color_im[...,0]*R_weight + color_im[...,1]*G_weight + color_im[...,2]*B_weight # assumes RGB ordering of channels

The weighted version can be equivalently rewritten as:

gray_im = (color_im * np.array([R_weight, G_weight, B_weight])).sum(axis=-1)

Upvotes: 1

Related Questions