Python 一种求多幅RGB图像中值的有效方法

Python 一种求多幅RGB图像中值的有效方法,python,opencv,python-imaging-library,median,Python,Opencv,Python Imaging Library,Median,我正在使用Python中的一个脚本,其中我希望找到相同维度的多个图像的中间值。也就是说,我不想把所有(红、绿、蓝)像素都放在[x,y]的位置,然后用它们的中值构建一个新图像 我当前的方法使用PythonPIL(图像库),但速度非常慢!我非常希望使用OpenCV(cv2)接口,因为它直接将每个图像作为numpy数组加载。然而,我在堆叠x维图像(25601920,3)时不断得到错误的索引。有什么帮助吗 我当前使用PIL的低效代码如下: from PIL import Image, ImageChop

我正在使用Python中的一个脚本,其中我希望找到相同维度的多个图像的中间值。也就是说,我不想把所有(红、绿、蓝)像素都放在[x,y]的位置,然后用它们的中值构建一个新图像

我当前的方法使用PythonPIL(图像库),但速度非常慢!我非常希望使用OpenCV(cv2)接口,因为它直接将每个图像作为numpy数组加载。然而,我在堆叠x维图像(25601920,3)时不断得到错误的索引。有什么帮助吗

我当前使用PIL的低效代码如下:

from PIL import Image, ImageChops,ImageDraw,ImageFilter,cv
import sys,glob,sys,math,shutil,time,os, errno,numpy,string
from os import *

inputs = ()
path = str(os.getcwd())
BGdummyy=0
os.chdir(path)
for files in glob.glob("*.png"):
    inputs = inputs + (str(str(files)),)
BGdummy=0
for file in inputs:
    BGdummy=BGdummy+1
    im = cv.LoadImage(file)
    cv.CvtColor( im, im, cv.CV_BGR2RGB )
    img = Image.fromstring("RGB", cv.GetSize(im), im.tostring())
    vars()["file"+str(BGdummy)] = img.load()
imgnew = Image.new("RGB", (2560,1920))
pixnew = imgnew.load()
for x in range(2560):
    for y in range(1920):
        R=[];G=[];B=[];
        for z in range(len(inputs)):
            R.append(vars()["file"+str(z+1)][x,y][0])
            G.append(vars()["file"+str(z+1)][x,y][1])
            B.append(vars()["file"+str(z+1)][x,y][2])
        R = sorted(R)
        G = sorted(G)
        B = sorted(B)
        mid = int(len(inputs)/2.)
        Rnew = R[mid]
        Gnew = G[mid]
        Bnew = B[mid]
        pixnew[x,y] = (Rnew,Gnew,Bnew)
    BGdummyy = BGdummyy+1
imgnew.save("NewBG.png")

我将演示如何使用5个大小为(3,3,3)的小数组执行此操作

首先,我将创建5个数组,然后将它们保存在列表X中。在您的情况下,您将在该列表中保留30个图像。(我在一行中完成)

接下来,将每个图像展平为一行。所以早些时候你的形象会是这样的

[R1G1B1 R2G2B2 R3G3B3,
 R4G4B4 R5G5B5 R6G6B6,
 R7G7B7 R8G8B8 R9G9B9]
这将变成
[R1 G1 B1 R2 G2 B2 R3 G3 B3………R9 G9 B9]
。然后将所有这些展平的图像叠加,形成一个大的二维阵列。在那个数组中,你们看,所有第一个红色像素都出现在第一列中,依此类推。然后你可以简单地应用np.median

Y = np.vstack((x.ravel() for x in X))
我用肥皂泡洗了每张照片,然后把它们叠起来。在我的例子中,Y是一个大小为5x27的数组(行-图像数,列-图像中的像素数)

现在我找到Y的中间值,并将其重塑为原始图像形状:

Z = np.median(Y,axis = 0)
Z = np.uint8(Z.reshape(a.shape))
完成了

为了确保它工作正常,让我们检查任意像素的值,比如说
Z[0,1,2]

In [50]: G1 = [x[0,1,2] for x in X]

In [51]: G1
Out[51]: [225, 65, 26, 182, 51]

In [52]: Z[0,1,2]
Out[52]: 65.0

是的,数据是正确的。

我从未使用过它,但它可能值得检查
scipy
——它将作为一个数组加载,您可以使用它进行操作。我的问题是,我有30个图像,我想将它们的中值转换为一个新图像。所以我需要的是:3个红色、绿色和蓝色像素的堆栈。x和y方向是像素的方向,而z方向是单个图像。在每个像素(x,y),我想要z方向的中值。因此,我现在最大的问题是找到一种方法,以一种合理的3D方式堆叠图像,然后我可以利用您建议的“np.media”命令。如果没有道理,请告诉我,然后我会尽量详细解释对不起,我误解了你的问题。检查我是否正确:您有30幅彩色图像。结果也是彩色图像。在结果图像中,第一个像素的蓝色值是所有30幅图像的第一个像素->蓝色值的中值。同样,对于红色和绿色等,这就是你想要的吗?完全正确(或任意数量的图像)。我现在可以用PIL库来做,但速度相当慢,因为我需要使用“加载像素”命令。我想保留Numpy和OpenCV(2)中的所有内容,正如您已经建议的那样。但基本上,我一直在摸索添加numpy数组以获得中值。提前谢谢!但是内存不是很贵吗?您需要将30个图像加载到内存中。在这种情况下,内存并不昂贵。即使是30个tiff格式的图像和2560x1920也不成问题,只有420 mb。
In [50]: G1 = [x[0,1,2] for x in X]

In [51]: G1
Out[51]: [225, 65, 26, 182, 51]

In [52]: Z[0,1,2]
Out[52]: 65.0