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

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

以下是我所拥有的:

Image.open(urlopen(url))

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

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

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


当前回答

以下代码适用于Python 3:

from PIL import Image
import requests

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

引用:

https://github.com/python-pillow/Pillow/pull/1151 https://github.com/python-pillow/Pillow/blob/master/CHANGES.rst#280-2015-04-01

其他回答

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

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

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

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

使用StringIO

import urllib, cStringIO

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

对于那些做一些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)))

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

在Python3中,您应该使用:

from PIL import Image
import requests
from io import BytesIO

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