从一系列图像中查找最大x,y值

时间:2014-03-05 19:13:41

标签: python numpy multiprocessing

我有一堆位图图像(2000-4000之间),我正在进行z投影最大强度投影。所以从堆栈中,我需要为每个x,y位置获得一个2d的最大值数组。

我设计了一个简单的脚本,将文件分成块并使用multiprocessing.pool来计算该chuck的最大数组。然后比较这些数组以找到堆栈的最大值。

它有效,但速度很慢。我的系统监视器显示我的CPU几乎无法正常工作。

任何人都可以给我一些关于如何加快速度的指示吗?

import Image
import os
import numpy as np
import multiprocessing
import sys

#Get the stack of images
files = []
for fn in os.listdir(sys.argv[1]):
    if fn.endswith('.bmp'):
        files.append(os.path.join(sys.argv[1], fn))

def processChunk(filelist):
    first = True
    max_ = None
    for img in filelist:
        im = Image.open(img)
        array = np.array(im)
        if first:
            max_ = array
            first = False
        max_ = np.maximum(array, max_)
    return max_



if __name__ == '__main__':

    pool = multiprocessing.Pool(processes=8)

    #Chop list into chunks
    file_chunks = []
    chunk_size = 100
    ranges = range(0, len(files), chunk_size)

    for chunk_idx in ranges:
        file_chunks.append(files[chunk_idx:chunk_idx+chunk_size])

    #find the maximum x,y vals in chunks of 100
    first = True
    maxi = None
    max_arrays = pool.map(processChunk, file_chunks )

    #Find the maximums from the maximums returned from each process
    for array in max_arrays:
        if first:
            maxi = array
            first = False
        maxi = np.maximum(array, maxi)
    img = Image.fromarray(maxi)
    img.save("max_intensity.tif")

1 个答案:

答案 0 :(得分:4)

编辑:

对样本数据做了一些小的基准测试,你是对的。此外,事实证明(更密切地阅读你的代码),我的大部分原始帖子都是错误的。你基本上做了相同数量的迭代(稍微多一点,但不多3倍)。我也发现了

x = np.maximum(x, y)

比两者都快一点

x[y > x] = y[y > x]
#or
ind = y > x
x[ind] = y[ind]

然后我会稍微改变你的代码。类似的东西:

import numpy as np
from multiprocessing import Pool

def process(chunk):
    max_ = np.zeros((4000, 4000))
    for im in chunk:
        im_array = np.array(Image.open(im))
        max_ = np.maximum(max_, im_array)
    return max_

if __name__ == "__main__":
    p = Pool(8)

    chunksize = 500 #4000/8 = 500, might have less overhead
    chunks = [files[i:i+chunksize]
              for i in range(0, len(files), chunksize)]

    # this returns an array of (len(files)/chunksize, 4000, 4000)
    max_arrays = np.array(p.map(process, chunks))
    maxi = np.amax(max_array, axis=0) #finds maximum along first axis
    img = Image.fromarray(maxi) #should be of shape (4000, 4000)

我认为这是你可以做到这一点的最快方法之一,虽然我对树或锦标赛风格算法有所了解,也可能是递归算法。干得好。


图像有多大?小到足以一次将两个图像加载到内存中?如果是这样,那么你可以这样做:

maxi = np.zeros(image_shape) # something like (1024, 1024)

for im in files:
    im_array = np.array(Image.open(im))
    inds = im_array > maxi # find where image intensity > max intensity
    maxi[inds] = im_array[inds] # update the maximum value at each pixel 

max_im = Image.fromarray(maxi)
max_im.save("max_intensity.tif")

在所有迭代之后,maxi数组将包含每个(x,y)坐标的最大强度。不需要把它分成块。此外,只有一个for循环,而不是3,所以它会更快,可能不需要多处理。