Как мне прочитать данные изображения с URL в Python?

То, что я пытаюсь сделать, довольно просто, когда мы имеем дело с локальным файлом, но проблема возникает, когда я пытаюсь сделать это с помощью удаленного URL.

По сути, я пытаюсь создать объект изображения PIL из файла, извлеченного из URL. Конечно, я всегда мог просто извлечь URL и сохранить его во временном файле, а затем открыть его в объект изображения, но это кажется очень неэффективным.

Вот что у меня есть:

Image.open(urlopen(url))

Слезы жалуются, что seek() не доступно, поэтому я попробовал это:

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

Но это тоже не сработало. Есть ли лучший способ сделать это, или запись во временный файл является приемлемым способом сделать это?

15 ответов

Решение

Вы можете попробовать использовать StringIO

import urllib, cStringIO

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

В Python3 модули StringIO и cStringIO исчезли.

В Python3 вы должны использовать:

from PIL import Image
import requests
from io import BytesIO

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

Для тех из вас, кто использует подушку, начиная с версии 2.8.0, вы можете:

from PIL import Image
import urllib2

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

или если вы используете requests:

from PIL import Image
import requests

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

Рекомендации:

Я использую библиотеку запросов. Кажется, это более надежно.

from PIL import Image
import requests
from StringIO import StringIO

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

Это работает и на Python 3.6...

from urllib.request import urlopen
from PIL import Image

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

Использование StringIO чтобы превратить прочитанную строку в подобный файлу объект:

from StringIO import StringIO
import urllib

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

В наши дни, пожалуй, рекомендуемый способ ввода / вывода изображений - это использовать специальный пакет ImageIO. Данные изображения можно прочитать прямо из URL-адреса с помощью одной простой строки кода:

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

Многие ответы на этой странице предшествуют выпуску этого пакета и поэтому не упоминают его. ImageIO начинался как компонент набора инструментов Scikit-Image. Он поддерживает ряд научных форматов помимо форматов, предоставляемых популярной библиотекой обработки изображений PILlow. Он оборачивает все это в чистый API, ориентированный исключительно на ввод / вывод изображений. Фактически, SciPy удалила свой собственный считыватель / писатель изображений в пользу ImageIO.

Для тех, кто выполняет некоторую пост-обработку sklearn/numpy (т.е. глубокое обучение), вы можете обернуть объект PIL с помощью np.array(). Это может избавить вас от необходимости заходить в Google, как я:

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

Выберите изображение в Chrome, щелкните правой кнопкой мыши на нем, нажмите на Copy image addressвставьте его в str переменная (my_url) читать изображение:

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

Открой это;

from PIL import Image

img = Image.open('my_image.png')
img.show()

Ручная упаковка в BytesIO больше не требуется, так как PIL >= 2.8.0. Просто используйте Image.open(response.raw)

Добавление поверх комментария Виниция:

Вы должны пройти stream=Trueкак указано https://requests.readthedocs.io/en/master/user/quickstart/

Так

img = Image.open(requests.get(url, stream=True).raw)
      from PIL import Image
import cv2
import numpy as np
import requests
image=Image.open(requests.get("https://previews.123rf.com/images/darrenwhi/darrenwhi1310/darrenwhi131000024/24022179-photo-of-many-cars-with-one-a-different-color.jpg", stream=True).raw)
#image =resize((420,250))

image_array=np.array(image)
image 

ИСПОЛЬЗУЙТЕ urllib.request.urlretrieve () И PIL.Image.open(), ЧТОБЫ ЗАГРУЗИТЬ И ПРОЧИТАТЬ ДАННЫЕ ИЗОБРАЖЕНИЯ:

запросы на импорт

импортировать urllib.request

      import PIL
urllib.request.urlretrieve("https://i.imgur.com/ExdKOOz.png", "sample.png")
img = PIL.Image.open("sample.png")
img.show()

или Вызовите request.get (url) с url в качестве адреса объектного файла для загрузки через запрос GET. Вызовите io.BytesIO (obj) с obj в качестве содержимого ответа, чтобы загрузить необработанные данные в виде байтового объекта. Чтобы загрузить данные изображения, вызовите PIL.Image.open(bytes_obj) с bytes_obj в качестве объекта байтов:

      import io
response = requests.get("https://i.imgur.com/ExdKOOz.png")
image_bytes = io.BytesIO(response.content)
img = PIL.Image.open(image_bytes)
img.show()

Для Python 3 с использованием OpenCV:

      import cv2
from urllib.request import urlopen

image_url = "IMAGE-URL-GOES-HERE"
resp = urlopen(image_url)
image = np.asarray(bytearray(resp.read()), dtype="uint8")
image = cv2.imdecode(image, cv2.IMREAD_COLOR) # The image object

# Optional: For testing & viewing the image
cv2.imshow('image',image)

Для Python 3 с использованием OpenCV и Google Colab/Jupyter Notebook:

      import cv2
from google.colab.patches import cv2_imshow
from urllib.request import urlopen

image_url = "IMAGE-URL-GOES-HERE"
resp = urlopen(image_url)
image = np.asarray(bytearray(resp.read()), dtype="uint8")
image = cv2.imdecode(image, cv2.IMREAD_COLOR) # The image object

# Optional: For testing & viewing the image
cv2_imshow(image)

Чтобы напрямую получить изображение в виде массива numpy без использования PIL

import requests, io
import matplotlib.pyplot as plt 

response = requests.get(url).content
img = plt.imread(io.BytesIO(response), format='JPG')
plt.imshow(img)

Решения, упомянутые выше, могут работать, но они упускают один момент, который я хотел бы выделить: когда мы извлекаем или извлекаем URL-адрес изображения для чтения, мы не всегда можем получить фактическое содержимое изображения, если мы не передаем заголовки при создании получить запрос.

например:

запрос без заголовков

      import requests
url = "https://www.roaringcreationsfilms.com/rcsfilms-media/chankya-quotes-in-hindi-32.jpg"
data = requests.get(url).content

если мы проверим данные:

      print(data)
b'<head><title>Not Acceptable!</title></head><body><h1>Not Acceptable!</h1><p>An 
appropriate representation of the requested resource could not be found on this server.
This error was generated by Mod_Security.</p></body></html>'

вы видите, мы на самом деле не получаем содержимое изображения.

запрос с заголовками

      import requests
url = "https://www.roaringcreationsfilms.com/rcsfilms-media/chankya-quotes-in-hindi-32.jpg"
headers = {"User-Agent": "PostmanRuntime/7.31.1"}
data = requests.get(url, headers=headers).content

и, если мы теперь проверим данные:

      print(data)
b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\t\x06\x06\........\xfb\x04El\xb3\xa8L\xbc\xa12\xc6<\xc4\x891\xf2L|\xf7\x9eV\x18\xc5\xd8\x8f\x02\xca\xdc\xb1c+-\x96\'\x86\xcb,l\xb12;\x16\xd4j\xfd/\xde\xbf\xff\xd9'

Теперь мы получаем фактическое содержимое изображения.

Следует отметить, что для разных URL-адресов могут потребоваться разные комбинации заголовков (например, «User-Agent», «Accept», «Accept-Encoding» и т. д.) для успешного получения данных, а некоторые даже могут не требовать никаких заголовков. Но всегда рекомендуется передавать «User-Agent» в качестве минимально необходимого заголовка при выполнении запроса.

Другие вопросы по тегам