Как преобразовать цветовое пространство ProPhoto RGB в RGB с помощью scikit-image и / или PIL?

#python #computer-vision #python-imaging-library #scikit-image #color-space

#питон #компьютерное зрение #python-imaging-library #scikit-image #цветовое пространство

Вопрос:

У меня есть файлы TIF, которые находятся в цветовом пространстве ProPhoto RGB. Они отлично импортируются с помощью метода «imload» scikit-image. Однако, когда я пытаюсь использовать matplotlib для просмотра данных изображения, я получаю сообщение об ошибке:

 plt.imshow(myImage)

plt.show()
 

Обрезка входных данных до допустимого диапазона для imshow с данными RGB ([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)
 

Очевидно, что эти значения необходимо масштабировать, чтобы получить правильные значения RGB в диапазоне от 0 до 255.

Когда я открываю файл изображения в чем-то вроде IrfanView и повторно сохраняю его, цветовое пространство обрабатывается правильно как RGB (вероятно, потому, что IrfanView преобразует его для меня). Однако мне нужно автоматизировать это преобразование.

Возможно ли преобразовать TIF с использованием цветового пространства ProPhoto RGB в цветовое пространство RGB с использованием scikit-image или PIL (или чего-то еще)? Я не видел никаких упоминаний об этом цветовом пространстве в документах для модуля «color» scikit-image в https://scikit-image.org/docs/stable/api/skimage.color.html . Разве «ProPhoto RGB» может быть известен под другим именем или совместим с другим методом преобразования?

Спасибо!

Редактировать:

Ответ пользователя Abhi25t помог добиться некоторого прогресса в отображении этих изображений. Однако их ответ, похоже, касается только преобразования 16-разрядного в 8-разрядное. Все еще существует проблема с цветовым пространством ProPhoto RGB в sRGB. Надеюсь, это редактирование демонстрирует это лучше.

Значения пикселей для необработанного тестового TIF-изображения в цветовом пространстве ProPhoto:

  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, 233, 234],
       [232, 233, 234],
       ...,
       [232, 231, 233],
       [232, 231, 233],
       [231, 231, 233]], dtype=uint8)
 

Я добавил сюда несколько тестовых кодов и изображений:
https://drive.google.com/drive/folders/1tcfUY2Kwlz-LAlt6_YXtT8l6vLnCucbM?usp=sharing

Изображение должно отображаться как цель проверки цвета. Вы должны быть в состоянии увидеть это правильно, просто построив результат imread для «TEST_PROPHOTO_IRFAN_SAVED.tif».

 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. Может быть, вы можете поделиться TIFF ProPhoto через Dropbox или GoogleDrive, чтобы люди могли экспериментировать?

Ответ №1:

Вам нужно будет выполнить следующие шаги:

  1. Прочитайте изображение с imread помощью .
  2. Преобразовать в представление с плавающей запятой в диапазоне [0-1], т. Е. Преобразовать в число с плавающей запятой и разделить на 65535.
  3. Декодируйте с помощью функции декодирования RIMM-ROMM RGB.
  4. Преобразование из 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.
  2. Преобразовать в целочисленное представление в диапазоне [0-255], т.Е. умножить на 255 и преобразовать в целое число.

Цвет может выполнять от 3 до 5 напрямую, используя определение color.RGB_to_RGB. Предполагая, что данные уже находятся в диапазоне с плавающей запятой, преобразование будет таким:

 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, возможно, что при преобразовании будут получены цвета, не соответствующие гамме. Для простоты их можно обрезать в диапазоне [0-1] после шага 4 или 5 или отобразить гамму с помощью специального алгоритма.

ProPhoto RGB и sRGB

Комментарии:

1. Спасибо! Это очень близко к полному ответу. Тем не менее, я нахожу, что при реализации этого значения получаются странными. Например, после вашего шага 5 я запускаю: (img_rgb_convert * 255).astype(‘int’) (т. Е. Для выполнения вашего шага 6). Это создает массив, содержащий значения до 287 и до -462 для моего тестового файла. Обрезка их на 0 и 255, похоже , дает достоверные результаты (хотя я не уверен, что смогу легко воспринимать любые тонкие различия в цвете), но правильный ли это подход?

2. Наконец, я загрузил преобразованный в IrfanView файл и использовал numpy.subtract для сравнения значений RGB с не обрезанным (img_rgb_convert * 255).astype(‘int’)[Результат шага 6]. Эта разница может варьироваться от -462 до 32. Сравнение с обрезанным img_rgb_convert дает диапазон от -23 до 24. Это кажется проблемой, если только проблема не связана с преобразованием IrfanView?

3. > Это создает массив, содержащий значения до 287 и до -462 для моего тестового файла. Это неудивительно, потому что ProPhoto RGB имеет более широкую гамму, чем sRGB, и вы можете получить цвета, которые выходят за рамки гаммы. В качестве дополнительного шага, после 4 или 5, вы можете ограничить свои цвета так, чтобы они находились в диапазоне 0-1.

4. Еще раз спасибо. Это имеет большой смысл! Что вы думаете о разнице между преобразованными в IrfanView и обрезанными результатами «img_rgb_convert»?

5. Я не уверен, что, не имея возможности просмотреть код IrfanView, как вы видели, существует немало способов, которыми преобразование может пойти не так, если не соблюдать осторожность! Например, они, возможно, не выполняют хроматическую адаптацию, которая требуется, потому что источники освещения разные.

Ответ №2:

Здесь вам нужно преобразовать 16-битное разрешение (в оттенках серого) в 8-битное.

 myImage = myImage * 255/65535
 

И тогда matplotlib сможет отображаться.

При необходимости преобразуйте значения с плавающей точкой в int.

 myImage = myImage.astype(int)
 

Комментарии:

1. Я думаю, что 255/65535 должно быть (255/65535) Это помогло, однако проблема преобразования цветового пространства остается. Я попытался прояснить свой вопрос.