Source code for cvd_emulator

[docs]def cvd_emulator(image = "DEMO", cvd = "desaturate", severity = 1.0, output = None, dropalpha = False): """cvd_emulator(image = "DEMO", cvd = "desaturate", \ severity = 1.0, output = None, dropalpha = False) Simulate color deficiencies on png/jpg/jpeg figures. Takes an existing pixel image and simulates different color vision deficiencies. The function displays a matplotlib figure if output is set to None. If the parameter output is set, the converted figure will be stored. If only one color vision deficiency is defined (e.g., ``cvd = "desaturate"``) a figure of the same type and size as the input figure will be saved to the disc. If multiple cvd's are specified a multi-panel plot will be stored under `output`. Parameters ---------- image : str name of the figure which should be converted (png/jpg/jpeg). If ``image = "DEMO"`` the package demo figure will be used. cvd : str, list the color vision deficiency. Allowed types are deutanope, protanope, tritanope, and desaturated. Input is either a single string or a list of strings which define the cvd's which should be simulated. severity : float how severe the color vision deficiency is (``[0.,1.]``). Also used as the amount of desaturation if ``cvd = "desaturate"``. output : string optional. It None an interactive plotting window will be opened. If a string is given the figure will be written to ``output``. dropalpha : bool whether or not to drop the alpha channel. Only useful for figures having an alpha channel (png w/ alpha). Examples -------- >>> from colorspace.cvd_emulator import cvd_emulator >>> cvd_emulator("DEMO", "deutan", 0.5) >>> cvd_emulator("DEMO", "desaturate", 1.0, "output.png") >>> cvd_emulator("DEMO", ["original", "deutan", "protan"], 0.5, dropalpha = True) .. note:: Requires the modules ``matplotlib`` and ``imageio``. """ import os import inspect # Conver to ..? allowed = ["protan", "tritan", "deutan", "desaturate", "original"] tmp = [] if isinstance(cvd, str): cvd = [cvd] for c in cvd: if c in allowed: tmp.append(c) else: raise ValueError("cvd type {:s} not allowed. ".format(cvd) + \ "Use {:s}".format(", ".join(allowed))) if len(cvd) == 0: raise ValueError("no valid \"cvd\" methods") cvd = tmp; del tmp # If image = "DEMO": use package demo image. if image == "DEMO": resource_package = os.path.dirname(__file__) image = os.path.join(resource_package, "data", "colorful.png") # Check if file exists if not os.path.isfile(image): raise Exception("method {:s}".format(inspect.stack()[0][3]) + \ "cannot find image file {:s}".format(image)) # Wrong input for output if not output is None and not isinstance(output, str): raise ValueError("output has to be None or a string (file name)") # Import imageio try: import imageio except Exception as e: raise Exception("the {:s} requires the ".format(inspect.stack()[0][3]) + \ "python module imageio to be installed: {:s}".format(str(e))) # Read image data try: img = imageio.imread(image) except Exception as e: raise Exception(str(e)) # Extracting colors (scale from [0,255] to [0.,1.]) data = {} if img.shape[2] == 3: [data["R"], data["G"], data["B"]] = \ [img[:,:,i].flatten() / 255. for i in [0,1,2]] elif img.shape[2] == 4: [data["R"], data["G"], data["B"], data["alpha"]] = \ [img[:,:,i].flatten() / 255. for i in [0,1,2,3]] # Create sRGB with or without from .colorlib import sRGB if not "alpha" in data.keys(): rgba = sRGB(data["R"], data["G"], data["B"]) else: rgba = sRGB(data["R"], data["G"], data["B"], data["alpha"]) # Drop alpha if dropalpha: rgba.dropalpha() # Apply color deficiency from . import CVD import matplotlib.pyplot as plt from numpy import ceil if len(cvd) <= 3: [nrow, ncol] = [1, len(cvd)] else: [nrow, ncol] = [ceil(len(cvd)/2.), 2] # Start plotting for c in range(0, len(cvd)): # Start plotting if len(cvd) == 1: fig = plt.figure() else: fig = plt.subplot(nrow, ncol, c + 1) if cvd[c] == "original": cols = rgba else: fun = getattr(CVD, cvd[c]) cols = fun(rgba, severity) # Convert RGB [0.-1.] to [0,255], uint8 def fun(x, shape): from numpy import fmin, fmax x = fmax(0, fmin(255, x*255)) return x.reshape(shape) # Shape of the new figure if cols.hasalpha(): shape = [img.shape[0],img.shape[1],4] else: shape = [img.shape[0],img.shape[1],3] # Create new image matrix and fill in the data from numpy import ndarray, uint8 imnew = ndarray(shape, dtype = uint8) imnew[:,:,0] = fun(cols.get("R"), shape[0:2]) imnew[:,:,1] = fun(cols.get("G"), shape[0:2]) imnew[:,:,2] = fun(cols.get("B"), shape[0:2]) if cols.hasalpha(): imnew[:,:,3] = fun(cols.get("alpha"), shape[0:2]) import matplotlib.pyplot as plt plt.imshow(imnew) plt.axis("off") # Adjusting outer margins plt.subplots_adjust(left = 0., right = 1., top = 1., bottom = 0.1) # Show or save image. if output is None: else: # Write a simple figure: if len(cvd) == 1: imageio.imwrite(output, imnew) # Save matplotlib panel plot else: plt.savefig(output)