Как мне прочитать данные изображения с 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» в качестве минимально необходимого заголовка при выполнении запроса.