【问题标题】:Transparency is turned to an olive green透明度变成橄榄绿
【发布时间】:2020-04-30 20:05:52
【问题描述】:

这段代码:

import numpy
import PIL.Image

base = PIL.Image.open('grin-emoji-by-twitter.png').convert('RGBA')
base2 = numpy.array(base)
print(base2.shape)
print(base2)

产生以下输出:

(512, 512, 4)        # 512 px by 512 px with RGBA channels
[[[ 71 112  76   0]  # list of all the RGBA pixels...
  [ 71 112  76   0]  # ...visible as an olive green shade when saved
  [ 71 112  76   0]
                     # ...and so on...

显示左上角的像素:虽然它们应该是透明的([0 0 0 0]),但它们不是一些奇怪的橄榄绿色阴影([71 112 76 0])(左图:原图,右图:“已处理”):

这个错误很奇怪,因为这是打开 RGBA 图像和convert them to NumPy 的“正确”方式。使用 numpy.asarray 也无济于事。

复制的原始文件是here,虽然它是彩色映射的(调色板图像),这可能是我的问题的根源。但是我使用.convert('RGBA') 将其从彩色映射转换为RGBA 图像。使用的 PIL 版本是 6.1.0。

【问题讨论】:

  • 你是如何从数组中生成行为不端的文件的?您的代码示例未显示。
  • @AKX 当我们遇到print 语句时,图像已经是橄榄色了。所以错误在于加载和添加保存代码只会分散注意力。
  • 在将图像加载到代码中之前,我尝试了在 Gimp 中将图像转换为 RGBA 的明显替代解决方案,但 imageio 无论如何都无法将透明层保存到 GIF 中。唉,我得用另一个库了。
  • @xjcl 关于 Pillow 中使用的不同模式的一些说明,请参阅下面的答案。此外,正如 AKX 之前所要求的,请提供生成“错误”输出的代码。据推测,alpha 通道没有正确导出,例如保存为 JPG 时可能发生这种情况。
  • 另外,@xjcl – 你最终想要达到什么目的?最后的评论稍微说明了一些事情,但是..?

标签: python python-3.x image-processing python-imaging-library


【解决方案1】:

没有错误,但可能是对 Pillow 中不同的 modes 工作方式的误解。

如您所见,有问题的图像是托盘图像。但是,通过将图像显式转换为RGBA 模式,来自原始调色板和透明度的所有信息都被“处理”,因此当转换为某个 NumPy 数组时,您将只能看到从调色板中获取的颜色,以及 alpha频道已提取。

如果不做任何转换就打开图片,会自动采用P(或者PA)模式,一些提取出来的NumPy数组只有一个通道。我们来看下面的例子:

from matplotlib import pyplot as plt
import numpy as np
from PIL import Image

plt.figure(1, figsize=(10, 9))

# Read image with Pillow, explicit RGBA mode
image_pil = Image.open('grin-emoji-by-twitter.png').convert('RGBA')
plt.subplot(2, 2, 1), plt.imshow(image_pil), plt.title('Pillow image; explicit RGBA mode')
image_np = np.array(image_pil)
plt.subplot(2, 2, 2), plt.imshow(image_np), plt.title('NumPy array')

print("Image.open(...).convert('RGBA'):")
print(image_np.shape, image_np.dtype, '\n')

# Palette of Pillow image
print("Palette:")
print(image_pil.getpalette(), '\n')

# Image info of Pillow image
print("Information:")
print(image_pil.info, '\n')

# Read image with Pillow, no mode set, P mode is taken implicitly
image_pil = Image.open('grin-emoji-by-twitter.png')
plt.subplot(2, 2, 3), plt.imshow(image_pil), plt.title('Pillow image; implicit P mode')
image_np = np.array(image_pil)
plt.subplot(2, 2, 4), plt.imshow(image_np), plt.title('NumPy array')

print("Image.open(...):")
print(image_np.shape, image_np.dtype, '\n')

# Palette of Pillow image
print("Palette:")
print(image_pil.getpalette(), '\n')

# Image info of Pillow image
print("Information:")
print(image_pil.info)

plt.tight_layout()
plt.show()

这是图像输出:

如您所见,两种模式的 Pillow 图像相同,但提取的 NumPy 数组不同(四通道 RGBA 与单通道)。

让我们进一步看看print 的输出:

Image.open(...).convert('RGBA'):
(512, 512, 4) uint8 

Palette:
None 

Information:
{} 

Image.open(...):
(512, 512) uint8 

Palette:
[71, 112, 76, 255, 202, 78, ... ] 

Information:
{'transparency': b"\x00\x0e\x02\..."}

我们再次看到了 NumPy 数组的不同之处。但是,您还可以看到,调色板和透明度信息不再存储为显式 RGBA 转换后的 Pillow 图像的元数据,而是编码到像素值本身,而在使用模式 P 加载时它们会保持不变.此外,您会看到[71, 112, 76](橄榄绿色)用于所有0 像素值,即背景。 (为什么选择这种颜色,是另一个问题。)

因此,根据您希望使用提取的 NumPy 数组实现的目标,在使用 Pillow 加载图像时使用模式 P

希望有帮助!

----------------------------------------
System information
----------------------------------------
Platform:    Windows-10-10.0.16299-SP0
Python:      3.8.1
Matplotlib:  3.2.0rc1
NumPy:       1.18.1
Pillow:      7.0.0
----------------------------------------

【讨论】:

    【解决方案2】:

    对,我在 cmets 中误会了……

    关键是完全透明像素的 RGB 颜色无关紧要 - [0 0 0 0] 与 [71 112 76 0] 一样透明 - 某些软件选择了橄榄绿色作为该特定图像的透明像素。

    任何查看器 - MatPlotLib 可能? – 您用来查看的矩阵显然无法正确显示 Alpha 通道,因此它选择根本不解释它。

    如果您需要查看背景颜色更清晰的图像,可以使用.paste(im, mask=im) 让 Pillow 使用图像的 Alpha 通道作为透明蒙版。

    我使用#FF00FF、affectionately known as Magic Pink 来更好地展示效果,但您可能想要白色。

    import PIL.Image
    
    background_color = (255, 0, 255)
    
    base = PIL.Image.open('grin-emoji-by-twitter.png').convert('RGBA')
    
    matte = PIL.Image.new('RGBA', base.size)
    matte.paste(background_color, box=(0, 0) + base.size)
    matte.paste(base, mask=base)
    matte.save('matte.png')
    

    【讨论】:

      猜你喜欢
      • 2015-12-19
      • 1970-01-01
      • 2021-09-22
      • 2015-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多