changing alpha-channel of select-pixels of image using numpy

Question:

Relatively new to numpy – trying to use it for image-processing; I have an image in the RGBA color-space; the image is mostly transparent w/ a small-object whose transparency I want to change from 255 to 127, without affecting the transparency of surrounding pixels whose alpha is 0. I can index into the array and find all the groups of pixels I want, but am struggling on how to actually change their alpha-channels to 127 w/o affecting the alpha-channels of all the pixels; here is how I am indexing into the array – the things I’ve tried either do not affect the array or else reassign all the alphas in the entire array to 127:

>>> from PIL import Image
>>> import numpy as np
>>> a = Image.open('a.png')
>>> b = np.array(a)
>>> b.shape
(1080, 1080, 4)
>>> b[b[:,:,3]==255][:,3]
array([255, 255, 255, ..., 255, 255, 255], dtype=uint8)
>>> b[b[:,:,3]==255][:,3] = 127
>>> b[b[:,:,3]==255][:,3]
array([255, 255, 255, ..., 255, 255, 255], dtype=uint8)

Solution:

>>> b[540,540]
array([  0,   0,   0, 255], dtype=uint8)
>>> alpha = b[:,:,3]
>>> b[alpha==255,3]=127
>>> b[540,540]
array([  0,   0,   0, 127], dtype=uint8)
Asked By: user18615293

||

Answers:

It’s because double slicing the array will produce a view of the copy of the array. That’s why your array will not be updated. Instead, you can put it together in one slice.

b[b[:,:,3]==255,3] = 127

I would do it like this. I am actually changing 128 to 255 because it’s easier to display:

#!/usr/bin/env python3

from PIL import Image
import numpy as np

# Make solid red image
im = np.full((100,300,4), [255,0,0,255], np.uint8)

im[20:80, 20:80,   3] =  64  # 25% opaque square on left
im[20:80, 120:180, 3] = 128  # 50% opaque square in centre
im[20:80, 220:280, 3] = 192  # 75% opaque square on right

Image.fromarray(im).save('start.png')

enter image description here

# Now define easy way to refer to alpha channel
alpha = im[:, :, 3]

# Anywhere alpha is 128, change it to 255
alpha[alpha==128] = 255

Image.fromarray(im).save('result.png')

enter image description here

Answered By: Mark Setchell