Comment puis-je enregistrer une image avec PIL?

119

Je viens de faire un traitement d'image en utilisant la bibliothèque d'images Python (PIL) en utilisant un article que j'ai trouvé plus tôt pour effectuer des transformations de Fourier des images et je ne parviens pas à faire fonctionner la fonction de sauvegarde. L'ensemble du code fonctionne bien mais il ne sauvera pas l'image résultante:

from PIL import Image
import numpy as np

i = Image.open("C:/Users/User/Desktop/mesh.bmp")
i = i.convert("L")
a = np.asarray(i)
b = np.abs(np.fft.rfft2(a))
j = Image.fromarray(b)
j.save("C:/Users/User/Desktop/mesh_trans",".bmp")

L'erreur que j'obtiens est la suivante:

save_handler = SAVE[string.upper(format)] # unknown format
    KeyError: '.BMP'

Comment puis-je enregistrer une image avec Pythons PIL?

user1999274
la source

Réponses:

144

L'erreur concernant l'extension de fichier a été gérée, soit vous utilisez BMP(sans le point), soit vous passez le nom de sortie avec l'extension déjà. Maintenant, pour gérer l'erreur, vous devez modifier correctement vos données dans le domaine de fréquence à enregistrer en tant qu'image entière, PILcela vous indique qu'il n'accepte pas les données flottantes à enregistrer en BMP.

Voici une suggestion (avec d'autres modifications mineures, comme utiliser fftshiftet numpy.arrayau lieu de numpy.asarray) pour effectuer la conversion pour une visualisation correcte:

import sys
import numpy
from PIL import Image

img = Image.open(sys.argv[1]).convert('L')

im = numpy.array(img)
fft_mag = numpy.abs(numpy.fft.fftshift(numpy.fft.fft2(im)))

visual = numpy.log(fft_mag)
visual = (visual - visual.min()) / (visual.max() - visual.min())

result = Image.fromarray((visual * 255).astype(numpy.uint8))
result.save('out.bmp')
mmgp
la source
1
hé merci beaucoup. cela fonctionne parfaitement maintenant! maintenant tout ce que j'ai à faire est de comprendre toutes les étapes, mais ce ne sera pas trop mal. merci beaucoup pour l'aide
user1999274
@ user1999274 la différence majeure réside dans l'utilisation de fft2au lieu de rfft2puisque pour les données discrètes, je ne vois pas l'intérêt d'utiliser le plus tard. Le reste est purement cosmétique, c'est-à-dire que vous ne pourriez pas visualiser correctement la transformée de Fourier sans lui appliquer un facteur log. Ensuite, la normalisation consiste à simplifier les choses pour la conversion vers la plage [0, 255].
mmgp
1
visual = (visual - visual.min()) / (visual.max() - visual.min())sera par défaut si visualn'a pas de variance (peu probable, mais vaut la peine d'être attrapé)
1
J'ai essayé d'utiliser ce code pour mon problème, mais j'obtiens des images noires simples. Quelqu'un a-t-il une idée à ce sujet? stackoverflow.com/questions/24266000/…
user961627
32

Vous devriez pouvoir simplement laisser PIL obtenir le type de fichier de l'extension, c'est-à-dire utiliser:

j.save("C:/Users/User/Desktop/mesh_trans.bmp")
wim
la source
1
Merci pour la contribution. cependant, quand j'essaye de laisser la fonction de sauvegarde obtenir le type de fichier comme vous l'avez suggéré ci-dessus, j'obtiens l'erreur suivante: IOError: impossible d'écrire le mode F comme BMP. aucun conseil?
user1999274
1
Oui, vous devez convertir le tableau en numpy.uint8dtype plutôt qu'en float.
wim
6

Essayez de supprimer le .avant le .bmp(il ne correspond pas BMPcomme prévu). Comme vous pouvez le voir à partir de l'erreur, la save_handlercasse supérieure est celle que formatvous avez fournie, puis recherche une correspondance dans SAVE. Cependant, la clé correspondante dans cet objet est BMP(au lieu de .BMP).

Je ne sais pas grand-chose PIL, mais après quelques recherches rapides, il semble que ce soit un problème avec model'image. Modification de la définition de jen:

j = Image.fromarray(b, mode='RGB')

Cela a semblé fonctionner pour moi (notez cependant que je n'ai que très peu de connaissances PIL, donc je suggérerais d'utiliser la solution de @ mmgp car il sait clairement ce qu'ils font :)). Pour les types de mode, j'ai utilisé cette page - j'espère que l'un des choix fonctionnera pour vous.

RocketDonkey
la source
J'ai essayé de supprimer le .bmp en faveur du bmp et cela ne fonctionnait toujours pas. l'erreur que j'obtiens maintenant est: IOError: impossible d'écrire le mode F comme BMP. J'ai vérifié les pages PIL pour la documentation et il a dit d'utiliser le .bmp donc dans l'ensemble je n'ai toujours aucune idée pourquoi cela ne fonctionne pas.
user1999274
@ user1999274 A publié une mise à jour qui a semblé fonctionner pour moi (excuses pour le manque de détails - la reconstituer au fur et à mesure :)).
RocketDonkey
@RocketDonkey, il a été un peu plus intelligent que cela, car la conversion des résultats d'une transformée de Fourier en un espace de couleurs RVB donnera une image sans signification. Ce n'est pas parce que cela ne déclenche plus d'exception que le résultat est correct.
mmgp
@mmgp D'accord - c'est pourquoi j'ai attribué la mention +1 au vôtre et j'espère que l'OP l'acceptera :)
RocketDonkey
4

Je sais que c'est vieux, mais j'ai trouvé que (en utilisant Pillow) ouvrir le fichier en utilisant open(fp, 'w')puis en enregistrant le fichier fonctionnera. Par exemple:

with open(fp, 'w') as f:
    result.save(f)

fp étant le chemin du fichier, bien sûr.

Necko
la source
1
La documentation de Pillow indique que le formatparamètre doit être utilisé si un objet fichier est utilisé dans save. N'est-ce pas nécessaire?
Rob Rose
@RobRose lors de mes tests, lorsque j'ai posté la réponse, je n'ai rien trouvé de tel nécessaire. Cependant, cela peut être le cas maintenant. Si un test que vous faites s'avère nécessaire, faites-le moi savoir et je modifierai ma réponse
Necko