我有一堆位图图像(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")
答案 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,所以它会更快,可能不需要多处理。