Comment lire des données d'image à partir d'une URL en Python?

182

Ce que j'essaie de faire est assez simple lorsque nous avons affaire à un fichier local, mais le problème survient lorsque j'essaie de le faire avec une URL distante.

Fondamentalement, j'essaie de créer un objet image PIL à partir d'un fichier extrait d'une URL. Bien sûr, je pourrais toujours simplement récupérer l'URL et la stocker dans un fichier temporaire, puis l'ouvrir dans un objet image, mais cela semble très inefficace.

Voici ce que j'ai:

Image.open(urlopen(url))

Cela s'efface de se plaindre que ce seek()n'est pas disponible, alors j'ai essayé ceci:

Image.open(urlopen(url).read())

Mais cela n'a pas fonctionné non plus. Y a-t-il une meilleure façon de faire cela, ou est-ce que l'écriture dans un fichier temporaire est la manière acceptée de faire ce genre de chose?

Daniel Quinn
la source

Réponses:

282

Dans Python3, les modules StringIO et cStringIO ont disparu.

En Python3, vous devez utiliser:

from PIL import Image
import requests
from io import BytesIO

response = requests.get(url)
img = Image.open(BytesIO(response.content))
Andres Kull
la source
Comment récupérer l'image de response.content?
Amresh Giri
requestsLe package renvoie le code d'état 503 lors de la récupération d'une image à partir d'une URL. Au lieu de cela, j'ai dû recourir http.clientpour obtenir l'image.
Manishankar Singh
Quand j'essaye ceci, j'obtiens: AttributeError: le module 'requests' n'a pas d'attribut 'get'.
apiljic
2
L'encapsulation manuelle dans BytesIO n'est plus nécessaire depuis PIL> = 2.8.0. Utilisez simplement Image.open(response.raw). PIL vérifie automatiquement cela maintenant et fait l'emballage BytesIO sous le capot. De: oreiller.readthedocs.io/en/3.0.x/releasenotes/2.8.0.html
Vinícius M
MERCIUUUUUUUUUUU, OP.
Sharl Sherif le
166

vous pouvez essayer d'utiliser un StringIO

import urllib, cStringIO

file = cStringIO.StringIO(urllib.urlopen(URL).read())
img = Image.open(file)
Fábio Diniz
la source
Merci, je voudrais juste ajouter que le même code exact fonctionnera avec urllib2 (avec Python2)
doucement
17
en python 3, ce serait de urllib.request import urlopen et io.io.BytesIO au lieu de StringIO
matyas
2
HELP, IOError: impossible d'identifier le fichier image <objet _io.BytesIO à 0x7fb91b6a29b0> mon url est: ... model = product.template & id = 16 & field = image_medium
С. Дэлгэрцэцэг
56

J'utilise la bibliothèque de requêtes. Cela semble plus robuste.

from PIL import Image
import requests
from StringIO import StringIO

response = requests.get(url)
img = Image.open(StringIO(response.content))
Saurav
la source
3
Pour une raison quelconque, urllib ne fonctionnait pas pour certaines URL, mais les requêtes ont fonctionné là où cela a échoué
mirri66
Je n'ai pas pu trouver le package PIL, mais il semble que l'oreiller ait repris l'effort PIL et que vous pouvez installer pour python3 avec pip3.4 install pillow.
disruptif
3
Notez que les requêtes chargeront la réponse entière en mémoire, puis PIL chargera à nouveau la chose entière en tant qu'image, donc vous avez deux copies complètes résidant en mémoire. La réponse précédente utilisant la méthode urllib diffuse les données, de sorte que vous ne vous retrouvez qu'avec une copie plus la taille du tampon de streaming. Vous pouvez également diffuser les données avec des requêtes, mais comme la réponse ne prend pas en charge la sémantique read (), vous devrez créer un adaptateur.
sirdodger le
@sirdodger Faites-vous référence à urllib2 ou urllib?
CMCDragonkai
@CMCDragonkai Je faisais référence à la réponse urllib acceptée. Si la surcharge de mémoire est un problème, il est préférable d'utiliser cette réponse aux demandes. (Cependant, comme je l'ai mentionné, une solution différente utilisant des requêtes pourrait avoir le même effet.)
sirdodger
42

Pour ceux d'entre vous qui utilisent Pillow, à partir de la version 2.8.0, vous pouvez:

from PIL import Image
import urllib2

im = Image.open(urllib2.urlopen(url))

ou si vous utilisez requests:

from PIL import Image
import requests

im = Image.open(requests.get(url, stream=True).raw)

Références:

Giovanni Cappellotto
la source
27

Utilisez StringIOpour transformer la chaîne de lecture en un objet de type fichier:

from StringIO import StringIO
import urllib

Image.open(StringIO(urllib.requests.urlopen(url).read()))
Dan D.
la source
21

Pour ceux qui effectuent un post-traitement sklearn / numpy (c'est-à-dire un apprentissage profond), vous pouvez envelopper l'objet PIL avec np.array (). Cela pourrait vous éviter d'avoir à le rechercher sur Google comme je l'ai fait:

from PIL import Image
import requests
import numpy as np
from StringIO import StringIO

response = requests.get(url)
img = np.array(Image.open(StringIO(response.content)))
Ben
la source
19

Python 3

from urllib.request import urlopen
from PIL import Image

img = Image.open(urlopen(url))
img

Jupyter Notebook et IPython

import IPython
url = 'https://newevolutiondesigns.com/images/freebies/colorful-background-14.jpg'
IPython.display.Image(url, width = 250)

Contrairement aux autres méthodes, cette méthode fonctionne également dans une boucle for!

Miladiouss
la source
12

La manière sans doute recommandée de faire des entrées / sorties d'images de nos jours est d'utiliser le package dédié ImageIO . Les données d'image peuvent être lues directement à partir d'une URL avec une simple ligne de code:

from imageio import imread
image = imread('https://cdn.sstatic.net/Sites/stackoverflow/img/logo.png')

De nombreuses réponses sur cette page sont antérieures à la sortie de ce package et ne le mentionnent donc pas. ImageIO a commencé en tant que composant de la boîte à outils Scikit-Image . Il prend en charge un certain nombre de formats scientifiques en plus de ceux fournis par la populaire bibliothèque de traitement d' images PILlow . Il enveloppe le tout dans une API propre uniquement axée sur l'entrée / la sortie d'image. En fait, SciPy a supprimé son propre lecteur / graveur d'images en faveur d'ImageIO .

anon
la source
3

sélectionnez l'image en chrome, faites un clic droit dessus, cliquez dessus Copy image address, collez-la dans une strvariable ( my_url) pour lire l'image:

import shutil
import requests

my_url = 'https://www.washingtonian.com/wp-content/uploads/2017/06/6-30-17-goat-yoga-congressional-cemetery-1-994x559.jpg'
response = requests.get(my_url, stream=True)
with open('my_image.png', 'wb') as file:
    shutil.copyfileobj(response.raw, file)
del response

ouvrez-le;

from PIL import Image

img = Image.open('my_image.png')
img.show()
Shivid
la source