【问题标题】:Python: How to read images from zip file in memory?Python:如何从内存中的 zip 文件中读取图像?
【发布时间】:2015-08-02 22:15:55
【问题描述】:

我看到了这个问题的变体,但不是在这个确切的上下文中。我拥有的是一个名为 100-Test.zip 的文件,其中包含 100 个 .jpg 图像。我想在内存中打开这个文件并处理每个执行 PIL 操作的文件。其余的代码已经写好了,我只想集中精力从 zip 文件到第一个 PIL 图像。这是我从阅读其他问题中收集的建议中的代码现在的样子,但它不起作用。各位大神可以帮忙看看吗?

import zipfile
from StringIO import StringIO
from PIL import Image

imgzip = open('100-Test.zip', 'rb')
z = zipfile.ZipFile(imgzip)
data = z.read(z.namelist()[0])
dataEnc = StringIO(data)
img = Image.open(dataEnc)

print img

但是当我运行它时出现这个错误:

 IOError: cannot identify image file <StringIO.StringIO instance at
 0x7f606ecffab8>

替代方案:我看到其他消息来源说要使用它:

image_file = StringIO(open("test.jpg",'rb').read())
im = Image.open(image_file)

但问题是我没有打开文件,它已经在数据变量的内存中。我也尝试过使用dataEnc = StringIO.read(data),但得到了这个错误:

TypeError: unbound method read() must be called with StringIO instance as 
first argument (got str instance instead)

【问题讨论】:

  • 你的第一个例子对我来说很好,你也可以z = zipfile.ZipFile('100-Test.zip')
  • @alfredox 你检查过z.namelist()[0] 是否是一个图像文件吗?
  • @PadraicCunningham 所以您没有对代码进行任何更改并且它有效吗?我不确定我错过了什么,因为我收到了这些错误。
  • @ozgur 我只是假设它包含 zipfile 中的第一个文件,我不知道如何测试这是一个图像。
  • 是的,正如@ozgur 暗示的那样,问题可能是压缩文件中的第一项不是有效的图像文件(或者至少你的 PIL 不知道如何解码)。只需打印 z.namelist 即可让您了解您实际打开的是哪个文件

标签: python io buffer python-imaging-library zipfile


【解决方案1】:

原来的问题是由于图像被压缩在压缩文件的目录中,namelist() 中有一个额外的空元素。以下是检查并遍历 100 张图像的完整代码。

import zipfile
from StringIO import StringIO
from PIL import Image
import imghdr

imgzip = open('100-Test.zip')
zippedImgs = zipfile.ZipFile(imgzip)

for i in xrange(len(zippedImgs.namelist())):
    print "iter", i, " ",
    file_in_zip = zippedImgs.namelist()[i]
    if (".jpg" in file_in_zip or ".JPG" in file_in_zip):
        print "Found image: ", file_in_zip, " -- ",
        data = zippedImgs.read(file_in_zip)
        dataEnc = StringIO(data)
        img = Image.open(dataEnc)
        print img
    else:
        print ""

谢谢大家!

【讨论】:

    【解决方案2】:

    没有必要使用 StringIO。 zipfile 可以读取内存中的图像文件。以下循环遍历 .zip 文件中的所有图像:

    import zipfile
    from PIL import Image
    
    imgzip = zipfile.ZipFile("100-Test.zip")
    inflist = imgzip.infolist()
    
    for f in inflist:
        ifile = imgzip.open(f)
        img = Image.open(ifile)
        print(img)
        # display(img)
    

    【讨论】:

    • 我刚刚在一个大型压缩 TIFF 文件 (1024*768*116) 上尝试了这个想法。虽然它可能对小文件有好处,但对于大文件来说太慢了。 (> 20 分钟 vs 6 秒未压缩)不过好主意......
    【解决方案3】:

    我有同样的问题,感谢@alfredox,我修改了答案,在python3中使用io.BytesIO而不是StringIo。

    z = zipfile.ZipFile(zip_file)
    for i in range(len(z.namelist())):
    
        file_in_zip = z.namelist()[i]
        if (".jpg" in file_in_zip or ".JPG" in file_in_zip):
    
            data = z.read(file_in_zip)
            dataEnc = io.BytesIO(data)
            img = Image.open(dataEnc)
            print(img)
    

    【讨论】:

      【解决方案4】:

      如果您需要处理像素数据,那么您可以按照以下步骤将 zip 文件中的图像流数据加载为保持原始数据形状(即 32x32 RGB)的 numpy 数组:

      1. 使用zipfile获取ZipExtFile格式
      2. 使用 PIL.Image 将 ZipExtFile 转换为类似图像的数据结构
      3. 将 PIL.image 转换为 numpy 数组

      不需要用原始数据形状重塑 numpy 数组,因为 PIL.Image 已经有了信息。所以输出将是一个形状=(32,32,3)的numpy数组

      import numpy as np
      import zipfile
      from PIL import Image
      
      with zipfile.ZipFile(zip_data_path, "r") as zip_data:
          content_list = zip_data.namelist()
          for name_file in content_list:
              img_bytes = zip_data.open(name_file)          # 1
              img_data = Image.open(img_bytes)              # 2
              # ndarray with shape=(32,32,3)
              image_as_array = np.array(img_data, np.uint8) # 3
      

      【讨论】:

        【解决方案5】:

        cv2.imdecode() 版本:

        with zipfile.ZipFile(zip_data_path, "r") as z:
            for img_name in z.namelist():
                buf = z.read(name)
                np_buf = np.frombuffer(buf, np.uint8)
                img = cv2.imdecode(np_buf, cv2.IMREAD_UNCHANGED)
                # Saving image as an example.
                cv2.imwrite(name, img)
        

        【讨论】:

          猜你喜欢
          • 2020-06-16
          • 2012-06-12
          • 1970-01-01
          • 2013-03-18
          • 2015-09-18
          • 1970-01-01
          • 1970-01-01
          • 2011-11-10
          相关资源
          最近更新 更多