在 pyglet 或 PIL / python 中从远程服务器加载图像

Loading image from a remote server in pyglet or PIL / python

我想将图像从远程机器输入到 pyglet(尽管我对其他平台开放,我可以在其他平台上显示图像并记录用户的鼠标点击和击键)。目前我正在尝试在远程服务器上使用 flask 并使用 requests

将其拉下
import requests

from PIL import Image
import io
import pyglet
import numpy as np

r = requests.get('http://{}:5000/test/cat2.jpeg'.format(myip),)

这不起作用:

im = pyglet.image.load(io.StringIO(r.text))

# Error: 
File "/usr/local/lib/python3.4/dist-packages/pyglet/image/__init__.py", line 178, in load
    file = open(filename, 'rb')

TypeError: invalid file: <_io.StringIO object at 0x7f6eb572bd38>

这也不行:

im = Image.open(io.BytesIO(r.text.encode()))

# Error:
Traceback (most recent call last):

  File "<ipython-input-68-409ca9b8f6f6>", line 1, in <module>
    im = Image.open(io.BytesIO(r.text.encode()))

  File "/usr/local/lib/python3.4/dist-packages/PIL/Image.py", line 2274, in open
    % (filename if filename else fp))

OSError: cannot identify image file <_io.BytesIO object at 0x7f6eb5a8b6a8>

有没有另一种方法可以不在磁盘上保存文件?

第一个示例无法正常工作,因为我遇到了编码问题。但这将使您走上使用手动 ImageData 对象来处理图像的方式:

import pyglet, urllib.request

# == The Web part:
img_url = 'http://hvornum.se/linux.jpg'
web_response = urllib.request.urlopen(img_url)
img_data = web_response.read()

# == Loading the image part:
window = pyglet.window.Window(fullscreen=False, width=700, height=921)
image = pyglet.sprite.Sprite(pyglet.image.ImageData(700, 921, 'RGB', img_data))

# == Stuff to render the image:
@window.event
def on_draw():
    window.clear()
    image.draw()
    window.flip()

@window.event
def on_close():
    print("I'm closing now")

pyglet.app.run()

现在,更方便、更少手动的处理方式是使用 io.BytesIO 虚拟文件句柄,然后使用参数 file=dummyFile 将其放入 pyglet.image.load() 中,如下所示:

import pyglet, urllib.request
from io import BytesIO

# == The Web part:
img_url = 'http://hvornum.se/linux.jpg'
web_response = urllib.request.urlopen(img_url)
img_data = web_response.read()
dummy_file = BytesIO(img_data)

# == Loading the image part:
window = pyglet.window.Window(fullscreen=False, width=700, height=921)
image = pyglet.sprite.Sprite(pyglet.image.load('noname.jpg', file=dummy_file))

# == Stuff to render the image:
@window.event
def on_draw():
    window.clear()
    image.draw()
    window.flip()

@window.event
def on_close():
    print("I'm closing now")

pyglet.app.run()

在我这边工作,而且速度也相当快。
最后一点,尝试将图像放入 pyglet.sprite.Sprite 对象中,它们往往更快、更容易使用,并为您提供一大堆漂亮的功能(例如轻松定位、spr.scale 和旋转函数)

您可以通过PIL显示远程图片如下:

import requests
from PIL import Image
from StringIO import StringIO

r = requests.get('http://{}:5000/test/cat2.jpeg', stream=True)
sio = StringIO(r.raw.read())
im = Image.open(sio)
im.show()

请注意,stream=True 选项是从数据创建 StringIO 对象所必需的。另外,不使用 io.StringIO 而是 StringIO.StringIO.