Вы можете сделать это с помощью PIL / Pillow, используя встроенную систему управления цветом и создавая преобразование следующим образом:
#!/usr/local/bin/python3
import numpy as np
from PIL import Image, ImageCms
# Open image and discard alpha channel which makes wheel round rather than square
im = Image.open('colorwheel.png').convert('RGB')
# Convert to Lab colourspace
srgb_p = ImageCms.createProfile("sRGB")
lab_p = ImageCms.createProfile("LAB")
rgb2lab = ImageCms.buildTransformFromOpenProfiles(srgb_p, lab_p, "RGB", "LAB")
Lab = ImageCms.applyTransform(im, rgb2lab)
И Lab
теперь ваше изображение в цветовом пространстве Lab.Если вы продолжите и добавите следующие строки в конец приведенного выше кода, вы можете разделить изображение Lab на составляющие его каналы и сохранить каждое из них как изображения в оттенках серого для проверки.
# Split into constituent channels so we can save 3 separate greyscales
L, a, b = Lab.split()
L.save('L.png')
a.save('a.png')
b.save('b.png')
Итак, если выначните с этого изображения:
вы получите это как L
канал:
это канал a
:
и канал b
:
На мгновение ненаучный канал a
должен быть отрицательным / низким, если изображение зеленым, и высоким / положительным, если изображение пурпурноетак это выглядит правильно.И канал b
должен быть отрицательным / низким, если изображение синим, и высоким / положительным, где желтый, так что это выглядит довольно хорошо для меня!Что касается канала L
, формула от RGB к оттенкам серого выглядит (вне головы) примерно так:
L = 0.2*R + 0.7*G + 0.1*B
Так что можно ожидать, что канал L
будет намного ярче, чем изображениезеленый и самый темный там, где синий.
В качестве альтернативы, вы можете сделать это с помощью модуля scikit-image, может быть, даже более просто так:
import numpy as np
from skimage import color, io
# Open image and make Numpy arrays 'rgb' and 'Lab'
rgb = io.imread('image.png')
Lab = color.rgb2lab(rgb)
не уверен на 100% в масштабировании, но я подозреваю, что канал L
является плавающим в диапазоне 0..100, и что a
и b
также являются плавающими в диапазоне -128 .. + 128, хотя я могубыть неправым!
С моим изображением цветового круга выше я получил следующие минимумы / максимумы для каждого канала:
Lab[:,:,0].min() # L min
32.29567256501352
Lab[:,:,0].max() # L max
97.13950703971322
Lab[:,:,1].min() # a min
-86.18302974439501
Lab[:,:,1].max() # a max
98.23305386311316
Lab[:,:,2].min() # b min
-107.85730020669489
Lab[:,:,2].max() # b max
94.47812227647823