【问题标题】:Joining multiple huge images with pyvips使用 pyvips 连接多个巨大的图像
【发布时间】:2018-09-02 19:42:54
【问题描述】:

我正在尝试弄清楚如何通过 python 将多个图像与 vips 连接起来。我在一个文件夹中有 30 个(但可以超过 600 个)条纹的 png 文件,它们的分辨率为 854x289920(所有相同的分辨率)...

如果我尝试使用 MemmoryError 将它们水平连接在一起,python 中的 PIL 将立即死亡。所以我四处搜索并发现 VIPS 可以做我需要的两件事加入图像并从结果中制作深度缩放图像。

不幸的是,我不确定如何在 python 中正确地水平连接它们。

我在数组中有一个来自文件夹的图像列表,但是我将如何遍历它们并按顺序将合并的图像写入磁盘?

【问题讨论】:

    标签: python image image-processing vips


    【解决方案1】:

    仅供参考,您也可以在命令行中执行此操作。试试:

    vips arrayjoin "a.png b.png c.png" mypyr.dz --across 3
    

    将水平连接三个 PNG 图像并将结果保存为一个名为 mypyr 的深度缩放金字塔。 arrayjoin 文档具有所有选项:

    https://www.libvips.org/API/current/libvips-conversion.html#vips-arrayjoin

    您可以通过在.dz 之后将它们括在方括号中来提供金字塔构建器参数。

    vips arrayjoin "a.png b.png c.png" mypyr.dz[overlap=0,container=zip] --across 3
    

    在 Windows 上,deepzoom 金字塔的编写速度可能非常慢,因为 Windows 讨厌创建文件,并且讨厌巨大的目录。如果使用container=zip 编写,vips 将直接创建一个包含金字塔的 .zip 文件。这使得金字塔的创建速度提高了大约 4 倍。

    【讨论】:

      【解决方案2】:

      这似乎也适用于打开大量图像并对其进行 joinarray 以使它们彼此相邻。谢谢@user894763

      import os
      import pyvips
      # natsort helps with sorting the list logically
      from natsort import natsorted
      
      source = r"E:/pics/"
      output = r"E:/out/"
      save_to = output + 'final' + '.tif'
      
      # define list of pictures we are going to get from folder
      list_of_pictures = []
      # get the 
      for x in os.listdir(source):
          list_of_pictures.append(source + x)
      
      # list_of_pictures now contains all the images from folder including full path
      # since os.listdir will not guarantee proper order of files we use natsorted to do it
      list_of_pictures = natsorted(list_of_pictures)
      
      array_images = []
      image = None
      # lets create array of the images for joining, using sequential so it use less ram
      for i in list_of_pictures:
          tile = pyvips.Image.new_from_file(i, access="sequential")
          array_images.append(tile)
      
      # Join them, across is how many pictures there be next to each other, so i just counted all pictures in array with len 
      out = pyvips.Image.arrayjoin(array_images, across=len(list_of_pictures))
      # write it out to file....
      out.write_to_file(save_to, Q=95, compression="lzw", bigtiff=True)
      

      【讨论】:

      • 保存时的Q参数仅用于JPG压缩,对LZW没有任何影响。使用compression="deflate"predictor="horizontal",您可能会看到最好的结果。不过正如我所说,我会直接编写金字塔而不保存中间,它会快得多。
      【解决方案3】:

      我还是带着一些问题想通了:

      import pyvips
      
      list_of_pictures = []
      for x in os.listdir(source):
          list_of_pictures.append(source + x)
      
      image = None
      for i in list_of_pictures:
          tile = pyvips.Image.new_from_file(i, access="sequential")
          image = tile if not image else image.join(tile, "horizontal")
      
      image.write_to_file(save_to)
      

      是的,生成带有连接图片的 tif……但是冬青牛!原始图片是 png (30x) 总共 4.5GB 结果 tiff 是 25GB !什么给了,为什么会有这么大的尺寸差异?

      【讨论】:

      • 好的,这里有一些压缩选项:image.write_to_file(save_to, Q=95, compression="lzw", bigtiff=True)
      • 有效选项在哪里 (jpeg, deflate, packbits, ccittfax4, lzw) jpeg = fails if its get over 4GB, deflate = crash, packbits = 13.2GB ( made in 45s), ccittfax4 = wbuffer_write: write failed, lzw = 5.88GB (made in 151s) 到目前为止,lzw 压缩似乎提供了最好的结果尺寸虎钳,我没有注意到结果中有任何图像退化
      • 您可以使用arrayjoin 在一个步骤中加入图像数组。对于非常大量的源图像,它会更好地工作。您可以直接写入 deepzoom 金字塔,只需将最后一行换成 image.dzsave("mypyr")
      • 你也可以用write_to_file写一个deepzoom金字塔:只需使用.dz作为后缀。例如:image.write_to_file("mypyr.dz[suffix=.png]")
      • @user894763 谢谢,我想我将首先生成一个巨大的图像并从那里继续......但是 arrayjoin 看起来很有趣,我只是不确定我是否正确理解了参数。假设我有 30 张图像,并且想让它们彼此相邻排列,我会这样做:pyvips.Image.arrayjoin(list_of_images, across = 30) 吗?我指的是cross参数。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-21
      • 2017-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-13
      • 2013-04-20
      相关资源
      最近更新 更多