Source code for ImageUtils

#*******************************************************************#
#                                                                   #
#-------------------------------------------------------------------#
#                                                                   #
#*******************************************************************#
import copy
import numpy as np
from PIL import Image,ImageDraw,ImageFont
from mahotas import labeled

def _getImAsArray(sigma,types,field,colormap,scale=1,nx=None,ny=None,transparant=False,gv=None,bc=None):
    if bc is None:
        bc = (0,0,0)
    (nx,ny) = sigma.shape 
    sigma = np.transpose((sigma.astype(np.float)))
    types = np.transpose((types.astype(np.float)))
    field = np.transpose((field.astype(np.float)))
    if np.sum(sigma) == 0:
        im = Image.fromarray(255*np.uint8(np.ones_like(sigma)))
        im = im.resize((int(scale*nx),int(scale*ny)))
        return np.asarray(im),sigma,np.zeros_like(sigma)
    if gv is None:
        gv = [100,255]
    if ((np.max(field)-np.min(field)) > 0):
        field = (((field-np.max(field))/(np.min(field)-np.max(field)))*(gv[1]-gv[0]))+gv[0]
    fim = Image.fromarray(field)
    fim = fim.resize((int(scale*nx),int(scale*ny)))
    fim.convert("RGB")
    im = Image.fromarray(sigma)
    im = im.resize((int(scale*nx),int(scale*ny)))
    sigma = np.asarray(im)
    tim = Image.fromarray(np.uint8(types))
    tim = tim.resize((int(scale*nx),int(scale*ny)))            
    types = np.asarray(tim)
    sigMin = 0
    bim = None
    while sigMin < np.max(sigma):
        imtemp = copy.deepcopy(np.asarray(im))
        imtemp[np.where(imtemp < sigMin)] = 0
        imtemp[np.where(imtemp > sigMin+254)] = 0
        if bim is None:
            bim = labeled.borders(imtemp)
        else:
            bim += labeled.borders(imtemp)
        sigMin += 254
    if np.sum(field) == 0:
        imnew = colormap[0]*np.ones((scale*ny,scale*nx,3))
    else:
        imnew = np.dstack((np.asarray(fim),np.asarray(fim),np.asarray(fim)))
    if not transparant:
        for tp in np.unique(types):
            if tp == 0:
                continue
            imnew[types==tp] = colormap[tp]
    #~ imnew[types==0] = colormap[0]
    # set border black
    imnew[bim] = bc
    return imnew,sigma,np.asarray(tim)

[docs]def makeImage(id,inpath,t,colormap,timestamp=False,label=False,scale=1,bc=None,fontsize=6,border=True,gzipped=True,fieldname=None): """ Draw morphology for one timestep :param id: simulation identifier :param inpath: path containing data files :param t: time step :param outpath: path to save images to :param colormap: dictionary with cell types as keys and colors (r,g,b) as values :param timestamp: add time stamp to the image :type timestamp: bool :param label: add id as label to the image :type label: bool :param scale: scaling of the image :type scale: number :param bc: color of cell boundaries (r,g,b) :param fontsize: size of the fonts used for label and time stamp; font size will be multiplied by scale. :type fontsize: int :param border: cut of border pixels :type border: bool :param gzipped: data is gzipped :type gzipped: bool :param fieldname: name of chemical field :type fieldname: str :return: image object .. seealso:: :func:`~OpenSimUtils.ImageUtils.drawCells`, :func:`~OpenSimUtils.ImageUtils.addTimeStamp`, :func:`~OpenSimUtils.ImageUtils.addLabel` """ sigma = readSigma(id,t,inpath,gzipped,border) types = readTau(id,t,inpath,gzipped,border) if fieldname is not None: field = readChemField(id,t,inpath,fieldname,gzipped,border) else: field = np.zeros_like(sigma) (nx,ny) = sigma.shape (imnew,sigma,types) = _getImAsArray(sigma,types,field,colormap,scale=scale,bc=bc) im = Image.fromarray(np.uint8(imnew)) im = im.rotate(90) if timestamp: fs = int(fontsize*(nx/200.0)*scale) addTimeStamp(im,str(t),fs,fc=bc) if label: fs = int(1.25*fontsize*(nx/200.0)*scale) addLabel(im,str(id),fs,fc=bc) return im
[docs]def drawRelDirField(field,sigma,scale=1): """ Draw gray-scale image of a field of the relative director :param field: numpy array with field :param scale: scaling factor :param gv: minimum and maximum color value :param raw: use raw values of field, otherwise values are mapped on the range of gv :return: image object """ (nx,ny) = field.shape gv = [0,220] field = (((field-np.max(field))/(np.min(field)-np.max(field)))*(gv[1]-gv[0]))+gv[0] field[np.where(sigma==0)] = 255 fim = Image.fromarray(field) fim = fim.resize((int(scale*nx),int(scale*ny))) fim.convert("RGB") im = Image.fromarray(np.uint8(np.dstack((np.asarray(fim),np.asarray(fim),np.asarray(fim))))) im = im.transpose(Image.FLIP_TOP_BOTTOM) #~ im = im.rotate(90) return im
[docs]def stackImages(images,geometry,filename,label=False,title=None,fontsize=20,border=False,scale=1,fontpath="/usr/share/fonts/msttcore/"): """ Stack a set of images together in one image. :param images: dictionary with labels as keys and image filenames as values :param geometry: number of rows and columns (x,y) :param filename: target of the stacked image :param label: add labels to the subimages :param title: overall title for image :param fontsize: fontsize for labels and title :param border: add border to subimages :type border: bool :param scale: scaling factor of the created picture """ fontsize=int(fontsize*scale) font = ImageFont.truetype(fontpath+"/times.ttf", fontsize) labels = images.keys() nx = 0 ny = 0 for im in images.values(): sz = Image.open(im).size if sz[0] > nx: nx = sz[0] ny = sz[1] imsize = (scale*nx,scale*ny) if label: im = Image.new('RGB',(10,10)) draw = ImageDraw.Draw(im) lsize = draw.textsize(str(labels[0]),font=font) imsize = (int(scale*imsize[0]),int(scale*imsize[1])+lsize[1]) #~ imsize[1] += lsize[1] #---- Create new image ----# offsetX = 5 offsetY = 0 imw = int(np.ceil(imsize[0]*geometry[0]+2*offsetX)) imh = int(np.ceil(imsize[1]*geometry[1]+offsetY)) if title is not None: im = Image.new('RGB',(10,10)) draw = ImageDraw.Draw(im) tsize = draw.textsize(str(title),font=font) im = Image.new('RGBA',(imw,imh+tsize[1]),(255,255,255)) offsetY = tsize[1] else: im = Image.new('RGBA',(imw,imh),(255,255,255)) offsetY = 0 draw = ImageDraw.Draw(im) #----- Put plots on canvas ----# labels.sort() for i,l in enumerate(labels): x0 = int(i%geometry[0]*imsize[0]+offsetX) y0 = int((i/geometry[0])*imsize[1]+offsetY) newim = Image.open(images[l]) im.paste(newim.resize((int(nx*scale),int(ny*scale))),(x0,y0)) if border: draw.rectangle([(x0,y0),(x0+int(nx*scale),y0+int(ny*scale))],outline=(0,0,0)) if label: for i,l in enumerate(labels): tsize = draw.textsize(str(l),font=font) x0 = (i%geometry[0])*imsize[0]+0.5*imsize[0]-0.5*tsize[0]+offsetX y0 = (i/geometry[0])*imsize[1]+1*imsize[1]-tsize[1]+offsetY draw.text((x0,y0),str(l),fill=(0,0,0),font=font) if not (title is None): tsize = draw.textsize(str(title),font=font) draw.text((im.size[0]/2.0-0.5*tsize[0]+offsetX,0),str(title),fill=(0,0,0),font=font) #----- Save image -----# #~ if scale is not 1: #~ im = im.resize((int(scale*im.size[0]),int(scale*im.size[1]))) im.save(filename)
[docs]def morphImages(images,filename,xlabel=None,ylabel=None,xtics=None,ytics=None,fontsize=20,scale=1,border=False,title=None,bcolor=(255,255,255),fcolor=(0,0,0),fontpath='/usr/share/fonts/msttcore/',delta=0): """ Stack a set of images together in one morphospace. :param images: 2D array with image filenames :param filename: target of the stacked image :param xlabel: label to be plotted on x-axis :param ylabel: label to be plotted on y-axis :param xtics: items on x-axis :param ytics: items on y-axis :param fontsize: fontsize for labels and title :param scale: scaling factor of the created picture :param border: add border to subimages :param title: overall title for image """ font = ImageFont.truetype(fontpath+"/times.ttf", fontsize) tfont = ImageFont.truetype(fontpath+"/times.ttf", int(1.1*fontsize)) #~ subimsize = Image.open(images[0][0]).size orgsize = Image.open(images[0][0]).size subimsize = (int(scale*orgsize[0]+delta),int(scale*orgsize[1]+delta)) imsize = [subimsize[0]*len(images[0])-delta,subimsize[1]*len(images)-delta] oX = 0 oY = 0 toX = 0 toY = 0 if xlabel is not None: im = Image.new('RGB',(10,10)) draw = ImageDraw.Draw(im) lsize = draw.textsize(str(xlabel),font=font) imsize[1] = imsize[1]+lsize[1] oY += lsize[1] toY += lsize[1] if ylabel is not None: im = Image.new('RGB',(10,10)) draw = ImageDraw.Draw(im) lsize = draw.textsize(str(ylabel),font=font) imsize[0] += lsize[1] oX += lsize[1] toX += lsize[1] if xtics is not None: im = Image.new('RGB',(10,10)) draw = ImageDraw.Draw(im) lsize = draw.textsize(str(xtics[0]),font=font) imsize[1] += lsize[1] oY += lsize[1] if ytics is not None: im = Image.new('RGB',(10,10)) draw = ImageDraw.Draw(im) lsize = draw.textsize(str(ytics[0]),font=font) imsize[0] += lsize[1] oX += lsize[1] loY = 0 if title is not None: im = Image.new('RGB',(10,10)) draw = ImageDraw.Draw(im) lsize = draw.textsize(str(title),tfont) offset = lsize[1]+20*scale imsize[1] += offset oY += offset if xlabel is not None: loY += offset toY += offset #---- Create new image ----# im = Image.new('RGBA',imsize,bcolor) draw = ImageDraw.Draw(im) #----- Put plots on canvas ----# for i in range(len(images)): for j in range(len(images[0])): #~ print i,j,len(images),len(images[0]) newim = Image.open(images[i][j]) x0 = j*subimsize[0]+oX y0 = i*subimsize[0]+oY im.paste(newim.resize((int(scale*orgsize[0]),int(scale*orgsize[1]))),(x0,y0)) #~ im.paste(newim.resize(subimsize),(x0,y0)) if border: draw.rectangle([(x0,y0),(x0+newim.size[0],y0+newim.size[1])],outline=(0,0,0)) #----- Draw axis and tics -----# ticsfont = ImageFont.truetype(fontpath+"/times.ttf", int(.75*fontsize)) if xtics is not None: for i in range(len(xtics)): tsize = draw.textsize(str(xtics[i]),font=ticsfont) x0 = (i+0.5)*subimsize[0]+oX-int(tsize[0]/2.0) y0 = toY draw.text((x0,y0),str(xtics[i]),fill=fcolor,font=ticsfont) if ytics is not None: for i in range(len(ytics)): x0 = toX y0 = int((i+.5)*subimsize[1]+oY) #~ draw.text((x0,y0),str(ytics[i]),fill=(0,0,0),font=ticsfont) tsize = draw.textsize(str(ytics[i]),font=ticsfont) tim = Image.new('RGBA',(tsize[0],tsize[1]),bcolor) tdraw = ImageDraw.Draw(tim) tdraw.text((0,0),str(ytics[i]),fill=fcolor,font=ticsfont) tim = tim.rotate(90) y0 -= int(tsize[0]/2.0) im.paste(tim,(x0,y0)) if xlabel is not None: tsize = draw.textsize(str(xlabel),font=font) draw.text((im.size[0]/2.0-0.5*tsize[0],loY),str(xlabel),fill=fcolor,font=font) if ylabel is not None: tsize = draw.textsize(str(ylabel),font=font) tim = Image.new('RGBA',(tsize[0],tsize[1]),bcolor) tdraw = ImageDraw.Draw(tim) tdraw.text((0,0),str(ylabel),fill=fcolor,font=font) tim = tim.rotate(90) im.paste(tim,(0,int(im.size[1]/2.0-tsize[0]))) if title is not None: tsize = draw.textsize(str(title),font=tfont) draw.text((im.size[0]/2.0-0.5*tsize[0],0),str(title),fill=fcolor,font=tfont) #----- Save image -----# im.save(filename)