📚 The CoCalc Library - books, templates and other resources
License: OTHER
123```python4%matplotlib inline5```67# Images are numpy arrays89Images are represented in ``scikit-image`` using standard ``numpy`` arrays. This allows maximum inter-operability with other libraries in the scientific Python ecosystem, such as ``matplotlib`` and ``scipy``.1011Let's see how to build a grayscale image as a 2D array:12131415```python16import numpy as np17from matplotlib import pyplot as plt1819random_image = np.random.random([500, 500])2021plt.imshow(random_image, cmap='gray', interpolation='nearest');22```232425262728The same holds for "real-world" images:29303132```python33from skimage import data3435coins = data.coins()3637print(type(coins), coins.dtype, coins.shape)38plt.imshow(coins, cmap='gray', interpolation='nearest');39```4041```output42<class 'numpy.ndarray'> uint8 (303, 384)43```444546474849A color image is a 3D array, where the last dimension has size 3 and represents the red, green, and blue channels:50515253```python54cat = data.chelsea()55print("Shape:", cat.shape)56print("Values min/max:", cat.min(), cat.max())5758plt.imshow(cat, interpolation='nearest');59```6061```output62Shape: (300, 451, 3)63Values min/max: 0 23164```656667686970These are *just numpy arrays*. Making a red square is easy using just array slicing and manipulation:71727374```python75cat[10:110, 10:110, :] = [255, 0, 0] # [red, green, blue]76plt.imshow(cat);77```787980818283Images can also include transparent regions by adding a 4th dimension, called an *alpha layer*.8485## Data types and image values8687In literature, one finds different conventions for representing image values:8889```900 - 255 where 0 is black, 255 is white910 - 1 where 0 is black, 1 is white92```939495``scikit-image`` supports both conventions--the choice is determined by the96data-type of the array.9798E.g., here, I generate two valid images:99100101102```python103linear0 = np.linspace(0, 1, 2500).reshape((50, 50))104linear1 = np.linspace(0, 255, 2500).reshape((50, 50)).astype(np.uint8)105106print("Linear0:", linear0.dtype, linear0.min(), linear0.max())107print("Linear1:", linear1.dtype, linear1.min(), linear1.max())108109fig, (ax0, ax1) = plt.subplots(1, 2)110ax0.imshow(linear0, cmap='gray')111ax1.imshow(linear1, cmap='gray');112```113114```output115Linear0: float64 0.0 1.0116Linear1: uint8 0 255117```118119120121122123The library is designed in such a way that any data-type is allowed as input,124as long as the range is correct (0-1 for floating point images, 0-255 for unsigned bytes,1250-65535 for unsigned 16-bit integers).126127This is achieved through the use of a few utility functions, such as ``img_as_float`` and ``img_as_ubyte``:128129130131```python132from skimage import img_as_float, img_as_ubyte133134image = data.chelsea()135136image_float = img_as_float(image)137image_ubyte = img_as_ubyte(image)138139print("type, min, max:", image_float.dtype, image_float.min(), image_float.max())140print("type, min, max:", image_ubyte.dtype, image_ubyte.min(), image_ubyte.max())141142print("231/255 =", 231/255.)143```144145```output146type, min, max: float64 0.0 0.905882352941147type, min, max: uint8 0 231148231/255 = 0.9058823529411765149```150151Your code would then typically look like this:152153154155```python156def my_function(any_image):157float_image = img_as_float(any_image)158# Proceed, knowing image is in [0, 1]159```160161We recommend using the floating point representation, given that162``scikit-image`` mostly uses that format internally.163164## Displaying images using matplotlib165166Before we get started, a quick note about plotting images---specifically, plotting gray-scale images with Matplotlib. First, let's grab an example image from `scikit-image`.167168169170```python171from skimage import data172173image = data.camera()174```175176Also, we'll want to make sure we have numpy and matplotlib imported.177178179180```python181import matplotlib.pyplot as plt182import numpy as np183```184185If we plot a gray-scale image using the old default colormap "jet"186(it's been replaced by Viridis in Matplotlib >= 1.5), and a gray-scale187colormap, "gray", you can easily see the difference:188189190191```python192fig, (ax_jet, ax_gray) = plt.subplots(ncols=2, figsize=(10, 5))193194ax_jet.imshow(image, cmap='jet')195ax_gray.imshow(image, cmap='gray');196```197198199200201202We can get a better idea of the ill effects by zooming into the man's face.203204205206```python207face = image[80:160, 200:280]208fig, (ax_jet, ax_gray) = plt.subplots(ncols=2)209ax_jet.imshow(face, cmap='jet')210ax_gray.imshow(face, cmap='gray');211```212213214215216217Notice how the face looks distorted and splotchy with the "jet" colormap. Also, this colormap distorts the concepts of light and dark, and there are artificial boundaries created by the different color hues. Is that a beauty mark on the man's upper lip? No, it's just an artifact of this ridiculous colormap.218219Here's another example:220221222223```python224X, Y = np.ogrid[-5:5:0.1, -5:5:0.1]225R = np.exp(-(X**2 + Y**2) / 15)226227fig, (ax_jet, ax_gray) = plt.subplots(1, 2)228ax_jet.imshow(R, cmap='jet')229ax_gray.imshow(R, cmap='gray');230```231232233234235236Woah! See all those non-existing contours?237238You can set both the method of interpolation and colormap used239explicitly in the ``imshow`` command:240241242243```python244plt.imshow(R, cmap='gray', interpolation='nearest');245```246247248249250251Otherwise, you can add the following setting at the top of any script252to change the default colormap:253254255256```python257plt.rcParams['image.cmap'] = 'gray'258```259260Don't worry: color images are unaffected by this change.261262In addition, we'll set the interpolation to 'nearest neighborhood' so263that it's easier to distinguish individual pixels in your image (the264default is 'bicubic'--see the exploration below).265266267268```python269plt.rcParams['image.interpolation'] = 'nearest'270```271272For reference, let's look at the images above using Matplotlib's new 'viridis' and 'magma' colormaps (requires matplotlib >= 1.5).273274275276```python277fig, axes = plt.subplots(2, 2, figsize=(10, 10))278279axes[0, 0].imshow(R, cmap='jet')280axes[0, 1].imshow(R, cmap='viridis')281axes[1, 0].imshow(R, cmap='magma')282axes[1, 1].imshow(R, cmap='gray');283```284285286287288289### Interactive demo: interpolation and color maps290291If you are viewing this tutorial from inside a Jupyter notebook, the292following code will display an interactive widget for exploring293different colormaps and types of interpolation.294295296297```python298from IPython.html.widgets import interact, fixed299from matplotlib import cm as colormaps300import matplotlib.colors301import inspect302303@interact(image=fixed(face),304cmap=sorted([c for c in dir(colormaps)305if not c.endswith('_r') and306isinstance(getattr(colormaps, c),307matplotlib.colors.Colormap)],308key=lambda x: x.lower()),309reverse_cmap=False,310interpolation=['nearest', 'bilinear', 'bicubic',311'spline16', 'spline36', 'hanning', 'hamming',312'hermite', 'kaiser', 'quadric', 'catrom',313'gaussian', 'bessel', 'mitchell', 'sinc', 'lanczos'])314def imshow_params(image, cmap='jet', reverse_cmap=False, interpolation='bicubic'):315fig, axes = plt.subplots(1, 5, figsize=(15, 4))316317if reverse_cmap:318cmap = cmap + '_r'319320axes[0].imshow(image, cmap='gray', interpolation='nearest')321axes[0].set_title('Original')322323axes[1].imshow(image[:5, :5], cmap='gray', interpolation='nearest')324axes[1].set_title('Top 5x5 block')325axes[1].set_xlabel('No interpolation')326327axes[2].imshow(image, cmap=cmap, interpolation=interpolation)328axes[2].set_title('%s colormap' % cmap)329axes[2].set_xlabel('%s interpolation' % interpolation)330331axes[3].imshow(image[:5, :5], cmap=cmap, interpolation=interpolation)332axes[3].set_title('%s colormap' % cmap)333axes[3].set_xlabel('%s interpolation' % interpolation)334335axes[4].imshow(R, cmap=cmap, interpolation=interpolation)336axes[4].set_title('%s colormap' % cmap)337axes[4].set_xlabel('%s interpolation' % interpolation)338339for ax in axes:340ax.set_xticks([])341ax.set_yticks([])342```343344345346347348## Image I/O349350Mostly, we won't be using input images from the scikit-image example data sets. Those images are typically stored in JPEG or PNG format. Since scikit-image operates on NumPy arrays, *any* image reader library that provides arrays will do. Options include matplotlib, pillow, imageio, imread, etc.351352scikit-image conveniently wraps many of these in the `io` submodule, and will use whatever option is available:353354355356```python357from skimage import io358359image = io.imread('../../images/balloon.jpg')360361print(type(image))362plt.imshow(image);363```364365```output366<class 'numpy.ndarray'>367```368369370371372373We also have the ability to load multiple images, or multi-layer TIFF images:374375376377```python378ic = io.imread_collection('../../images/*.png')379380print(type(ic), '\n\n', ic)381```382383```output384<class 'skimage.io.collection.ImageCollection'>385386['../../images/chapel_floor.png', '../../images/clock_motion.png', '../../images/fingers.png', '../../images/snakes.png', '../../images/zebrafish-spinal-cord-color.png', '../../images/zebrafish-spinal-cord.png']387```388389390391```python392f, axes = plt.subplots(nrows=1, ncols=len(ic), figsize=(15, 10))393394for i, image in enumerate(ic):395axes[i].imshow(image, cmap='gray')396axes[i].axis('off')397```398399400401402403## Exercises404405### Draw the letter H406407Define a function that takes as input an RGB image and a pair of coordinates (row, column), and returns the image (optionally a copy) with green letter H overlaid at those coordinates. The coordinates should point to the top-left corner of the H.408409The arms and strut of the H should have a width of 3 pixels, and the H itself should have a height of 24 pixels and width of 20 pixels.410411Start with the following template:412413414415```python416def draw_H(image, coords, color=(0.8, 0.8, 0.8), in_place=True):417out = image.copy()418# your code goes here419return out420```421422Test your function like so:423424425426```python427cat = data.chelsea()428cat_H = draw_H(cat, (50, -50))429plt.imshow(cat_H);430```431432433434435436### RGB intensity plot437438Plot the intensity of each channel of the image along a given row.439Start with the following template:440441```442def plot_intensity(image, row):443# Fill in the three lines below444red_values = ...445green_values = ...446blue_values = ...447448plt.figure()449plt.plot(red_values, 'r')450plt.plot(green_values, 'g')451plt.plot(blue_values, 'b')452453pass454```455456457Test your function using:458459```460plot_intensity(cat, 50)461plot_intensity(cat, 100)462```463464465466