【问题标题】:How to perform a sequence of a very large image averaging in python / OpenCV?如何在 python / OpenCV 中执行一系列非常大的图像平均?
【发布时间】:2015-01-16 00:23:09
【问题描述】:

我正在处理 30,000 x 30,000 像素的 TIFF 图像,并希望一次平均 11 个这些图像。

如果可能的话,我更喜欢在 python 中执行此操作,并且想知道解决此问题的最佳方法是什么?

我应该使用OpenCV 还是只使用numpy 可以完成?

独立平均每个 RGBA 通道会提高性能吗?

或者我应该将图像分割成更小的图像并独立处理它们,然后将生成的部分缝合在一起?

像这样直接使用 openCV 会导致内存错误:

im0 = cv2.imread( '5014.tif' )
im1 = cv2.imread( '5114.tif' )
im2 = cv2.imread( '5214.tif' )
im3 = cv2.imread( '5314.tif' )
im4 = cv2.imread( '5414.tif' )
cv2.imwrite( 'avg.tif', .01*im0 -.002*im1 -.002*im2 -.002*im3 -.002*im4 )

【问题讨论】:

    标签: python performance image-processing numpy out-of-memory


    【解决方案1】:

    您的“堆栈”具有“形状”(30000, 30000, 4, 11)。我不会担心以任何方式手动循环最后两个维度 - 我会担心您遇到的内存不足。

    我不知道 OpenCV 语法,但如果您可以在没有内存问题的情况下读取一张图像,请执行以下操作:

    image_filenames = ['5014.tif', '5114.tif', ...]
    N = float(len(image_filenames))
    
    output = # empty array of image dimensions
    
    for image_filename in image_filenames:
        # read in this image
        # add image / N to output
    
    # save the output
    

    【讨论】:

    • 恕我直言,内存占用量是 12 倍(不是 11 倍),平均不使用算术平均值,而是使用不同的微积分。
    【解决方案2】:

    需要改进哪些性能?

    1. SMALLER 静态 Memory Footprint -- 因为处理 不 执行任何复杂的计算,只需更改处理方案以从 30GB 静态 RAM 占用量减少到一些5GB。 (代码示例以这种方式运行,遍历 11 个文件的序列)

    aListOfFNAMEs = [ ''5014.tif', ...                      ] # SETUP: FNAMEs
    aListOfCOEFFs = [ .01, -.002, -.002, -.002, -.002, .... ] #        COEFFs till the 11-th
    
    anInputIMG    = cv2.imread( aListOfFNAMEs[0] )            # LOAD
    anAveragedIMG = numpy.zeros( anInputIMG.shape )           # ensure .copy, not view
    
    anAveragedIMG += aListOfCOEFFs[0]*anInputIMG              # process the 1st LOAD-ed
    
    for aPtr in range( 1, len(aListOfCOEFFs ) ):              # iterate, process the rest
        anInputIMG     = cv2.imread( aListOfFNAMEs[aPtr] )    #          re-use MEM on LOAD(s)
        anAveragedIMG += aListOfCOEFFs[aPtr] * anInputIMG     #          process <next>
    
    cv2.imwrite( "avg.TIF", anAveragedIMG )                   # SAVE
    del anInputIMG                                            # release for GC
    del anAveragedIMG                                         # release for GC, DONE.
    

    1. 更快矢量化矩阵运算 - 由于处理允许 numpy/openCV 矢量化矩阵运算,RGB 色彩平面分离成独立处理不允许 strong>提高速度,恰恰相反。 (上面的代码就是这样运行的)

    2. FASTEST 基于 GPU 的 块操作 -- 虽然可能,但会让您的项目花费大量时间来安排 GPU 设备/主机设备数据传输,以便每个块移动的数据少于 hte GPU-DRAM 允许的大小。所请求的计算具有如此低的数学/计算密度,因此无法证明这些开销是合理的,以进入基于 GPU 的模式。

    【讨论】:

    • 谢谢 - 我接受了另一个答案,因为它首先出现,但非常感谢您的额外解释和代码!
    • 很高兴知道您认为它很有用。 StackOverflow 支持用户通过 [+1] 投票来表达问题和答案的有用性。不要犹豫,使用它并享受成为这个伟大社区的活跃成员。
    • 谢谢 - 我实际上不知道我可以为我提出的问题做到这一点。
    • 这里不急。后来你可能会意识到,一个人甚至可能不接受并改变最佳品种投票:o) 很酷的事情是,你对社区感到满意。
    【解决方案3】:

    libvips是一个大图的图像处理系统。它流式传输图像,而不是执行单独的加载/处理/保存步骤,因此您可以处理比计算机内存量大得多的图像。它有一个方便的high-level python binding。对于此类任务,它应该是quicker than opencv。

    你可以像这样在 Python 中解决你的问题:

    #!/usr/bin/python
    
    import pyvips
    
    if len(sys.argv) < 3:
        print("usage: %s output-file in1 in2 ..." % sys.argv[0])
        sys.exit(1)
    
    outfile = sys.argv[1]
    input_names = sys.argv[2:]
    
    total = sum([pyvips.Image.new_from_file(filename, access="sequential")
                 for filename in input_names])
    avg = total / len(input_names)
    
    # avg will be a float image, cast back to 8-bit for write, or we'll 
    # get a float tiff
    avg.cast("uchar").write_to_file(outfile)
    

    像这样运行:

    $ time ./avg.py x.tif ~/pics/wtc*.tif
    memory: high-water mark 38.50 MB
    real    0m5.759s
    user    0m2.584s
    sys 0m0.457s
    

    这是在具有机械硬盘的机器上平均四个 10,000 x 10,000 RGB 图像,所以我猜你的数据集大约需要两分钟。内存使用量应在 100mb 左右。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-23
      • 2018-11-13
      • 2014-08-02
      • 2021-05-20
      • 2012-03-29
      • 2018-06-08
      相关资源
      最近更新 更多