为什么打开并显示此图像时颜色会完全改变?如何将 ICC 配置文件添加到图像?

Why does colour completely changes when opening and showing this image? How do I add an ICC profile to an image?

这是原图:

这是我用Pillow打开展示后的图片:

原始图像是JPEG,但我尝试将格式更改为TIFF、PSD,但没有任何效果。我已经尝试将图像转换为 RGB、RGBA、CMYK,但看不到任何改进。

如果我简单地截取图像并在 Pillow 中打开它,颜色会保留。

然后我想我可能不需要Pillow,我可以使用另一个库,并尝试了OpenCV,但是同样的事情发生了!与上图相同的结果。

正如@HansHirse 在我上一个问题的评论中所建议的那样,post 让我意识到当我只保存图像时,颜色会保留下来。 (虽然只是打开和保存而不使用 ICC 配置文件生成准确的图像。)

from PIL import Image

i = Image.open("/Users/shashwataryal/Downloads/Tom Ford Rodeo.jpeg")

##Colours are preserved when I just save the image immediately after opening.
i.save("/Users/shashwataryal/Downloads/1.jpeg")

##however, if I create a new image and paste my image I have the same issue.
##The image is very saturated. (not dull like in the question @HansHirse suggested in my previous post)
layer = Image.new('RGB', i.size, "#faf8f8")
layer.show()
layer.paste(i)
layer.show()
layer.save('/Users/shashwataryal/Downloads/1.jpeg',icc_profile=i.info.get('icc_profile'))
layer.save('/Users/shashwataryal/Downloads/2.jpeg',icc_profile=i.info.get('icc_profile'))

我正在尝试将图像添加到新的空白枕头图像中,并且可能还会添加其他图像。我不知道如何将 ICC 配置文件添加到新图像中。如果我将它们粘贴到在 Pillow 中创建的新图像上,是否会影响其他图像?

我之前的问题被标记为重复:

虽然这个问题很相似,但它只是处理打开后立即保存图像的问题,我打开后立即保存没有问题。我的问题是在将它粘贴到一个大空白后保存它 canvas。

您需要 Pillow 的 ImageCms 模块:

The ImageCms module provides color profile management support [...]

对于以下演示代码,我使用了来自 here 的具有不同嵌入式 ICC 配置文件的示例图像。

from matplotlib import pyplot as plt
from PIL import Image, ImageCms
from io import BytesIO

# Infices for test image
infices = ['sRGB', 'AdobeRGB', 'ColorMatch', 'ProPhoto', 'WideRGB']

# Initialize output visualization
plt.figure(1, figsize=(19, 9))

# Iterate infices
for i_infix, infix in enumerate(infices, start=1):

    # Read image
    image = Image.open('Momiji-{}-yes.jpg'.format(infix))

    # Extract original ICC profile
    orig_icc = ImageCms.ImageCmsProfile(BytesIO(image.info.get('icc_profile')))
    desc = ImageCms.getProfileDescription(orig_icc)

    # Plot image with original ICC profile
    plt.subplot(2, len(infices), i_infix), plt.imshow(image)
    plt.title('Original ICC profile: {}'.format(desc))

    # Create sRGB ICC profile and convert image to sRGB
    srgb_icc = ImageCms.createProfile('sRGB')
    image = ImageCms.profileToProfile(image, orig_icc, srgb_icc)

    # Plot converted image with sRGB ICC profile
    plt.subplot(2, len(infices), len(infices) + i_infix), plt.imshow(image)
    plt.title('sRGB ICC profile')

plt.tight_layout(), plt.show()

代码提取每个示例图像的 ICC 配置文件,并将其存储为 CmsProfile object. Using ImageCms.createProfile, you can create an inbuilt sRGB ICC profile, which I used for rectifying all input images using ImageCms.profileToProfile:

如您所见,输入图像具有非常明显的颜色差异,而输出图像非常相似(我没有检查像素方面的相等性)。

如果您想保留特定输入图像的 ICC 配置文件,您可以简单地在开始时保存它,然后纠正所有输入图像 w.r.t。该 ICC 配置文件。例如,这将是将所有输入图像转换为“ProPhoto RGB”ICC 配置文件的输出:

因此,您需要打开图像,提取 ICC 配置文件,将图像粘贴到新空白 canvas,并将生成的图像转换为保存的 ICC 配置文件。如果您有来自不同来源的图像,因此可能具有不同的嵌入式 ICC 配置文件,您需要决定要做什么:(1) 校正所有输入图像,如上所示,合并可能的颜色差异或 (2) 实际转换颜色您的输入图像,使它们具有相同的外观,但使用最终结果的 ICC 配置文件。后者将单独成为一个话题。

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.19041-SP0
Python:        3.9.1
PyCharm:       2021.1.1
Matplotlib:    3.4.2
Pillow:        8.2.0
----------------------------------------