Estoy usando el Python Imaging Library para colorear una imagen en blanco y negro con una tabla de búsqueda que define las relaciones de color. La tabla de búsqueda es simplemente una lista de 256 elementos de tuplas RGB:Usando el método Image.point() en PIL para manipular datos de píxeles
>>> len(colors)
256
>>> colors[0]
(255, 237, 237)
>>> colors[127]
(50, 196, 33)
>>>
Mi primera versión utiliza los métodos getpixel()
y putpixel()
:
for x in range(w):
for y in range(h):
pix = img.getpixel((x,y))
img.putpixel((x,y), colors[pix[0]])
Este fue terriblemente lento. Un informe profile
apuntó a los métodos putpixel
y getpixel
como los culpables. Una pequeña investigación (es decir, lea los documentos) y encuentro "Tenga en cuenta que este método es relativamente lento." re: putpixel
. (tiempo de ejecución real: 53s en putpixel
y 50 getpixel
una imagen de 1024x1024 para)
Sobre la base de la sugerencia en la documentación, solía im.load()
y el acceso de píxeles directa en su lugar:
pixels = img.load()
for x in range(w):
for y in range(h):
pix = pixels[x, y]
pixels[x, y] = colors[pix[0]]
procesamiento acelerado por una orden de magnitud, pero sigue siendo lento: aproximadamente 3.5s para procesar una imagen de 1024x1024.
Un estudio más a fondo de los documentos PIL parece indicar Image.point()
es exactamente previsto para este fin:
im.point(table)
=> imagen
im.point(function)
=> imagendevuelve una copia de la imagen donde se ha mapeado cada píxel a través de la tabla dada. La tabla debe contener 256 valores por banda en la imagen. Si se usa una función en su lugar, debería tomar un solo argumento. La función se llama una vez para cada valor de píxel posible, y la tabla resultante se aplica a todas las bandas de la imagen.
He pasado algún tiempo pirateando la interfaz, pero parece que no puedo hacerlo bien. Perdona mi ignorancia, pero los documentos de PIL son escuetos y no tengo mucha experiencia en el procesamiento de imágenes. Busqué en Google un poco y encontré algunos ejemplos, pero nada que hiciera que el uso "haga clic" para mí. Por lo tanto, finalmente, mis preguntas:
- ¿Es
Image.point()
la herramienta adecuada para este trabajo? - ¿Qué formato/estructura tiene
Image.point()
esperan la tabla? - ¿Alguien puede dar un paso atrás en una implementación de ejemplo? Cada iteración que he intentado hasta ahora ha terminado con una imagen negra recta.
aplanar la lista? vale, pero ¿cómo funciona eso? Quiero píxeles con valor 0 -> (12, 140, 10) y píxeles con valor 255 -> (254, 237, 220). –
ya sabes, creo que este podría ser el único lugar en Internet donde se describe el formato esperado de esa tabla. // Acabo de obtener img.point() trabajando con la tabla de búsqueda, gracias a su descripción. Los resultados no son exactamente los que esperaba, pero tengo lo suficiente como para hackearlos y resolverlos. ¡Muchas gracias! –
@ J.J., El formato no es realmente obvio. Cometí un error en mi primera explicación y lo arreglé ahora. Espero haberlo hecho bien esta vez. Me voy a dormir, así que no podré responder preguntas. –