如何使用PIL(Python-Imaging)反转图像的颜色?

75

我需要将一系列以白色绘制在黑色背景字母形式的图像转换为颜色反转后的图像(即负片)。我该如何使用PIL实现这个目标?

7个回答

121
尝试查看文档中提供的以下内容:https://pillow.readthedocs.io/en/stable/reference/ImageOps.html
from PIL import Image
import PIL.ImageOps    

image = Image.open('your_image.png')

inverted_image = PIL.ImageOps.invert(image)

inverted_image.save('new_name.png')

注意:“ImageOps模块包含许多‘现成的’图像处理操作。该模块有些实验性,大多数运算符仅适用于L和RGB图像。”


哦,看起来我错过了那个模块。谢谢。 - bialix
是的,但是几个 PIL 实现会在图像模式不是 RGBL(即 RGBACMYK1)的情况下失败,这种情况下,您必须使用解决方法将源图像的波段转换为 L 图像,然后反转这些图像并将它们合并在一起(见下文)。 - mxl
模块“PIL”没有属性“ImageOps”。 - Yaroslav Dukal

40

如果图片是RGBA透明的,这样做会失败... 不过这个方法应该可以解决:

from PIL import Image
import PIL.ImageOps    

image = Image.open('your_image.png')
if image.mode == 'RGBA':
    r,g,b,a = image.split()
    rgb_image = Image.merge('RGB', (r,g,b))

    inverted_image = PIL.ImageOps.invert(rgb_image)

    r2,g2,b2 = inverted_image.split()

    final_transparent_image = Image.merge('RGBA', (r2,g2,b2,a))

    final_transparent_image.save('new_file.png')

else:
    inverted_image = PIL.ImageOps.invert(image)
    inverted_image.save('new_name.png')

2
好的,但这并不包括反转阿尔法通道。如果我也想反转阿尔法通道怎么办? - AgentM
1
这个回答虽然很老,但仍然像魔法一样有效。谢谢你! - Aniket Betkikar

31

对于任何使用“1”模式(即,1位像素,黑白色,每字节存储一个像素 - 请参阅文档)的图像,您需要在调用PIL.ImageOps.invert之前将其转换为“L”模式。

因此:

im = im.convert('L')
im = ImageOps.invert(im)
im = im.convert('1')

2
我希望有一种方法可以直接告诉其他使用类似掩码来反转的方法,而不是这种解决方式...但是好吧,现在它能用了! - nmz787

2

现在ImageOps必须:

PIL.ImageChops.invert(PIL.Image.open(imagepath))

请注意,这在我的Python 3.8.5版本中有效。


1

当然,ImageOps工具能够很好地完成其工作,但不幸的是它无法处理一些模式,比如“RGBA”。这段代码将解决这个问题。

def invert(image: Image.Image) -> Image.Image:
    drawer = ImageDraw.Draw(image)
    pixels = image.load()
    for x in range(image.size[0]):
        for y in range(image.size[1]):
            data = pixels[x, y]
            if data != (0, 0, 0, 0) and isinstance(data, tuple):
                drawer.point((x, y), (255 - data[0], 255 - data[1], 255 - data[2], data[3]))

    return image

0
如果有人想要反转一个 CMYK 图像,当前的 PIL 和 Pillow 实现似乎不支持此操作并会抛出错误。然而,你可以通过使用这个方便的函数(本质上是 Greg Sadetsky 上面的帖子的扩展)来反转图像的各个通道来轻松解决这个问题:
def CMYKInvert(img) :
    return Image.merge(img.mode, [ImageOps.invert(b.convert('L')) for b in img.split()])

-1
from PIL import Image

img = Image.open("archive.extension") 

pixels = img.load()

for i in range(img.size[0]):
    for j in range(img.size[1]):
        x,y,z = pixels[i,j][0],pixels[i,j][1],pixels[i,j][2]
        x,y,z = abs(x-255), abs(y-255), abs(z-255)
        pixels[i,j] = (x,y,z)

img.show()

`


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