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

308
我所尝试的是在处理本地文件时相当简单的问题,但当我尝试使用远程URL时就会出现问题。
基本上,我正在尝试从从URL获取的文件创建PIL图像对象。 当然,我总是可以只获取URL并将其存储在临时文件中,然后将其打开为图像对象,但那样感觉非常低效。
这是我拥有的:
Image.open(urlopen(url))

它会因为seek()不可用而抛出错误,所以我尝试了这个:

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

但那也不起作用。有更好的方法来做这件事吗?还是写入临时文件是这种情况下被接受的方式?


可能存在问题,请求无法从URL获取图像。尝试从另一个URL进行相同的测试(仅供测试目的)。 - Aashish Chaubey
15个回答

443

在Python3中,StringIO和cStringIO模块已经被删除。

在Python3中,你应该使用:

from PIL import Image
import requests
from io import BytesIO

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

1
如何从 response.content 中获取图像? - Amresh Giri
requests包在从URL获取图像时抛出503状态码。相反,我不得不求助于http.client来获取图像。 - MSS
当我尝试这个时,我得到了以下错误:AttributeError: module 'requests' has no attribute 'get'。 - apiljic
39
自 PIL 版本 2.8.0 起,不再需要手动使用 BytesIO 进行封装。 只需使用 Image.open(response.raw) 即可。 PIL 现在会自动检查并在幕后进行 BytesIO 封装。 来源:https://pillow.readthedocs.io/en/3.0.x/releasenotes/2.8.0.html - Vinícius M
@ViníciusM,你的答案应该在顶部!谢谢。 - alanho
2
有点烦人,需要三个库...Pillow 应该直接添加这个功能! - Nic Scozzaro

189

5
urllib2应该是针对Python2的,现在已经过时了。对于Python 3,可以使用urllib.requests:urllib.request.urlopen(url).read() - wordsforthewise
2
正如@wordsforthewise所提到的,urllib已经过时了。我选择了第二个选项,因为我在我的代码中已经使用了“requests”,而且它也起作用了,所以我点了赞。是否应该删除解决方案中的urllib部分,以便读者不会浪费时间尝试第一种方法,然后意识到它不起作用,然后转向下一个方法? - Mugdha
1
嗨,这对我的项目非常有效!只是想知道,它是否会构建任何缓存或缓冲区?我需要关闭这些图像/清除任何东西吗? - Pissed Off Banker

173

使用StringIO

import urllib, cStringIO

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

谢谢,我只想补充一下,完全相同的代码也适用于urllib2(使用Python2)。 - sofly
23
在Python 3中,应该使用“from urllib.request import urlopen和io.BytesIO”,而不是StringIO。 - matyas
2
帮助,IOError:无法识别图像文件<_io.BytesIO object at 0x7fb91b6a29b0>我的URL是:...model=product.template&id=16&field=image_medium - С. Дэлгэрцэцэг

62

使用 requests:

from PIL import Image
import requests
from StringIO import StringIO

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

3
由于某些原因,urllib 无法处理某些 URL,但是在这些情况下,requests 可以成功处理。 - mirri66
我找不到PIL包,但是看起来pillow已经接管了PIL的工作,你可以使用pip3.4 install pillow为python3安装。 - disruptive
3
请注意,请求将整个响应加载到内存中,然后PIL将再次将整个内容加载为图像,因此您在内存中有两个完整的副本。使用urllib方法的先前答案流式传输数据,因此您最终只会有一个副本加上流式缓冲区大小。您也可以使用requests流式传输数据,但是由于响应不支持read()语义,因此您需要构建一个适配器。 - sirdodger
@sirdodger,您是在指urllib2还是urllib? - CMCDragonkai
@CMCDragonkai 我指的是被接受的urllib答案。如果内存开销是一个问题,那么它比使用这个requests答案更好。(然而,正如我所提到的,使用requests的不同解决方案可以实现相同的效果。) - sirdodger
@sirdodger PIL现在似乎也支持流式处理了。=) https://pillow.readthedocs.io/en/3.0.x/releasenotes/2.8.0.html - Vinícius M

52

Python 3

from urllib.request import urlopen
from PIL import Image

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

Jupyter Notebook 和 IPython

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

与其他方法不同,该方法也可以在for循环中使用!


31

这篇答案是针对Python 2.7编写的。

对于Python 3,urlopen已经从urllib移动到了urllib.requests。而StringIO.StringIOio.BytesIO所取代。

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

from StringIO import StringIO
from PIL import Image
import urllib

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

1
这个回应干净易懂,但是 import 语句应该写成 from io import StringIO - Vid Stropnik

26

现在处理图像输入/输出的推荐方法是使用专用包ImageIO。只需一行简单的代码,就可以直接从URL读取图像数据:

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

这一页上的很多答案都是在那个软件包发布之前写的,因此没有提到它。ImageIO最初是Scikit-Image工具包的组成部分。除了由流行的图像处理库PILlow提供的几种格式外,它还支持许多科学格式。它通过一个干净的API封装了所有内容,专注于图像的输入/输出。事实上,SciPy已经取消了自己的图像读写器,转而使用ImageIO

非常慢。如果您想要在一行中完成操作,skimage方法将是更好的选择。 - Anupam Tripathi
2
这是skimage(Scikit-Image)的方法,正如答案所解释的那样。它的速度和你的互联网连接一样慢。 - john-hen

24

对于那些进行一些sklearn/numpy后处理(即深度学习)的人,您可以使用np.array()将PIL对象包装起来。这可能会避免像我一样不得不在Google上搜索它:

对于进行某些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)))

5

在Chrome中选择图像,右键单击图像,点击复制图片地址,将其粘贴到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()

4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接