Python 如何使用numpy数组中的RGBA数据列表进行alpha合成?

Python 如何使用numpy数组中的RGBA数据列表进行alpha合成?,python,arrays,numpy,multidimensional-array,alphablending,Python,Arrays,Numpy,Multidimensional Array,Alphablending,按照alpha混合两个颜色值的公式,我希望将其应用于rgba图像数据的n个numpy数组,尽管在实践中,预期用例的数组上限非常低,可能大于5。在上下文中,此过程将约束到形状相同的数组 理论上,我可以通过迭代来实现这一点,但预计这将是计算密集型的,而且效率极低 在整个阵列中,在两个阵列之间相同位置的两个元素之间应用函数的最有效方法是什么 一个松散的例子: # in context, the numpy arrays come from here, as either numpy data in t

按照alpha混合两个颜色值的公式,我希望将其应用于rgba图像数据的n个numpy数组,尽管在实践中,预期用例的数组上限非常低,可能大于5。在上下文中,此过程将约束到形状相同的数组

理论上,我可以通过迭代来实现这一点,但预计这将是计算密集型的,而且效率极低

在整个阵列中,在两个阵列之间相同位置的两个元素之间应用函数的最有效方法是什么

一个松散的例子:

# in context, the numpy arrays come from here, as either numpy data in the 
# first place or a path
def import_data(source):
    # first test for an extant numpy array
    try:
        assert(type(source) is np.ndarray)
        data = source
    except AssertionError:
        try:
            exists(source)
            data = add_alpha_channel(np.array(Image.open(source)))
        except IOError:
            raise IOError("Cannot identify image data in file '{0}'".format(source))
        except TypeError:
                raise TypeError("Cannot identify image data from source.")

    return data

# and here is the in-progress method that will, in theory composite the stack of 
# arrays; it context this is a bit more elaborate; self.width & height are just what  
# they appear to be—-the final size of the composited output of all layers

def render(self):
        render_surface = np.zeros((self.height, self.width, 4))
        for l in self.__layers:  
            foreground = l.render() # basically this just returns an np array
            # the next four lines just find the regions between two layers to 
            # be composited
            l_x1, l_y1 = l.origin
            l_x2 = l_x1 + foreground.shape[1]
            l_y2 = l_y1 + foreground.shape[0]
            background = render_surface[l_y1: l_y2, l_x1: l_x2]

            # at this point, foreground & background contain two identically shaped 
            # arrays to be composited; next line is where the function i'm seeking 
            # ought to go
            render_surface[l_y1: l_y2, l_x1: l_x2] = ?

从这两幅RGBA图像开始:

我实施了您链接的公式,并得出以下结论:

#!/usr/local/bin/python3
from PIL import Image
import numpy as np

# Open input images, and make Numpy array versions
src  = Image.open("a.png")
dst  = Image.open("b.png")
nsrc = np.array(src, dtype=np.float)
ndst = np.array(dst, dtype=np.float)

# Extract the RGB channels
srcRGB = nsrc[...,:3]
dstRGB = ndst[...,:3]

# Extract the alpha channels and normalise to range 0..1
srcA = nsrc[...,3]/255.0
dstA = ndst[...,3]/255.0

# Work out resultant alpha channel
outA = srcA + dstA*(1-srcA)

# Work out resultant RGB
outRGB = (srcRGB*srcA[...,np.newaxis] + dstRGB*dstA[...,np.newaxis]*(1-srcA[...,np.newaxis])) / outA[...,np.newaxis]

# Merge RGB and alpha (scaled back up to 0..255) back into single image
outRGBA = np.dstack((outRGB,outA*255)).astype(np.uint8)

# Make into a PIL Image, just to save it
Image.fromarray(outRGBA).save('result.png')
输出图像


从这两幅RGBA图像开始:

我实施了您链接的公式,并得出以下结论:

#!/usr/local/bin/python3
from PIL import Image
import numpy as np

# Open input images, and make Numpy array versions
src  = Image.open("a.png")
dst  = Image.open("b.png")
nsrc = np.array(src, dtype=np.float)
ndst = np.array(dst, dtype=np.float)

# Extract the RGB channels
srcRGB = nsrc[...,:3]
dstRGB = ndst[...,:3]

# Extract the alpha channels and normalise to range 0..1
srcA = nsrc[...,3]/255.0
dstA = ndst[...,3]/255.0

# Work out resultant alpha channel
outA = srcA + dstA*(1-srcA)

# Work out resultant RGB
outRGB = (srcRGB*srcA[...,np.newaxis] + dstRGB*dstA[...,np.newaxis]*(1-srcA[...,np.newaxis])) / outA[...,np.newaxis]

# Merge RGB and alpha (scaled back up to 0..255) back into single image
outRGBA = np.dstack((outRGB,outA*255)).astype(np.uint8)

# Make into a PIL Image, just to save it
Image.fromarray(outRGBA).save('result.png')
输出图像


使用OpenCV可能@MarkSetchell所以,这个解决方案可能是我的归宿,但我不希望仅仅因为一种方法而在项目中添加依赖项——这是一个广泛的学术研究发行包。我有理由相信有一种方法可以将numpy数组压缩到一个维度,并进行一些数组操作来实现这一点,我只是对这种编程远没有足够的能力来实现这一点。但是我很欣赏这一点,因为是的,如果没有一个只有numpy的解决方案,这是可行的。如果你给出一些示例数据,像这样的问题往往会得到更好的回答-可能会显示几行代码来生成5行的3个图像,6列和4个RGBA值,这样每个人都可以看到,由于所有维度都不同,什么被乘以了什么。@MarkSetchell我可以,但现实世界的上下文太复杂,无法显示,它是特定上下文的一个次要图形库,正如我的问题所述,我将始终使用相同形状的数组。它相当于一个NDARRAY列表,然后。。。其余的都是我的问题。但重点是,我会把一些生态上有效的东西放在一起。使用OpenCV可能@MarkSetchell所以,这个解决方案可能是我的归宿,但我不希望仅仅因为一种方法而在项目中添加依赖项——这是一个广泛的学术研究发行包。我有理由相信有一种方法可以将numpy数组压缩到一个维度,并进行一些数组操作来实现这一点,我只是对这种编程远没有足够的能力来实现这一点。但是我很欣赏这一点,因为是的,如果没有一个只有numpy的解决方案,这是可行的。如果你给出一些示例数据,像这样的问题往往会得到更好的回答-可能会显示几行代码来生成5行的3个图像,6列和4个RGBA值,这样每个人都可以看到,由于所有维度都不同,什么被乘以了什么。@MarkSetchell我可以,但现实世界的上下文太复杂,无法显示,它是特定上下文的一个次要图形库,正如我的问题所述,我将始终使用相同形状的数组。它相当于一个NDARRAY列表,然后。。。其余的都是我的问题。但重点是,我将把一些生态上有效的东西放在一起;泰。虽然我确实按照您的建议使用cv2实现了一个解决方案,但这显然是首选;泰。虽然我确实按照您的建议使用cv2实现了一个解决方案,但这显然是首选。