【问题标题】:How do I open an image from the internet in PIL?如何在 PIL 中打开来自 Internet 的图像?
【发布时间】:2012-08-18 17:21:45
【问题描述】:

我想在互联网上查找图像的尺寸。我尝试使用

from PIL import Image
import urllib2 as urllib
fd = urllib.urlopen("http://a/b/c")
im = Image.open(fd)
im.size

按照this answer 的建议,但我收到错误消息

addinfourl instance has no attribute 'seek'

我查了一下,urllib2.urlopen(url)返回的对象好像没有dir的seek方法。

那么,我必须做些什么才能将 Internet 上的图像加载到 PIL 中?

【问题讨论】:

    标签: python python-imaging-library urllib2


    【解决方案1】:

    您可以考虑将io.BytesIO 用于forward compatibility
    Python 3 中不存在 StringIO 和 cStringIO 模块。

    from PIL import Image
    import urllib2 as urllib
    import io
    
    fd = urllib.urlopen("http://a/b/c")
    image_file = io.BytesIO(fd.read())
    im = Image.open(image_file)
    

    【讨论】:

    【解决方案2】:

    使用 Python requests:

    from PIL import Image
    from StringIO import StringIO
    import requests
    
    r = requests.get("http://a/b/c")
    im = Image.open(StringIO(r.content))
    im.size
    

    【讨论】:

    • 虽然这个答案与其他答案不同,但它解决实际问题的方式与 jdi 的答案没有任何不同。它仍然将流包装在StringIO 中。
    • 这对没有 urllib2 但有请求的 Docker 映像很有用。感谢您发布替代方案。
    • 修复 ImportError: from io import StringIO for Python 3```
    【解决方案3】:

    使用相同的示例,只需使用 StringIO 将缓冲区包装到适当的类似文件的对象中:

    from PIL import Image
    import urllib2 as urllib
    from StringIO import StringIO
    
    fd = urllib.urlopen("http://a/b/c")
    im = Image.open(StringIO(fd.read()))
    im.size
    

    【讨论】:

      【解决方案4】:

      这个pull-request 增加了对 Pillow(友好的 PIL 分支)原生流处理的支持,应该从 2.8.0 版本开始提供。这允许使用urllib 更简单地打开远程文件:

      from PIL import Image
      import urllib2
      Image.open(urllib2.urlopen(url))
      

      ...或使用requests:

      from PIL import Image
      import requests
      Image.open(requests.get(url, stream=True).raw)
      

      由于mentioned by mjpieters on the PR 请求不会自动解码gzip 响应,因此如果您正在下载由于某种原因进一步压缩的图像,您必须在访问.raw 之前在响应对象上设置decode_content=True

      response = requests.get(url, stream=True)
      response.raw.decode_content = True
      image = Image.open(response.raw)
      

      【讨论】:

        【解决方案5】:

        urllib documentation 提到urlopen 返回的对象不支持seek 操作。

        该模块提供了一个高级接口,用于跨平台获取数据 万维网。特别是 urlopen() 函数是类似的 到内置函数 open(),但接受 Universal Resource 定位器(URL)而不是文件名。有一些限制——它可以 只能打开读取的URL,没有seek操作。

        但是,PIL.open 函数明确需要它。

        打开

        Image.open(infile) => 图像

        Image.open(infile, mode) => 图像

        打开并识别给定的图像文件。这是一个惰性操作; 在您尝试之前不会从文件中读取实际的图像数据 处理数据(调用load方法强制加载)。如果模式 给定参数,它必须是“r”。

        您可以使用字符串(表示文件名)或文件 目的。在后一种情况下,文件对象必须实现读取、查找、 并告诉方法,并以二进制模式打开。

        尝试使用cStringIO 模块将字符串转换为类似文件的对象。

        from PIL import Image
        import urllib2 as urllib
        import cStringIO
        
        fd = urllib.urlopen("http://a/b/c")
        image_file = cStringIO.StringIO(fd.read())
        im = Image.open(image_file)
        im.size
        

        【讨论】:

          【解决方案6】:

          这个答案是 4 年前的,但它在 Google 中仍然处于领先地位。在 Python3 中, 我们有简单的解决方案。

          from urllib.request import urlopen
          img =Image.open(urlopen('http://dl.iplaypython.com/images/banner336x280.jpg'))
          new_img =img.resize((300,500),Image.ANTIALIAS)
          new_img.save('url.jpg','jpeg')
          

          【讨论】:

          • 你能再解释一下吗?
          【解决方案7】:

          使用请求库并以字节形式获取输出

          import requests
          import io
          
          response = requests.get("https://i.imgur.com/ExdKOOz.png")
          image_bytes = io.BytesIO(response.content)
          

          【讨论】:

            猜你喜欢
            • 2013-08-24
            • 2021-05-20
            • 2020-08-06
            • 2018-04-19
            • 2015-12-30
            • 2019-05-12
            • 1970-01-01
            • 2020-01-28
            相关资源
            最近更新 更多