Numpy.putmask con imágenes

Tengo una imagen convertida en un ndarray con valores RGBA. Supongamos que es 50 x 50 x 4.

Quiero reemplazar todos los píxeles con valores array([255, 255, 255, 255]) para array([0, 0, 0, 0]) . Asi que:

 from numpy import * from PIL import Image def test(mask): mask = array(mask) find = array([255, 255, 255, 255]) replace = array([0, 0, 0, 0]) return putmask(mask, mask != find, replace) mask = Image.open('test.png') test(mask) 

¿Qué estoy haciendo mal? Eso me da un ValueError: putmask: mask and data must be the same size . Sin embargo, si cambio las matrices a números (buscar = 255, reemplazar = 0) funciona.

Una forma de hacer este tipo de enmascaramiento de canales es dividir la matriz en r, g, b, a, canales, y luego definir el índice utilizando numerosas operaciones de bits lógicos:

 import numpy as np import Image def blackout(img): arr = np.array(img) r,g,b,a=arr.T idx = ((r==255) & (g==255) & (b==255) & (a==255)).T arr[idx]=0 return arr img = Image.open('test.png') mask=blackout(img) img2=Image.fromarray(mask,mode='RGBA') img2.show() 

Una forma más concisa de hacer esto es

 img = Image.open('test.png') a = numpy.array(img) a[(a == 255).all(axis=-1)] = 0 img2 = Image.fromarray(a, mode='RGBA') 

Más generalmente, si los elementos de find y repl no son todos iguales, también puede hacer

 find = [1, 2, 3, 4] repl = [5, 6, 7, 8] a[(a == find).all(axis=-1)] = repl 

Esta solución utiliza putmask y creo que es la más cercana al código OP. Hay dos errores en el código original que el OP debe conocer: 1) putmask es una operación in situ. Devuelve None . 2) putmask también requiere matrices de igual tamaño. (Lástima) no tiene un argumento de palabra clave de axis .

 import numpy as np from PIL import Image img1 = Image.open('test.png') arry = np.array(img1) find = np.array([255, 255, 255, 255]) repl = np.array([ 0, 0, 0, 0]) # this is the closest to the OPs code I could come up with that # compares each pixel array with the 'find' array mask = np.all(arry==find, axis=2) # I iterate here just in case repl is not always the same value for i,rep in enumerate(repl): # putmask works in-place - returns None np.putmask(arry[:,:,i], mask, rep) img2 = Image.fromarray(arry, mode='RGBA') img2.save('testx.png')