如何从Python中的URL读取图像数据?

当我们处理本地文件时,我试图做的事情相当简单,但当我试图用远程URL这样做时,问题就来了。

基本上,我试图从一个URL提取的文件创建一个PIL图像对象。当然,我总是可以只获取URL并将其存储在临时文件中,然后将其打开到一个图像对象中,但这感觉非常低效。

以下是我所拥有的:

Image.open(urlopen(url))

它抱怨seek()不可用,所以我尝试了这个:

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

但这也不管用。是否有更好的方法来做到这一点,或者写入临时文件是做这类事情的公认方法?

407432 次浏览

使用StringIO将读取的字符串转换为类文件对象:

from StringIO import StringIO
from PIL import Image
import urllib


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

使用StringIO

import urllib, cStringIO


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

使用requests:

from PIL import Image
import requests
from StringIO import StringIO


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

在Python3中,StringIO和cStringIO模块消失了。

在Python3中,您应该使用:

from PIL import Image
import requests
from io import BytesIO


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

对于那些做一些sklearn/numpy后处理(即深度学习)的人,你可以用np.array()包装PIL对象。这可能会让你不必像我一样大声抱怨:

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

以下代码适用于Python 3:

from PIL import Image
import requests


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

引用:

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

Python 3

from urllib.request import urlopen
from PIL import Image


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

木星笔记本和IPython

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

与其他方法不同,此方法也适用于for循环!

如今,有争议的推荐图像输入/输出方法是使用专用包ImageIO。图像数据可以通过简单的一行代码直接从URL读取:

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

本页上的许多回答早于该软件包发布之前,因此没有提及它。ImageIO最初是Scikit-Image工具包的组件。在流行的图像处理库枕头提供的格式之上,它支持许多科学格式。它将所有这些都包装在一个干净的API中,只关注图像输入/输出。事实上,SciPy 删除有自己的图像读取器/写入器支持ImageIO

自PIL >= 2.8.0以来,不再需要在BytesIO中手动包装。只需使用Image.open(response.raw)

在Vinícius的评论之上补充道:

你应该传递stream=True,正如所指出的https://requests.readthedocs.io/en/master/user/quickstart/#raw-response-content

所以

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

直接获取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)

使用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()

或Call requests.get(url), url作为通过GET请求下载的目标文件的地址。调用io.BytesIO(obj),并将obj作为响应的内容,将原始数据作为bytes对象加载。要加载图像数据,调用PIL.Image.open(bytes_obj),并将bytes_obj作为bytes对象:

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