alpha_composite 图像数据之处理方法细节

alpha_composite() 图像数据之处理方法细节

1. 事件内容

打开两个JPG的图像(图001.jpg, 图002.jpg), RGB格式, 都没有alpha图层.

dP3iRBfOFp.png!large 图001.jpg
EIIyPF2jl3.png!large 图002.jpg

使用convert("RGBA")转换成RGBA, 检查alpha图层内容都填满了255.

如果直接使用alpha_composite(), 只会看到第二张图像, 没合成效果.

3v5Vti6hbo.png!large 图003

图像转成RGBA后, 再使用putalpha(1), 检查alpha图层内容都填满了1.

再使用alpha_composite(), 将会看到两张图像合成的结果.

3sIaptsFjz.png!large 图004

2. 问题内容

问题一: alpha_composite()是如何计算两张图像pixel值, 而得到新图像pixel值 ?

问题二: alpha_composite()是如何计算两张图像alpha值, 而得到新图层alpha值 ?

注: 下方提供图像pixel值及alpha值数据供参考 (以R band + alpha为例, 僅列出部份值供对比用)


第一组 图001 (alpha值 = 255)

[001, 000, 000, 000, 255, 254, 255, 254, 255, 255, ... , 254]

[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, ... , 255]

第一组 图002 (alpha值 = 255)

[254, 255, 254, 255, 254, 255, 003, 000, 000, 254, ... , 255]

[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, ... , 255]

第一组 图003 (alpha_composite() 结果)

[254, 255, 254, 255, 254, 255, 003, 000, 000, 254, ... , 255]

[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, ... , 255]


第二组 图001 (alpha值 = 001)

[001, 000, 000, 000, 255, 254, 255, 254, 255, 255, ... , 254]

[001, 001, 001, 001, 001, 001, 001, 001, 001, 001, ... , 001]

第二组 图002 (alpha值 = 001)

[254, 255, 254, 255, 254, 255, 003, 000, 000, 254, ... , 255]

[001, 001, 001, 001, 001, 001, 001, 001, 001, 001, ... , 001]

第二组 图004 (alpha_composite() 结果)

[128, 128, 127, 128, 254, 254, 129, 127, 127, 254, ... , 254]

[002, 002, 002, 002, 002, 002, 002, 002, 002, 002, ... , 002]

### alpha_composite() 图像数据之处理方法细节

filename1 = "D:/图001.jpg"
filename2 = "D:/图002.jpg"

from PIL import Image

# Open two image jpg file
im1 = Image.open(filename1)
im2 = Image.open(filename2)

# Convert RBG to RGBA format to be with alpha band
im3 = im1.convert("RGBA")
im4 = im2.convert("RGBA")

# Alpha composite im4 over im3, then show the result 图003
result_im = Image.alpha_composite(im3, im4)
result_im.show()

# fill all alpha data in im3 and im4 with 1
im3.putalpha(1)
im4.putalpha(1)

# Alpha composite im4 over im3, then show the result 图004
result_im = Image.alpha_composite(im3, im4)
result_im.show()
Jason Yang
Jason990420
最佳答案

Image.alpha_composite(im1, im2) 工作原理如下:+1:

"""
algorithm of alpha_composite method: r2 over r1

r1, r2: pixel data
a1, a2: alpha data

factor_pixel = a2/(a2 + a1 * (1.0 - a2/ 255.0))
new_pixel = r2 * factor_pixel + r1 * (1 - factor_pixel)

factor_alpha = 1.0 - a2/255.0
new_alpha = a2 + a1 * factor_alpha

conclusion: Here, same method used for all three methods, but different
method implemented. Method 3 is used in Python PIL, so same result as
the data for confirmation. For method 2 and 3, it is caused by the iteration
error on interger and float number, but just small error 1.

"""

# list1 is destination image data
# list2 is source image data
# list3 is the final image data after Image.alpha_composite(destination_image, source_image)

list1_pixel = [1,0,0,0,255,254,255,254,255,255,254,
                1,0,0,0,255,254,255,254,255,255,254]
list1_alpha = [255,255,255,255,255,255,255,255,255,
                255,255,1,1,1,1,1,1,1,1,1,1,1]
list2_pixel = [254,255,254,255,254,255,3,0,0,254,255,
                254,255,254,255,254,255,3,0,0,254,255]
list2_alpha = [255,255,255,255,255,255,255,255,255,255,
                255,1,1,1,1,1,1,1,1,1,1,1]
list3_pixel = [254,255,254,255,254,255,3,0,0,254,255,
                128,128,127,128,254,254,129,127,127,254,254]
list3_alpha = [255,255,255,255,255,255,255,255,255,255,
                255,2,2,2,2,2,2,2,2,2,2,2]

# method 1

error = 0
item_different = 0

list_pixel = []
list_alpha = []

for index in range(len(list1_pixel)):
    dsta = list1_alpha[index] / 255.0
    srca = list2_alpha[index] / 255.0
    blend = dsta * (1.0 - srca)
    outa = srca + blend
    coef1 = srca / outa
    coef2 = 1 - coef1
    tmpr = list2_pixel[index] * coef1 + list1_pixel[index] * coef2
    pixel = int(tmpr + 0.5)
    alpha = int(outa * 255.0 + 0.5)
    list_pixel.append(pixel)
    list_alpha.append(alpha)
    difference1 = abs(pixel - list3_pixel[index])
    difference2 = abs(alpha - list3_alpha[index])
    error = error + difference1+ difference2
    if difference1:
        item_different += 1
    if difference2:
        item_different += 1

print("Method 1:")
print(item_different, "wrong items, the total differences counted:",error)

# method 1

error = 0
item_different = 0

list_pixel = []
list_alpha = []

for index in range(len(list1_pixel)):
    factor_pixel = list2_alpha[index] / (list2_alpha[index] + \
        list1_alpha[index] * (1.0 - list2_alpha[index]/ 255.0))
    pixel = list2_pixel[index] * factor_pixel + \
        list1_pixel[index]*(1 - factor_pixel)
    pixel = int(pixel + 0.5)
    factor_alpha = 1.0 - list2_alpha[index]/ 255.0
    alpha = list2_alpha[index] + list1_alpha[index] * factor_alpha
    alpha = int(alpha + 0.5)
    list_pixel.append(pixel)
    list_alpha.append(alpha)
    difference1 = abs(pixel - list3_pixel[index])
    difference2 = abs(alpha - list3_alpha[index])
    error = error + difference1+ difference2
    if difference1:
        item_different += 1
    if difference2:
        item_different += 1

print("Method 2:")
print(item_different, "wrong items, the total differences counted:",error)

# method 3

error = 0
item_different = 0

list_pixel = []
list_alpha = []

tmpr = 0
outa255 = 0

for index in range(len(list1_pixel)):
    blend = list1_alpha[index] * (255 - list2_alpha[index])
    outa255 = list2_alpha[index] * 255 + blend
    coef1 = list2_alpha[index] * 255 * 255 * 128 / outa255
    coef2 = 255 * 128 - coef1
    right8 = lambda a: ((int(a)>>8)+int(a)>>8)
    tmpr = list2_pixel[index] * coef1 + list1_pixel[index] \
        * coef2 + (0x80 << 7)
    pixel = right8(tmpr) >> 7
    alpha = right8(outa255 + 0x80);
    list_pixel.append(pixel)
    list_alpha.append(alpha)
    difference1 = abs(pixel - list3_pixel[index])
    difference2 = abs(alpha - list3_alpha[index])
    error = error + difference1 + difference2
    if difference1 != 0:
        item_different += 1
    if difference2 != 0:
        item_different += 1

print("Method 3")
print(item_different, "wrong items, the total differences counted:",error)
1年前 评论
讨论数量: 1
Jason990420

Image.alpha_composite(im1, im2) 工作原理如下:+1:

"""
algorithm of alpha_composite method: r2 over r1

r1, r2: pixel data
a1, a2: alpha data

factor_pixel = a2/(a2 + a1 * (1.0 - a2/ 255.0))
new_pixel = r2 * factor_pixel + r1 * (1 - factor_pixel)

factor_alpha = 1.0 - a2/255.0
new_alpha = a2 + a1 * factor_alpha

conclusion: Here, same method used for all three methods, but different
method implemented. Method 3 is used in Python PIL, so same result as
the data for confirmation. For method 2 and 3, it is caused by the iteration
error on interger and float number, but just small error 1.

"""

# list1 is destination image data
# list2 is source image data
# list3 is the final image data after Image.alpha_composite(destination_image, source_image)

list1_pixel = [1,0,0,0,255,254,255,254,255,255,254,
                1,0,0,0,255,254,255,254,255,255,254]
list1_alpha = [255,255,255,255,255,255,255,255,255,
                255,255,1,1,1,1,1,1,1,1,1,1,1]
list2_pixel = [254,255,254,255,254,255,3,0,0,254,255,
                254,255,254,255,254,255,3,0,0,254,255]
list2_alpha = [255,255,255,255,255,255,255,255,255,255,
                255,1,1,1,1,1,1,1,1,1,1,1]
list3_pixel = [254,255,254,255,254,255,3,0,0,254,255,
                128,128,127,128,254,254,129,127,127,254,254]
list3_alpha = [255,255,255,255,255,255,255,255,255,255,
                255,2,2,2,2,2,2,2,2,2,2,2]

# method 1

error = 0
item_different = 0

list_pixel = []
list_alpha = []

for index in range(len(list1_pixel)):
    dsta = list1_alpha[index] / 255.0
    srca = list2_alpha[index] / 255.0
    blend = dsta * (1.0 - srca)
    outa = srca + blend
    coef1 = srca / outa
    coef2 = 1 - coef1
    tmpr = list2_pixel[index] * coef1 + list1_pixel[index] * coef2
    pixel = int(tmpr + 0.5)
    alpha = int(outa * 255.0 + 0.5)
    list_pixel.append(pixel)
    list_alpha.append(alpha)
    difference1 = abs(pixel - list3_pixel[index])
    difference2 = abs(alpha - list3_alpha[index])
    error = error + difference1+ difference2
    if difference1:
        item_different += 1
    if difference2:
        item_different += 1

print("Method 1:")
print(item_different, "wrong items, the total differences counted:",error)

# method 1

error = 0
item_different = 0

list_pixel = []
list_alpha = []

for index in range(len(list1_pixel)):
    factor_pixel = list2_alpha[index] / (list2_alpha[index] + \
        list1_alpha[index] * (1.0 - list2_alpha[index]/ 255.0))
    pixel = list2_pixel[index] * factor_pixel + \
        list1_pixel[index]*(1 - factor_pixel)
    pixel = int(pixel + 0.5)
    factor_alpha = 1.0 - list2_alpha[index]/ 255.0
    alpha = list2_alpha[index] + list1_alpha[index] * factor_alpha
    alpha = int(alpha + 0.5)
    list_pixel.append(pixel)
    list_alpha.append(alpha)
    difference1 = abs(pixel - list3_pixel[index])
    difference2 = abs(alpha - list3_alpha[index])
    error = error + difference1+ difference2
    if difference1:
        item_different += 1
    if difference2:
        item_different += 1

print("Method 2:")
print(item_different, "wrong items, the total differences counted:",error)

# method 3

error = 0
item_different = 0

list_pixel = []
list_alpha = []

tmpr = 0
outa255 = 0

for index in range(len(list1_pixel)):
    blend = list1_alpha[index] * (255 - list2_alpha[index])
    outa255 = list2_alpha[index] * 255 + blend
    coef1 = list2_alpha[index] * 255 * 255 * 128 / outa255
    coef2 = 255 * 128 - coef1
    right8 = lambda a: ((int(a)>>8)+int(a)>>8)
    tmpr = list2_pixel[index] * coef1 + list1_pixel[index] \
        * coef2 + (0x80 << 7)
    pixel = right8(tmpr) >> 7
    alpha = right8(outa255 + 0x80);
    list_pixel.append(pixel)
    list_alpha.append(alpha)
    difference1 = abs(pixel - list3_pixel[index])
    difference2 = abs(alpha - list3_alpha[index])
    error = error + difference1 + difference2
    if difference1 != 0:
        item_different += 1
    if difference2 != 0:
        item_different += 1

print("Method 3")
print(item_different, "wrong items, the total differences counted:",error)
1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!