[PYTHON] Remplacez rapidement les couleurs de l'image par PIL / Pillow

Lors du remplacement des couleurs par PIL / Pillow, le moyen le plus simple de trouver est d'utiliser Image.getpixel / Image.putpixel.

Cependant, Image.getpixel / Image.putpixel est si lent qu'il faut quelques secondes pour traiter une seule image, ce qui est très lent. Il existe une méthode de remplacement rapide utilisant numpy, mais il semble insensé d'augmenter le nombre de modules dépendants lors du remplacement des couleurs.

Par conséquent, j'ai pensé à une méthode pour remplacer les couleurs à grande vitesse avec uniquement PIL / Pillow.

À titre d'exemple, remplaçons la couleur des vêtements (255, 204, 0) dans l'image ci-dessous par (48, 255, 48).

sample.png  result.png

L'image est RVB 24 bits sans alpha et le code est écrit en python2.

Séparez les images par couleur

Tout d'abord, utilisez Image.split pour diviser l'image en bandes pour chaque couleur.

from __future__ import unicode_literals, print_function, absolute_import
from PIL import Image, ImageChops

img = Image.open("sample.png ")

r, g, b = img.split()

Le contenu de chaque bande RVB est le suivant.

r.png g.png b.png

Binariser pour chaque couleur spécifique dans Image.point

src_color = (255, 204, 0)

_r = r.point(lambda _: 1 if _ == src_color[0] else 0, mode="1")
_g = g.point(lambda _: 1 if _ == src_color[1] else 0, mode="1")
_b = b.point(lambda _: 1 if _ == src_color[2] else 0, mode="1")

Image.point est une méthode de conversion de table. Cette fois, lambda est utilisé pour générer une image qui extrait uniquement des valeurs spécifiques pour chaque bande.

Le fait est que mode = "1" est spécifié dans l'argument, et si "1" est spécifié dans mode, une image avec une profondeur de couleur de 1 bit est générée. Il s'agit du processus requis pour la conversion dans le module ImageChops décrit plus loin.

Le contenu de chaque bande RVB est le suivant.

_r.png _g.png _b.png

ET composez chaque bande pour générer un masque

Le module ImageChops est un module pratique qui peut effectuer divers processus de composition tels que la composition d'addition et la composition de multiplication.

Cette fois, la composition ET est effectuée à l'aide de ImageChops.logical_and. Cette méthode n'accepte que les images avec mode = "1".

mask = ImageChops.logical_and(_r, _g)
mask = ImageChops.logical_and(mask, _b)

Vous pouvez créer un masque qui extrait les pixels de 1 dans toutes les bandes (c'est-à-dire une couleur spécifique).

mask.png

Tout ce que vous avez à faire est d'utiliser ce masque pour peindre la couleur que vous souhaitez remplacer.

dst_color = (48,255,48)
img.paste(Image.new("RGB", img.size, dst_color), mask=mask)

vitesse de traitement

J'ai comparé le traitement avec le cas de l'utilisation de getpixel / putpixel.

In [27]: %time replace_put_pixel(img, src_color, dst_color)
Wall time: 234 ms

In [28]: %time replace_fast(img, src_color, dst_color)
Wall time: 1.96 ms

La version getpixel / putpixel a 234 ms, tandis que cette méthode a 1,96 ms. C'est plus de 100 fois plus rapide.

Recommended Posts

Remplacez rapidement les couleurs de l'image par PIL / Pillow
Traitement d'image avec PIL (Pillow)
Traitement d'image avec PIL
Créez une image factice avec Python + PIL.
Générez de nombreuses images à un seul caractère avec Pillow (PIL)
Utilisez PIL ou Pillow avec Cygwin Python
J'ai essayé de jouer avec l'image avec Pillow
Traitez facilement des images en Python avec Pillow
Créez une application de composition d'images avec Flask + Pillow
Installation PIL avec pip
Aide-mémoire PIL / Pillow
Reconnaissance d'image avec keras
Traitement d'image avec Python
Convertir l'espace colorimétrique RVB en CIELAB avec PIL (Pillow)