2010-07-30 47 views
12

Tôi có hai hình ảnh, cả hai đều có kênh alpha. Tôi muốn đặt một hình ảnh lên hình khác, dẫn đến một hình ảnh mới với một kênh alpha, giống như sẽ xảy ra nếu chúng được hiển thị trong các lớp. Tôi muốn làm điều này với Thư viện hình ảnh Python, nhưng các khuyến nghị trong các hệ thống khác sẽ là tuyệt vời, ngay cả toán học thô sẽ là một lợi ích; Tôi có thể sử dụng NumPy.Với Thư viện hình ảnh Python (PIL), làm cách nào để tạo hình ảnh với kênh alpha trên hình ảnh khác?

VỀ:

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

Trái ngược với sự pha trộn 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

này làm việc cho tôi: im.paste (hình ảnh, hộp, mặt nạ) http://stackoverflow.com/questions/5324647/how-to-merge-a-transparant-png-image -with-another-image-using-pil – Gonzo

Trả lời

15

tôi không thể tìm thấy một func alpha composite tion trong PIL, vì vậy đây là nỗ lực của tôi lúc thực hiện nó với 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 

Ví dụ cho hai hình ảnh này,

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 sản xuất:

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

enter image description here

+0

Làm việc như một sự quyến rũ. Cảm ơn. –

28

Điều này dường như làm các trick:

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

Tôi đã sửa chữa :) Cảm ơn bạn đã chia sẻ. – unutbu

+1

@ ~ unutbu Không, máy của bạn hoạt động tốt hơn. Tôi đã kết hợp giải pháp của bạn trong dự án của tôi. –

+1

Chỉ cần thử này và (a) nó hoạt động khá độc đáo, ít nhất là cho công việc nhanh chóng và bẩn tôi đang làm và (b) không yêu cầu phải được cài đặt. Lưu ý bình luận ở trên mặc dù. – dpjanes

19

Gối 2.0 bây giờ chứa một chức năng alpha_composite mà thực hiện điều này.

img3 = Image.alpha_composite(img1, img2) 
Các vấn đề liên quan