À l'aide de l'Image.point() méthode dans le PIL pour manipuler les données de pixel
Je suis en utilisant le Python Imaging Library pour coloriser une image noir et blanc avec une table qui définit la couleur des liens. La table de recherche est tout simplement un 256-élément de la liste de RVB tuples:
>>> len(colors)
256
>>> colors[0]
(255, 237, 237)
>>> colors[127]
(50, 196, 33)
>>>
Ma première version utilisé le getpixel()
et putpixel()
méthodes:
for x in range(w):
for y in range(h):
pix = img.getpixel((x,y))
img.putpixel((x,y), colors[pix[0]])
C'était horriblement lent. Un profile
rapport a souligné la putpixel
et getpixel
méthodes comme les coupables. Une petite enquête (j'.e, lire les docs) et je trouve que "Noter que cette méthode est relativement lente." re: putpixel
. (réelle de l'exécution: 53s dans putpixel
et 50 getpixel
pour une image de 1024x1024)
Basé sur la suggestion dans les docs, j'ai utilisé im.load()
et l'accès direct aux pixels à la place:
pixels = img.load()
for x in range(w):
for y in range(h):
pix = pixels[x, y]
pixels[x, y] = colors[pix[0]]
Traitement accéléré par un ordre de grandeur, mais il est encore lent: environ 3,5 s pour traiter une image de 1024x1024.
Une étude plus approfondie de la PIL docs semble indiquer Image.point()
est exactement prévu à cet effet:
im.point(table)
=> image
im.point(function)
=> imageRenvoie une copie de l'image où chaque pixel a été cartographiée par le biais de la table donnée. La table contient 256 valeurs par bande dans l'image. Si une fonction est utilisée au lieu de cela, il devrait prendre qu'un seul argument. La fonction est appelée une fois pour chaque valeur de pixel, et la table résultante est appliquée à toutes les bandes de l'image.
J'ai passé un peu de temps piratage autour de l'interface, mais n'arrive pas à sembler obtenir ce droit. Pardonnez mon ignorance, mais PIL de docs sont curt et je n'ai pas beaucoup de traitement de l'image de l'expérience. J'ai googlé un peu et tourna quelques exemples, mais rien que le fait de l'utilisation de "cliquer" pour moi. Ainsi, finalement, mes questions:
- Est
Image.point()
le bon outil pour ce travail? - Quel format/structure ne
Image.point()
s'attendre à la table? - Quelqu'un peut ébaucher un exemple de mise en œuvre? Chaque itération que j'ai essayé jusqu'à présent, a terminé avec une noire droite de l'image.
Vous devez vous connecter pour publier un commentaire.
Oui en effet,
Image.point()
est parfait pour ce travailVous devez l'aplatir la liste de sorte qu'au lieu de
[(12, 140, 10), (10, 100, 200), ...]
utilisation:Voici un exemple rapide, j'ai juste essayé:
Et par la manière, si vous avez besoin de plus de contrôle sur les couleurs et vous vous sentez à l'Image.le point n'est pas pour vous, vous pouvez également utiliser
Image.getdata
etImage.putdata
pour changer les couleurs plus rapidement que les deuxload
etputpixel
. Il est plus lent queImage.point
bien.Image.getdata
vous donne la liste de tous les pixels, de les modifier et de les réécrire à l'aide deImage.putdata
. C'est aussi simple que cela. Mais essayer de le faire à l'aide deImage.point
premier.MODIFIER
J'ai fait une erreur dans la première explication, je vais vous expliquer correctement maintenant:
La table des couleurs en fait, c'est comme cela
Chaque bande de plage à côté de l'autre.
Pour changer la couleur (0, 0, 0) à (10, 100, 10), il faut devenir comme ceci:
Pour transformer votre liste de couleurs dans le bon format, essayez ceci:
Je crois que mon premier exemple doit démontrer la formate pour vous.
Je pense qu'il pourrait être plus typique de
point
, bande par bande, comme (levées directement à partir de la PIL tutoriel):