image processing made easy
Combines flexibility of PIL Python Imaging Library (Pillow) with the power of scikit-image embedded in an easy to use Image class
from Goulib.notebook import *
from Goulib.image import *
import PIL.Image as PILImage
lena_original=Image('../tests/data/lena.png') #Image can be init'ed from a path
from skimage import data
camera_original=Image(data.camera()) #or from an array
# Image has many "PIL compatible" methods, but they always return a result Image
# instead of working in-place :
size=(128,128)
lena=lena_original.resize(size)
lena_gray=lena.grayscale()
camera=camera_original.resize(size,PILImage.LANCZOS)
lena #images have a default HTML representation
from Goulib.table import Table # images can also be put in tables ! and they're responsive !
Table([[lena,lena_gray,camera],['lena','lena gray','camera']])
#Images have an attached immutable "mode" string:
h(str(lena)) #usually RGB(A) (float) for color images
h(str(lena_gray)) #gray images can be either F (float) or L (int)
h(modes) #supported modes are those from scipy + those from PIL (but in float instead of uint)
converters.edges() #a graph between modes
#conversions from/to any mode are implemented by traversing the graph automagically
lena_conv=dict((mode, lena.convert(mode)) for mode in modes)
lena_conv['1']*=255 # multiply 0/1 image so we can see it
Table([[lena_conv[m],m] for m in sorted(lena_conv)]).transpose()
note that displaying multi channel images assumes RGB(A) images, so for the above images we have:
lena_rgb=lena.split() #extract gray level images from each channel
images=[lena,lena_gray]+lena_rgb
Table([images],titles=['Lena','Gray']+[c for c in lena.mode])
camera=camera.convert('F') #not all conversions are automatic yet ...
Image(lena_rgb+[-camera]) # merges color planes and use camera as alpha channel
lena_lab=lena_conv['LAB'].split() #extract gray level images from each channel
images=[lena]+lena_lab
Table([images],titles=['Lena']+[c for c in lena_conv['LAB'].mode])
Image(lena_lab,'LAB').convert('RGB')
lena_conv['LAB'].convert('RGB')
lena_gray*'cyan' #gray colors can be multiplied by a color to make a colorized image
lena_gray.colorize('blue','yellow') #colorize between specified black and white colors
colors=['Cyan','Magenta','Yellow','blacK']
cmyk=lena.split('CMYK') # converts from RGB to CMYK under the hood
cmyk2=[im.colorize(col) for im,col in zip(cmyk,colors)]
Table([cmyk,cmyk2],titles=colors)
#rebuild color image from colorized CMYK planes
cmyk2[0]-(-cmyk2[1])-(-cmyk2[2])-(-cmyk2[3]) #what a strange syntax ...
optimal palette is computed automatically in Lab space from a k-means segmentation of a radom subset of pixels (see http://scikit-learn.org/stable/auto_examples/cluster/plot_color_quantization.html )
lenaP=lena.convert('P',colors=5) #image can be reduced to any number of colors
h(lenaP,lenaP.palette) # the optimal palette is computed automatically
#palette can also be explicitely specified
palette=Palette(['purple','peachpuff','indianred','brown','lightcoral'])
lenaP=lena.convert('P',colors=palette)
h(lenaP,lenaP.palette)
Table([[lena.dither(method,n) for method in dithering] for n in (2,3,4)], titles=dithering.values())