Como leio dados de imagem de um URL em Python?


182

O que estou tentando fazer é bastante simples quando estamos lidando com um arquivo local, mas o problema surge quando tento fazer isso com um URL remoto.

Basicamente, estou tentando criar um objeto de imagem PIL a partir de um arquivo extraído de uma URL. Claro, eu sempre poderia buscar o URL e armazená-lo em um arquivo temporário, depois abri-lo em um objeto de imagem, mas isso parece muito ineficiente.

Aqui está o que eu tenho:

Image.open(urlopen(url))

Ele sai reclamando que seek()não está disponível, então tentei o seguinte:

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

Mas isso também não funcionou. Existe uma maneira melhor de fazer isso ou está gravando em um arquivo temporário a maneira aceita de fazer esse tipo de coisa?


Respostas:


281

No Python3, os módulos StringIO e cStringIO se foram.

No Python3 você deve usar:

from PIL import Image
import requests
from io import BytesIO

response = requests.get(url)
img = Image.open(BytesIO(response.content))

Como recuperar a imagem de response.content?
Amresh Giri 07/02/19

requestsO pacote lança o código de status 503 ao buscar uma imagem de um URL. Em vez disso, tive que recorrer http.clientpara obter a imagem.
Manishankar Singh

Quando tento isso, obtenho: AttributeError: module 'orders' não tem atributo 'get'.
apiljic

2
O agrupamento manual no BytesIO não é mais necessário desde o PIL> = 2.8.0. Apenas use Image.open(response.raw). O PIL verifica automaticamente isso agora e faz o BytesIO embaixo do capô. De: pillow.readthedocs.io/en/3.0.x/releasenotes/2.8.0.html
Vinícius M

OBRIGADO, OP.
Sharl Sherif

166

você pode tentar usar um StringIO

import urllib, cStringIO

file = cStringIO.StringIO(urllib.urlopen(URL).read())
img = Image.open(file)

Obrigado, gostaria apenas de acrescentar que o mesmo código exato funcionará com urllib2 (com Python2)
suavemente

17
no python 3 seria de urllib.request import urlopen e io.io.BytesIO em vez de StringIO
matyas

2
HELP, IOError: não é possível identificar o objeto <_io.BytesIO do arquivo de imagem em 0x7fb91b6a29b0> meu URL é: ... model = product.template & id = 16 & field = image_medium
С. #

56

Eu uso a biblioteca de solicitações. Parece ser mais robusto.

from PIL import Image
import requests
from StringIO import StringIO

response = requests.get(url)
img = Image.open(StringIO(response.content))

3
Por alguma razão urllib não funcionar para algumas URLs, mas os pedidos trabalhou onde que falhou
mirri66

Não consegui encontrar o pacote PIL, mas parece que o travesseiro assumiu o esforço do PIL e você pode instalar o python3 com pip3.4 install pillow.
Disruptive

3
Observe que as solicitações carregarão a resposta inteira na memória e, em seguida, o PIL carregará a coisa inteira novamente como uma imagem, para que você tenha duas cópias completas residentes na memória. A resposta anterior, usando o método urllib, transmite os dados para que você tenha apenas uma cópia mais o tamanho do buffer de streaming. Você também pode transmitir os dados com solicitações, mas como a resposta não suporta a semântica read (), você precisaria construir um adaptador.
Sirdodger

@sirdodger Você está se referindo a urllib2 ou urllib?
CMCDragonkai

@CMCDragonkai Eu estava me referindo à resposta urllib aceita. Se a sobrecarga de memória for uma preocupação, é melhor do que usar esta solicitação de resposta. (No entanto, como mencionado, uma solução diferente usando pedidos poderia conseguir o mesmo efeito.)
sirdodger


27

Use StringIOpara transformar a sequência de leitura em um objeto parecido com um arquivo:

from StringIO import StringIO
import urllib

Image.open(StringIO(urllib.requests.urlopen(url).read()))

21

Para aqueles que fazem algum pós-processamento sklearn / numpy (por exemplo, Deep Learning), você pode agrupar o objeto PIL com np.array (). Isso pode evitar que você precise acessar o Google como eu fiz:

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)))

19

Python 3

from urllib.request import urlopen
from PIL import Image

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

Notebook Jupyter e IPython

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

Ao contrário de outros métodos, esse método também funciona em um loop for!


12

A maneira sem dúvida recomendada para entrada / saída de imagem atualmente é usar o pacote dedicado ImageIO . Os dados da imagem podem ser lidos diretamente de um URL com uma simples linha de código:

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

Muitas respostas nesta página são anteriores ao lançamento desse pacote e, portanto, não o mencionam. O ImageIO começou como um componente do kit de ferramentas Scikit-Image . Ele suporta vários formatos científicos, além dos fornecidos pela popular biblioteca de processamento de imagens PILlow . Ele agrupa tudo em uma API limpa, focada apenas na entrada / saída de imagem. De fato, o SciPy removeu seu próprio leitor / gravador de imagens em favor do ImageIO .


3

selecione a imagem no chrome, clique com o botão direito do mouse Copy image address, cole-o em uma strvariável ( my_url) para ler a imagem:

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

abra;

from PIL import Image

img = Image.open('my_image.png')
img.show()
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.