2010-07-30 95 views
12

我有两个图像,都与alpha通道。我想把一个图像放在另一个图像上,产生一个带有alpha通道的新图像,就像在图层中渲染时一样。我想用Python Imaging Library来做到这一点,但在其他系统中的建议将会非常棒,即使原始数学也会是一个福音。我可以使用NumPy。使用Python成像库(PIL),如何在另一个图像上使用Alpha通道组成图像?

OVER:

a http://dl.dropbox.com/u/1688099/ennorath/tmp/a.png + b http://dl.dropbox.com/u/1688099/ennorath/tmp/b.png = blend http://dl.dropbox.com/u/1688099/ennorath/tmp/over.png

与之相对BLEND 0.5:

a http://dl.dropbox.com/u/1688099/ennorath/tmp/a.png + b http://dl.dropbox.com/u/1688099/ennorath/tmp/b.png = blend http://dl.dropbox.com/u/1688099/ennorath/tmp/blend.png

+0

这个工作对我来说:im.paste(图像,盒,面罩) http://stackoverflow.com/questions/5324647/how-to-merge-a-transparant-png-image -with-another-image-using-pil – Gonzo 2011-12-16 14:13:06

回答

15

我无法找到一个alpha composite FUNC重刑在PIL,所以这里是我与numpy的实现它的企图:

import numpy as np 
from PIL import Image 

def alpha_composite(src, dst): 
    ''' 
    Return the alpha composite of src and dst. 

    Parameters: 
    src -- PIL RGBA Image object 
    dst -- PIL RGBA Image object 

    The algorithm comes from http://en.wikipedia.org/wiki/Alpha_compositing 
    ''' 
    # http://stackoverflow.com/a/3375291/190597 
    # http://stackoverflow.com/a/9166671/190597 
    src = np.asarray(src) 
    dst = np.asarray(dst) 
    out = np.empty(src.shape, dtype = 'float') 
    alpha = np.index_exp[:, :, 3:] 
    rgb = np.index_exp[:, :, :3] 
    src_a = src[alpha]/255.0 
    dst_a = dst[alpha]/255.0 
    out[alpha] = src_a+dst_a*(1-src_a) 
    old_setting = np.seterr(invalid = 'ignore') 
    out[rgb] = (src[rgb]*src_a + dst[rgb]*dst_a*(1-src_a))/out[alpha] 
    np.seterr(**old_setting)  
    out[alpha] *= 255 
    np.clip(out,0,255) 
    # astype('uint8') maps np.nan (and np.inf) to 0 
    out = out.astype('uint8') 
    out = Image.fromarray(out, 'RGBA') 
    return out 

例如给出这两个图像,

img1 = Image.new('RGBA', size = (100, 100), color = (255, 0, 0, 255)) 
draw = ImageDraw.Draw(img1) 
draw.rectangle((33, 0, 66, 100), fill = (255, 0, 0, 128)) 
draw.rectangle((67, 0, 100, 100), fill = (255, 0, 0, 0)) 
img1.save('/tmp/img1.png') 

enter image description here

img2 = Image.new('RGBA', size = (100, 100), color = (0, 255, 0, 255)) 
draw = ImageDraw.Draw(img2) 
draw.rectangle((0, 33, 100, 66), fill = (0, 255, 0, 128)) 
draw.rectangle((0, 67, 100, 100), fill = (0, 255, 0, 0)) 
img2.save('/tmp/img2.png') 

enter image description here

alpha_composite产生:

img3 = alpha_composite(img1, img2) 
img3.save('/tmp/img3.png') 

enter image description here

+0

工程就像一个魅力。谢谢。 – 2010-07-31 03:06:28

28

这似乎这样的伎俩:

from PIL import Image 
bottom = Image.open("a.png") 
top = Image.open("b.png") 

r, g, b, a = top.split() 
top = Image.merge("RGB", (r, g, b)) 
mask = Image.merge("L", (a,)) 
bottom.paste(top, (0, 0), mask) 
bottom.save("over.png") 
+0

我站在更正:)感谢分享。 – unutbu 2010-07-31 03:11:11

+1

@〜unutbu不,你的效果更好。我已将您的解决方案并入我的项目中。 – 2010-08-02 03:08:20

+1

刚刚尝试过这一个,并且(a)它工作得非常好,至少对于我正在做的快速和肮脏的任务和(b)不需要安装numpy。注意上面的评论。 – dpjanes 2011-06-20 11:16:36

19

枕头2.0现在包含一个alpha_composite功能做到这一点。

img3 = Image.alpha_composite(img1, img2) 
相关问题