PIL如何从图像中去除背景图片

6

如果我有一张背景图片,能否将其从另一张图片中移除并获取到所有的差异?比如:

enter image description here

enter image description here

假设我有这两张图片保存。在保留所有猫的情况下,如何从第二张图片中删除第一张图片?
1个回答

8
根据PIL手册ImageChops模块具有减法操作:
ImageChops.subtract(image1, image2, scale, offset) => image
Subtracts two images, dividing the result by scale and adding the offset.
If omitted, scale defaults to 1.0, and offset to 0.0.
out = (image1 - image2) / scale + offset

你可以使用生成的图像作为带有猫的图像的蒙版:保留掩码中非零像素的位置,否则将它们变成所需的背景颜色。
下面是示例代码:
from PIL import Image
from PIL import ImageChops
image1 = Image.open("image1.jpg") # no cats
image2 = Image.open("image2.jpg") # with cats

image = ImageChops.subtract(image2, image1)

mask1 = Image.eval(image, lambda a: 0 if a <= 24 else 255)
mask2 = mask1.convert('1')

blank = Image.eval(image, lambda a: 0)

new = Image.composite(image2, blank, mask2) 
new.show()

它几乎可以工作 :-)

resulting image

两个图像之间的差异比看起来更大。因为这些图像存储为JPG格式,它们是有损的。它们会稍微以不同的方式呈现,因此减法操作不会总是在相同区域的像素上产生零(即黑色)。

因此,我必须使用lambda a: 0 if a <= 24 else 255用于eval函数以获得合理的结果。

如果使用无损图像,则应该正常工作。然后,您应该使用0 if a == 0 else 255创建掩码。

请注意,如果某些“猫”像素意外地与背景像素相同,则它们将显示为黑色像素。


我在ImageChops.subtract()行收到了“ValuesError:images do not match”的错误。 - Spooky
@NeonWizard 如果我使用您发布的图像,它对我来说可以正常工作。 我添加了我得到的图像。 可能您使用的原始图像不同,因为您已从背景图像创建了“猫”图像并在此过程中更改了一些图像属性(例如大小)。 您可以使用 print image.infoprint image.size 等打印图像属性。请参见 http://effbot.org/imagingbook/image.htm#tag-Image.Image.verify。 - NZD
我用另一个游戏进行了测试。我确保图像大小相同。http://i.imgur.com/eC2MZHb.png 和 http://i.imgur.com/UqSKEzN.png - Spooky
1
@NeonWizard 我遇到了和你一样的错误。原因是你的图片不同。其中一个是 RGB,另一个是 RGBA。如果我使用 image.convert('RGB') 将第二张图片转换为 RGB 格式,它就可以工作了。 - NZD
你是如何弄清一个是RGBA,另一个是RGB的? - Spooky
@NeonWizard 我使用了 image1 = Image.open("image3.png") 然后 print image1.mode。请参考http://effbot.org/imagingbook/image.htm#attributes - NZD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接