如何在python/OpenCV中执行一系列非常大的图像平均?

如何在python/OpenCV中执行一系列非常大的图像平均?,python,performance,image-processing,numpy,out-of-memory,Python,Performance,Image Processing,Numpy,Out Of Memory,我正在处理30000x30000像素的TIFF图像,并希望一次平均11幅图像 如果可能的话,我更喜欢用python来实现,我想知道实现这一点的最佳方法是什么 我应该使用OpenCV还是只使用numpy 平均每个RGBA通道是否会独立提高性能 或者我应该将图像分割成更小的图像并独立处理它们,然后将生成的片段缝合在一起 使用openCV直接执行此操作会导致内存错误: im0 = cv2.imread( '5014.tif' ) im1 = cv2.imread( '5114.tif' ) im2 =

我正在处理30000x30000像素的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 )
您的“堆栈”具有“形状”
(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
您的“堆栈”具有“形状”
(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
需要改进哪些性能?
  • 更小静态内存占用——由于处理不会执行任何卷积运算,只需将处理方案更改为从30GB静态RAM占用到5GB左右即可。(代码示例以这种方式运行,遍历11个文件的序列)

  • aListOfFNAMEs=[''5014.tif',…]#设置:FNAMEs
    alistofceffs=[0.01、.002、.002、.002、.002、.002、…]#截止到11日
    输入=cv2.imread(aListOfFNAMEs[0])#加载
    anAveragedIMG=numpy.zeros(一个putimg.shape)#确保.copy,而不是view
    anAveragedIMG+=alistofceffs[0]*计算处理第一次加载
    对于范围(1,len(alistofceffs))内的aPtr:#迭代,处理其余部分
    输入=cv2.imread(aListOfFNAMEs[aPtr])#加载时重复使用内存
    平均dimg+=alistofceffs[aPtr]*一个计算过程
    cv2.imwrite(“avg.TIF”,平均值dimg)#保存
    del Animputing#发布给GC
    del anAveragedIMG#GC发布,完成。
    

  • 更快矢量化矩阵运算——由于处理允许numpy/openCV矢量化矩阵运算,RGB色平面分离为独立处理不会提高速度,相反。(上面的代码就是这样运行的)

  • 最快的基于GPU的块操作——在可能的情况下,会让您的项目花费大量时间安排GPU设备/主机设备数据传输,从而使每个块移动的数据少于GPU-DRAM允许的大小。请求的计算具有如此低的数学/计算密度,因此无法证明这些开销可以转入基于GPU的模式

  • 需要改进哪些性能?
  • 更小静态内存占用——由于处理不会执行任何卷积运算,只需将处理方案更改为从30GB静态RAM占用到5GB左右即可。(代码示例以这种方式运行,遍历11个文件的序列)

  • aListOfFNAMEs=[''5014.tif',…]#设置:FNAMEs
    alistofceffs=[0.01、.002、.002、.002、.002、.002、…]#截止到11日
    输入=cv2.imread(aListOfFNAMEs[0])#加载
    anAveragedIMG=numpy.zeros(一个putimg.shape)#确保.copy,而不是view
    anAveragedIMG+=alistofceffs[0]*计算处理第一次加载
    对于范围(1,len(alistofceffs))内的aPtr:#迭代,处理其余部分
    输入=cv2.imread(aListOfFNAMEs[aPtr])#加载时重复使用内存
    平均dimg+=alistofceffs[aPtr]*一个计算过程
    cv2.imwrite(“avg.TIF”,平均值dimg)#保存
    del Animputing#发布给GC
    del anAveragedIMG#GC发布,完成。
    

  • 更快矢量化矩阵运算——由于处理允许numpy/openCV矢量化矩阵运算,RGB色平面分离为独立处理不会提高速度,相反。(上面的代码就是这样运行的)

  • 最快的基于GPU的块操作——在可能的情况下,会让您的项目花费大量时间安排GPU设备/主机设备数据传输,从而使每个块移动的数据少于GPU-DRAM允许的大小。请求的计算具有如此低的数学/计算密度,因此无法证明这些开销可以转入基于GPU的模式

  • 是一种用于大图像的图像处理系统。它对图像进行流式处理,而不是执行单独的加载/处理/保存步骤,因此您可以处理比计算机内存量大得多的图像。它有一个方便的。它应该是用于这类任务的

    您可以用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
    
    这意味着在一台装有机械硬盘的机器上平均有四张10000 x 10000 RGB图像,所以我猜你的数据集大概需要两分钟。内存使用量应该在100mb左右

    是一种用于大图像的图像处理系统。它对图像进行流式处理,而不是执行单独的加载/处理/保存步骤,因此您可以处理比计算机内存量大得多的图像