Использование PIL и NumPy для преобразования изображения в массив Lab, изменения значений и последующего обратного преобразования

Я пытаюсь преобразовать изображение PIL в массив с помощью NumPy. Затем я хочу преобразовать этот массив в значения Lab, изменить значения, а затем преобразовать массив обратно в изображение и сохранить изображение. У меня такой код:

import Image, color, numpy

# Open the image file
src = Image.open("face-him.jpg")

# Attempt to ensure image is RGB
src = src.convert(mode="RGB")

# Create array of image using numpy
srcArray = numpy.asarray(src)

# Convert array from RGB into Lab
srcArray = color.rgb2lab(srcArray)

# Modify array here

# Convert array back into Lab
end = color.lab2rgb(srcArray)

# Create image from array
final = Image.fromarray(end, "RGB")

# Save
final.save("out.jpg")

Этот код зависит от PIL, NumPy и color. цвет можно найти в стволе SciPy здесь . Я загрузил файл color.py вместе с некоторыми файлами colordata .txt . Я изменил color.py так, чтобы он мог работать независимо от источника SciPy, и все, кажется, работает нормально - значения в массиве меняются, когда я запускаю преобразования.

Моя проблема в том, что когда я запускаю приведенный выше код, который просто преобразует изображение в Lab, затем обратно в RGB и сохраняет его, я получаю следующее изображение:

alt text

Что не так? Это факт, что я использую функции из color.py?

Для справки:
Исходное изображение -
face-him.jpg
Все исходные файлы, необходимые для тестирования - colour-test.zip


person betamax    schedule 12.07.2010    source источник
comment
Вы используете старую версию Scipy? Импорт цвета не работает; все функции, которые scipy_base (не существует для меня) пытается использовать, являются стандартными функциями Numpy (asarray, swapaxes и т. д.). Изменены первые две строки color.py на import numpy as sb и import numpy as scipy.   -  person Nick T    schedule 12.07.2010


Ответы (2)


Если не попробовать, то при преобразовании цветов часто встречаются ошибки масштабирования:
RGB - это байты 0..255, например желтый [255,255,0], тогда как rgb2xyz() и т. д. работают с тройками чисел с плавающей запятой, желтый [1., 1., 0].
(color.py не имеет проверок диапазона: lab2rgb( rgb2lab([255,255,0]) ) является мусором.)

В IPython %run main.py затем вывести углы srcArray и end?

Добавлено 13 июля: для записи / для Google вот идиомы NumPy для упаковки, распаковки и преобразования массивов изображений RGB:

    # unpack image array, 10 x 5 x 3 -> r g b --
img = np.arange( 10*5*3 ).reshape(( 10,5,3 ))
print "img.shape:", img.shape
r,g,b = img.transpose( 2,0,1 )  # 3 10 5
print "r.shape:", r.shape

    # pack 10 x 5 r g b -> 10 x 5 x 3 again --
rgb = np.array(( r, g, b )).transpose( 1,2,0 )  # 10 5 3 again
print "rgb.shape:", rgb.shape
assert (rgb == img).all()

    # rgb 0 .. 255 <-> float 0 .. 1 --
imgfloat = img.astype(np.float32) / 255.
img8 = (imgfloat * 255).round().astype(np.uint8)  
assert (img == img8).all()
person denis    schedule 12.07.2010
comment
Спасибо, этот комментарий был более полезным для моей проблемы. Однако ответ Ника Т помог мне немного лучше понять, как работает numpy. - person betamax; 15.07.2010

Как указал Денис, в lab2rgb или rgb2lab нет проверок диапазона, а rgb2lab, похоже, ожидает значений в диапазоне [0,1].

>>> a = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
>>> a
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
>>> color.lab2rgb(color.rgb2lab(a))
array([[ -1.74361805e-01,   1.39592186e-03,   1.24595808e-01],
       [  1.18478213e+00,   1.15700655e+00,   1.13767806e+00],
       [  2.62956273e+00,   2.38687422e+00,   2.21535897e+00]])
>>> from __future__ import division
>>> b = a/10
>>> b
array([[ 0.1,  0.2,  0.3],
       [ 0.4,  0.5,  0.6],
       [ 0.7,  0.8,  0.9]])
>>> color.lab2rgb(color.rgb2lab(a))
array([[ 0.1,  0.2,  0.3],
       [ 0.4,  0.5,  0.6],
       [ 0.7,  0.8,  0.9]])

В color.py функции xyz2lab и lab2xyz выполняют некоторую математику, которую я не могу понять с первого взгляда (я не так хорошо знаком с numpy или преобразованием изображений).

Изменить (этот код устраняет проблему):

PIL дает вам числа [0,255], попробуйте уменьшить их до [0,1] перед переходом к функции rgb2lab и увеличьте при выходе. например.:

#from __future__ import division # (if required)
[...]
# Create array of image using numpy
srcArray = numpy.asarray(src)/255

# Convert array from RGB into Lab
srcArray = color.rgb2lab(srcArray)

# Convert array back into Lab
end = color.lab2rgb(srcArray)*255
end = end.astype(numpy.uint8)
person Nick T    schedule 12.07.2010
comment
В строке c = color.lab2rgb(a) неужели вы не сделали c = color.lab2rgb(b)? Потому что в противном случае он пытается преобразовать исходную матрицу 1,2,3 из Lab в RGB .. - person betamax; 12.07.2010
comment
Снова отредактировано, проблема решена для меня (py 2.6) Не уверен, работает ли будущее подразделение на более старых версиях, но должна быть какая-то функция numpy, которая это делает. - person Nick T; 12.07.2010