用于堆叠图像的python代码运行速度非常慢,正在寻找加快速度的建议

用于堆叠图像的python代码运行速度非常慢,正在寻找加快速度的建议,python,performance,time-complexity,Python,Performance,Time Complexity,我已经写了一些代码来读取每150个像素的RGB值,1000像素x 720像素,经过裁剪和调整大小 import os from PIL import Image print("STACKING IMAGES...") os.chdir('cropped') images=os.listdir() #list all images present in directory print("GETTING IMAGES...") channelR=[] chan

我已经写了一些代码来读取每150个像素的RGB值,1000像素x 720像素,经过裁剪和调整大小

import os
from PIL import Image
print("STACKING IMAGES...")
os.chdir('cropped')
images=os.listdir() #list all images present in directory
print("GETTING IMAGES...")
channelR=[]
channelG=[]
channelB=[]
print("GETTING PIXEL INFORMATION...")  #runs reasonably fast
for image in images:  #loop through each image to extract RGB channels as separate lists
    with Image.open(image) as img:
        if image==images[0]:
            imgSize=img.size
        channelR.append(list(img.getdata(0)))
        channelG.append(list(img.getdata(1)))
        channelB.append(list(img.getdata(2)))
print("PIXEL INFORMATIION COLLECTED.")
print("AVERAGING IN CHANNEL RED.") #average for each pixel in each channel
avgR=[round(sum(x)/len(channelR)) for x in zip(*channelR)] #unzip the each pixel from all ~250 images, average it, store in tuple, starts to slow
print("AVERAGING IN CHANNEL GREEN.")
avgG=[round(sum(x)/len(channelG)) for x in zip(*channelG)] #slower
print("AVERAGING IN CHANNEL BLUE.")
avgB=[round(sum(x)/len(channelB)) for x in zip(*channelB)] #progressively slower
print("MERGING DATA ACROSS THREE CHANNELS.")
mergedData=[(x) for x in zip(avgR, avgG, avgB)]  #merge averaged colour channels pixel by pixel, doesn't seem to end, takes eternity
print("GENERATING IMAGE.")
stacked=Image.new('RGB', (imgSize)) #create image
stacked.putdata(mergedData) #generate image
stacked.show()
os.chdir('..')
stacked.save('stacked.tif', 'TIFF') #save file
print("FINISHED STACKING !")
Linux Mint操作系统在我的装备简陋的计算机Core2Duo(4GB内存)上运行,花了将近一个小时完成三个通道的平均化,再花一个小时合并单个平均像素,但没有完成,于是我中止了这个过程。我曾读到列表理解很慢,zip函数占用了太多内存,但修补这些会导致进一步的错误。我甚至读到,将程序划分为函数可能会加快速度

对于类似的性能,我会恳请回答问题的人在来自的图像上运行代码

任何加快该计划的帮助都将被感激地接受。在转向更强大的系统时,它是否有机会大幅提高速度


提前感谢您的帮助。

附加到列表的速度很慢。就像在一个循环中对可以做的事情有多个列表理解一样。您还可以使用numpy数组来加快它的速度,而不是在列表上迭代

下面是一些图片的示例代码。您可以根据自己的要求进行扩展

导入操作系统 将numpy作为np导入 进口PIL os.chdir“裁剪” imgfiles=['MVI_6450 001.jpg'、'MVI_6450 002.jpg'、'MVI_6450 003.jpg'、'MVI_6450 004.jpg'] allimgs=无 对于imgnum,枚举imgfiles中的imgfile: img=PIL.Image.openimgfile imgdata=np.arrayimg.getdata Nx3数组。列:R、G、B通道 如果allimgs为无: allshape=listimgdata.shape一幅图像的大小 allshape.appendlenimgfiles追加图像数 allshape现在是[num\u像素、num\u通道、num\u图像] 因此,制作这种形状的数组将允许我们存储所有图像 轴0:像素。轴1:通道。轴2:图像 allimgs=np.0形状 allimgs[:,:,imgnum]=imgdata设置imgnum的第个图像数据 得到最后一个轴的平均值 平均每个通道的所有图像中的相同像素 imgavg=np.meansallimgs,轴=-1 规格化,使最大值为255 也可以转换为uint8 imgavg=np.uint8imgavg/np.maximgavg*255 imgavg_tuple=tuplemaptuple,imgavg 堆叠=PIL.Image.newRGB,img.size 堆叠的.putdataimgavg_元组 表演 os.chdir'..'
注意:我们创建一个numpy数组,以在开始时保存所有图像,而不是在加载更多图像时追加,因为将其作为附加到numpy数组是一个非常糟糕的主意。这是因为numpy array append实际上创建了一个新数组,然后复制两个数组的内容,因此这是一个On ^2操作。

如果不在每个图像中的每个像素上循环两次,可能会节省一些时间。您可以为每个通道维护一个值列表,并在读取通道时将所有像素值除以图像数相加,而不是将完整的通道添加到一个大列表中以供以后分析。因此,你可以一次创建三个平均值列表。列表理解通常比没有理解的创建列表要慢。如果这些理解非常简单,扩展它们可能会节省一些时间slow@JacobSteinebronn,似乎表明了另一种情况,正如我所看到的许多其他链接一样。特别是当添加到列表中时。这很好!就我个人而言,我做过实验,发现列表比较慢,也许这取决于应用程序?在任何情况下,它都没有那么慢,就像20%或soTry tiffile.imwrite'stacked.tif',numpy.stack[imagecodecs.imreadname for name In glob.glob'*.jpg'].meanaxis=0.round.astype'uint8'使用和库一样。对于示例数据集,大约需要2秒。非常重要的注意:附加到numpy数组是可怕的!你最好把它附加到一个常规列表中。这是因为numpy.append不在适当的位置,所以要通过追加来构建一个包含n个项的列表,您需要在^2上追加,这显然是非常糟糕的。但是我的代码中的任何地方都没有追加到numpy数组?我没说您追加了,我只是指了指海报,因为他们似乎对这种事情比较陌生,像那样构建numpy阵列可能非常困难bad@PranavHosangadi,回溯最后一次调用:stackImg.py文件,第26行,位于stacked.putdataimgAvgTuple文件/usr/lib/python3/dist packages/PIL/Image.py,第1626行,在putdata self.im.putdatadata中,scale,offset TypeError:应为整数参数,got floatputdata要求像素值为int,但平均返回值为float