如何使用 scikit-image 和/或 PIL 将 ProPhoto RGB 色彩空间转换为 RGB?

问题描述

我有 ProPhoto RGB 色彩空间中的 TIF 文件。这些是使用 scikit-image 的“加载”方法导入的。但是,当我尝试使用 matplotlib 查看图像数据时,我收到错误:

plt.imshow(myImage)

plt.show()

使用 RGB 数据将输入数据剪切到 imshow 的有效范围(浮点数为 [0..1],整数为 [0..255])。

值被剪裁为 255,并显示全白图像。 imread 读取的图像数据的错误是正确的。值如下所示:

myImage[0]
array([[60061,60135,60673],[59907,59983,60533],[59931,60007,60557],...,[60649,60801,61147],[60581,60743,61091],[60647,60797,61143]],dtype=uint16)

显然需要对这些值进行缩放以获得范围在 0-255 之间的适当 RGB 值。

当我在 IrfanView 之类的东西中打开图像文件并重新保存它时,色彩空间被正确处理为 RGB(可能是因为 IrfanView 正在为我转换它)。但是,我需要自动执行该转换。

是否可以将使用 ProPhoto RGB 色彩空间的 TIF 转换为使用 scikit-image 或 PIL(或其他东西)的 RGB 色彩空间?我在 https://scikit-image.org/docs/stable/api/skimage.color.html 的 scikit-image 的“颜色”模块的文档中没有看到任何提及该颜色空间的内容。除非“ProPhoto RGB”可以被其他名称知道或与其他转换方法兼容?

谢谢!

编辑:

用户 Abhi25t 的回答有助于在显示这些图像方面取得一些进展。然而,他们的答案似乎只解决了 16 位到 8 位的转换。从 ProPhoto RGB 到 sRGB 仍然存在色彩空间问题。希望这次编辑能更好地证明这一点。

ProPhoto 色彩空间中原始测试 TIF 图像的像素值:

 array([[58465,58479,58785],[58575,58591,58879],[58441,58457,58739],[58185,58045,58549],[58101,57951,58463],[57993,57853,58371]],dtype=uint16)

Photoshop sRGB 转换文件的像素值:

array([[59771,59873,60161],[59863,59965,60235],[59755,59855,60119],[59623,59489,59993],[59561,59411,59925],[59463,59333,59851]],dtype=uint16)

IRFAN VIEW 转换文件的像素值(似乎已转换为 8 位并转换为 sRGB 空间):

array([[233,233,234],[233,[232,231,233],[231,233]],dtype=uint8)

我在这里添加了一些测试代码和图片: https://drive.google.com/drive/folders/1tcfUY2Kwlz-LAlt6_YXtT8l6vLnCucbM?usp=sharing

图像应显示为颜色检查器目标。您应该能够正确地看到它,只需绘制“TEST_PROPHOTO_IRFAN_SAVED.tif”的 imread 结果。

from skimage import io
import numpy as np
import matplotlib.pyplot as plt

# TEST_PROPHOTO.tif : RAW TIF FILE
# TEST_PROPHOTO_IRFAN_SAVED.tif : RAW TIF,OPENED IN IRFANVIEW AND RESAVED AS TIF
# TEST_SRGB_PHOTOSHOP_CONVERTED.tif : RAW TIF,OPENED IN PHOTOSHOP,PROFILE CONVERTED TO sRGB,RESAVED AS TIF

img_path = '/path/to/image/myImage.tif'

img_rgb = io.imread(img_path)
plt.imshow(img_rgb)
plt.show()

# VIEW IMAGE CONTENTS
img_rgb[0] # you can see these values are 16-bit;
# however,colorspace (actual RGB values) differs between the ProPhoto test file and the Photoshop converted sRGB file

# STACKOVERFLOW USER Abhi25t's METHOD TO CONVERT FROM 16-bit color [0-65535] to 8-bit color [0-255]:
img_rgb_convert = img_rgb * (255/65535)
img_rgb_convert = img_rgb_convert.astype(int)
plt.imshow(img_rgb_convert)
plt.show()

解决方法

您需要执行以下步骤:

  1. 使用 imread 读取图像。
  2. 转换为 [0-1] 范围内的浮点表示,即转换为浮点数并除以 65535。
  3. 使用 RIMM-ROMM RGB decoding function 解码。
  4. 使用 required colour conversion matrix 将 RIMM-ROMM RGB 色域转换为 sRGB 色域:
# Using CAT02.
[[ 2.0364917242 -0.7375906525 -0.2992598689]
 [-0.2257179791  1.2231765313  0.0027252248]
 [-0.0105451286 -0.1348798497  1.1452101525]]
  1. 使用 sRGB inverse Electro-Optical Transfer Function 进行编码。
  2. 转换为 [0-255] 范围内的整数表示,即乘以 255 并转换为整数。

Colour 可以直接使用 colour.RGB_to_RGB 定义进行 3 到 5 次。假设数据已经在浮点范围内,转换将如下所示:

img_rgb_convert = colour.RGB_to_RGB(
    img_rgb,colour.RGB_COLOURSPACES['ProPhoto RGB'],colour.RGB_COLOURSPACES['sRGB'],chromatic_adaptation_transform='CAT02',apply_cctf_decoding=True,apply_cctf_encoding=True)

注意:因为 ProPhoto RGB 的色域比 sRGB 的色域大,转换可能会产生色域外的颜色,这些颜色可以被剪掉为简单起见,在第 4 步或第 5 步之后的范围 [0-1] 或使用专用算法进行色域映射。

ProPhoto RGB & sRGB

,

您需要在此处将 16 位分辨率(灰度)转换为 8 位。

myImage = myImage * 255/65535

然后matplotlib就可以显示了。

如果需要,将您的浮点数转换为 int。

myImage = myImage.astype(int)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...