RGBA图像直接叠加
因为在做图像补全任务时,想要展示缺陷图像的样子,需要将背景透明的mask图像加到原图像上,生成需要补全的图像.
原本的mask长这样
原本的图像长这样
预期的图片长这样
省流版: img.alpha_composite(mask)
我们发现背景是黑色的,一开始想的是创建一个新的图片,和目标图像一样大小,使用mask.getpixel((i,j))
去获取mask每一个像素点,然后如果获取的黑色的,那就设置新图的像素为原图的像素newImg.putpixel((i,j),originImg.getpixel((i,j)))
,大概这个思路,因为原图是没有通道的,可能要简单的修改. 之前试过,这个方法是可行的,但是速度太慢了,我要对上百张图片进行这个操作要好久,所以去找别的方法.
首先我希望把mask盖到原图像上,就像PS一样,透明的部分不会印象下面的内容.因此我先把不透明的mask转化成透明的,因为mask是通用的,所以一张图片的效率低可以接受,以下是代码和效果.
mask = Image.open("mask.png")
W, H = mask.size
newMask = Image.new("RGBA", mask.size, (0, 0, 0, 0))
for i in range(W):
for j in range(H):
# print(mask.getpixel((i, j)))
if mask.getpixel((i, j)) == (255, 255, 255):
newMask.putpixel((i, j), (255, 255, 255, 255))
newMask.save("newMask.png")
这里才知道
img.size
返回的是先是宽度,然后才是高
getpixel((i,j)), 这里的i和j也分别是宽的位置和高的位置.
得到了新的mask
希望把newMask直接盖到原图像上,查了半天,网上要么是一个个像素去判断的,效率难以接受,要么是用Image.blend(image,mask,alpha)
,这种方法会改变原图像的透明度,效果如此公式:
$$\text{image} * (1-\text{alpha})+\text{mask} * \text{alpha}$$
truthImg = Image.open(os.path.join(basepath, "truth", imgName))
newImg = Image.new('RGBA', truthImg.size, (255, 0, 0, 0))
newImg.paste(truthImg, (0, 0))
Image.blend(newImg, newMask, 0.5).show()
效果如下:
显然这不是我们想要的效果.
查了半天,终于找到了一个满足我要的效果,并且效率可以接受的方式,原来它自带一个函数: img.alpha_composite(mask)
truthImg = Image.open(os.path.join(basepath, "truth", imgName))
newImg = Image.new('RGBA', truthImg.size, (255, 0, 0, 0))
newImg.paste(truthImg, (0, 0))
newImg.alpha_composite(newMask)
newImg.show()
效果如下:
效果非常好!这就是我想要的!
如果是直接上传PNG,透明背景的图片上传到github图床好像现实的效果不是很好,就像下面这样