Using PIL and NumPy to convert an image to Lab array, modify the values and then convert back Using PIL and NumPy to convert an image to Lab array, modify the values and then convert back python python

Using PIL and NumPy to convert an image to Lab array, modify the values and then convert back


Without having tried it, scaling errors are common in converting colors:
RGB is bytes 0 .. 255, e.g. yellow [255,255,0],whereas rgb2xyz() etc. work on triples of floats, yellow [1.,1.,0].
(color.py has no range checks: lab2rgb( rgb2lab([255,255,0]) ) is junk.)

In IPython, %run main.py, then print corners of srcArray and end ?

Added 13July: for the record / for google, here are NumPy idioms to pack, unpack and convert RGB image arrays:

    # 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.shaper,g,b = img.transpose( 2,0,1 )  # 3 10 5print "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 againprint "rgb.shape:", rgb.shapeassert (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()


As Denis pointed out, there are no range checks in lab2rgb or rgb2lab, and rgb2lab appears to expect values in the range [0,1].

>>> a = numpy.array([[1,2,3],[4,5,6],[7,8,9]])>>> aarray([[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>>> barray([[ 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]])

In color.py, the xyz2lab and lab2xyz functions are doing some math that I can't deduce at a glance (I'm not that familiar with numpy or image transforms).

Edit (this code fixes the problem):

PIL gives you numbers [0,255], try scaling those down to [0,1] before passing to the rgb2lab function and back up when coming out. e.g.:

#from __future__ import division # (if required)[...]# Create array of image using numpysrcArray = numpy.asarray(src)/255# Convert array from RGB into LabsrcArray = color.rgb2lab(srcArray)# Convert array back into Labend = color.lab2rgb(srcArray)*255end = end.astype(numpy.uint8)