[PYTHON] Traitement d'image avec PIL

In this project, we'll load and process the image with PIL.


PIL This library provides extensive file format support, an efficient internal representation, and fairly powerful image processing capabilities. The core image library is designed for fast access to data stored in a few basic pixel formats. It should provide a solid foundation for a general image processing tool.

Image Processing The library contains basic image processing functionality, including point operations, filtering with a set of built-in convolution kernels, and colour space conversions.

The library also supports image resizing, rotation and arbitrary affine transforms.

There’s a histogram method allowing you to pull some statistics out of an image. This can be used for automatic contrast enhancement, and for global statistical analysis.


Import libraries

# Used to change filepaths
from pathlib import Path

# We set up matplotlib, pandas, and the display function
%matplotlib inline
import matplotlib.pyplot as plt
from IPython.display import display
import pandas as pd

# import numpy to use in this cell
import numpy as np

# import Image from PIL so we can use it later
from PIL import Image

# generate test_data
test_data = np.random.beta(1, 1, size=(100, 100, 3))

# display the test_data
plt.imshow(test_data)
Screen Shot 2020-03-26 at 12.32.16 am.png

Opening images with PIL


# open the image
img = Image.open('datasets/bee_1.jpg')

# Get the image size
img_size = img.size

print("The image size is: {}".format(img_size))

# Just having the image as the last line in the cell will display it in the notebook
img
Screen Shot 2020-03-26 at 12.40.42 am.png

Image manipulation with PIL Pillow has a number of common image manipulation tasks built into the library. For example, one may want to resize an image so that the file size is smaller. Or, perhaps, convert an image to black-and-white instead of color. Operations that Pillow provides include:

# Crop the image to 25, 25, 75, 75
img_cropped = img.crop([25, 25, 75, 75])
display(img_cropped)

# rotate the image by 45 degrees
img_rotated = img.rotate(45, expand = 25)
display(img_rotated)

# flip the image left to right
img_flipped = img.transpose(Image.FLIP_LEFT_RIGHT)
display(img_flipped)

Screen Shot 2020-03-26 at 12.42.34 am.png

Images as arrays of data Most image formats have three color "channels": red, green, and blue (some images also have a fourth channel called "alpha" that controls transparency). For each pixel in an image, there is a value for every channel.

The way this is represented as data is as a three-dimensional matrix. The width of the matrix is the width of the image, the height of the matrix is the height of the image, and the depth of the matrix is the number of channels. So, as we saw, the height and width of our image are both 100 pixels. This means that the underlying data is a matrix with the dimensions 100x100x3.

# Turn our image object into a NumPy array
img_data = np.array(img)

# get the shape of the resulting array
img_data_shape = img_data.shape

print("Our NumPy array has the shape: {}".format(img_data_shape))

# plot the data with `imshow` 
plt.imshow(img_data)
plt.show()

# plot the red channel
plt.imshow(img_data[:, :, 0], cmap=plt.cm.Reds_r)
plt.show()

# plot the green channel
plt.imshow(img_data[:, 0, :], cmap=plt.cm.Greens_r)
plt.show()

# plot the blue channel
plt.imshow(img_data[0, :, :], cmap=plt.cm.Blues_r)
plt.show()
Screen Shot 2020-03-26 at 2.55.46 pm.png Screen Shot 2020-03-26 at 2.56.11 pm.png

Explore the color channels Color channels can help provide more information about an image. A picture of the ocean will be more blue, whereas a picture of a field will be more green. This kind of information can be useful when building models or examining the differences between images.

We'll look at the kernel density estimate for each of the color channels on the same plot so that we can understand how they differ.

When we make this plot, we'll see that a shape that appears further to the right means more of that color, whereas further to the left means less of that color.

def plot_kde(channel, color):
    """ Plots a kernel density estimate for the given data.
        
        `channel` must be a 2d array
        `color` must be a color string, e.g. 'r', 'g', or 'b'
    """
    data = channel.flatten()
    return pd.Series(data).plot.density(c=color)

# create the list of channels
channels = ['r','g','b']
    
def plot_rgb(image_data):
    # use enumerate to loop over colors and indexes
    for ix, color in enumerate(channels):
        plot_kde(img_data[:, :, ix], color)

    plt.show()
    
plot_rgb(img_data)
Screen Shot 2020-03-26 at 2.59.29 pm.png

Honey bees and bumble bees (i) Now we'll look at two different images and some of the differences between them. The first image is of a honey bee, and the second image is of a bumble bee.

First, let's look at the honey bee.


# load bee_12.jpg as honey
honey = Image.open('datasets/bee_12.jpg')

# display the honey bee image
display(honey)

# NumPy array of the honey bee image data
honey_data = np.array(honey)

# plot the rgb densities for the honey bee image
plot_rgb(honey_data)
Screen Shot 2020-03-26 at 3.06.27 pm.png

Honey bees and bumble bees (ii) Now let's look at the bumble bee.

When one compares these images, it is clear how different the colors are. The honey bee image above, with a blue flower, has a strong peak on the right-hand side of the blue channel. The bumble bee image, which has a lot of yellow for the bee and the background, has almost perfect overlap between the red and green channels (which together make yellow).


# load bee_3.jpg as bumble
bumble = Image.open('datasets/bee_3.jpg')

# display the bumble bee image
display(bumble)

# NumPy array of the bumble bee image data
bumble_data = np.array(bumble)

# plot the rgb densities for the bumble bee image
plot_rgb(bumble_data)
Screen Shot 2020-03-26 at 3.15.58 pm.png

Simplify, simplify, simplify While sometimes color information is useful, other times it can be distracting. In this examples where we are looking at bees, the bees themselves are very similar colors. On the other hand, the bees are often on top of different color flowers. We know that the colors of the flowers may be distracting from separating honey bees from bumble bees, so let's convert these images to black-and-white, or "grayscale."

# convert honey to grayscale
honey_bw = honey.convert("L")
display(honey_bw)

# convert the image to a NumPy array
honey_bw_arr = np.array(honey_bw)

# get the shape of the resulting array
honey_bw_arr_shape = honey_bw_arr.shape
print("Our NumPy array has the shape: {}".format(honey_bw_arr_shape))

# plot the array using matplotlib
plt.imshow(honey_bw_arr, cmap=plt.cm.gray)
plt.show()

# plot the kde of the new black and white array
plot_kde(honey_bw_arr, 'k')
Screen Shot 2020-03-26 at 3.25.38 pm.png

Save your work! Now, we'll make a couple changes to the Image object from Pillow and save that. We'll flip the image left-to-right, just as we did with the color version. Then, we'll change the NumPy version of the data by clipping it. Using the np.maximum function, we can take any number in the array smaller than 100 and replace it with 100. Because this reduces the range of values, it will increase the contrast of the image. We'll then convert that back to an Image and save the result.

# flip the image left-right with transpose
honey_bw_flip = honey_bw.transpose(Image.FLIP_LEFT_RIGHT)

# show the flipped image
display(honey_bw_flip)

# save the flipped image
honey_bw_flip.save("saved_images/bw_flipped.jpg ")

# create higher contrast by reducing range
honey_hc_arr = np.maximum(honey_bw_arr, 100)

# show the higher contrast version
plt.imshow(honey_hc_arr, cmap=plt.cm.gray)

# convert the NumPy array of high contrast to an Image
honey_bw_hc = Image.fromarray(honey_hc_arr)

# save the high contrast version
honey_bw_hc.save("saved_images/bw_hc.jpg ")
Screen Shot 2020-03-26 at 3.33.21 pm.png

Make a pipeline

We have all the tools in our toolbox to load images, transform them, and save the results. In this pipeline we will do the following:

image_paths = ['datasets/bee_1.jpg', 'datasets/bee_12.jpg', 'datasets/bee_2.jpg', 'datasets/bee_3.jpg']

def process_image(path):
    img = Image.open(path)

    # create paths to save files to
    bw_path = "saved_images/bw_{}.jpg ".format(path.stem)
    rcz_path = "saved_images/rcz_{}.jpg ".format(path.stem)

    print("Creating grayscale version of {} and saving to {}.".format(path, bw_path))
    bw = img.convert("L")
    bw.save(bw_path)

    print("Creating rotated, cropped, and zoomed version of {} and saving to {}.".format(path, rcz_path))
    rcz = img.rotate(45).crop([25,25,75,75]).resize((100,100))
    rcz.save(rcz_path)

# for loop over image paths
for img_path in image_paths:
    process_image(Path(img_path))
Screen Shot 2020-03-26 at 3.36.08 pm.png

Recommended Posts

Traitement d'image avec PIL
Traitement d'image avec PIL (Pillow)
Traitement d'image avec MyHDL
Traitement d'image avec Python
Traitement d'image avec Python (partie 2)
Traitement d'image avec Python (partie 1)
Traitement d'image avec Python (3)
[Python] Traitement d'image avec scicit-image
Principes de base du traitement d'image en temps réel avec opencv
Traitement d'image avec la binarisation Python 100 knocks # 3
100 traitement d'image par Python Knock # 2 Échelle de gris
[Traitement d'image] Postérisation
traitement d'image python
Traitement d'image 100 coups ①
Bases du traitement d'images binarisées par Python
Traitement d'image par Python 100 knock # 10 filtre médian
Créer une visionneuse de traitement d'image avec PySimpleGUI
Créez une image factice avec Python + PIL.
100 traitement d'image avec Python Knock # 8 Max Pooling
Traitement d'image avec Python et OpenCV [Tone Curve]
Traitement d'image par Python 100 knock # 12 motion filter
Dessin avec Matrix-Reinventor of Python Image Processing-
Traitez facilement des images en Python avec Pillow
Traitement d'image avec Python 100 knocks # 7 pooling moyen
Remplacez rapidement les couleurs de l'image par PIL / Pillow
Traitement d'image léger avec Python x OpenCV
Traitement d'image avec Lambda + OpenCV (création d'image grise)
Traitement d'image par Python 100 knock # 9 Filtre Gaussien
XavierNX accélère le traitement d'image OpenCV avec GPU (CUDA)
Installation PIL avec pip
Traitement des ensembles de données avec des pandas (1)
Traitement des ensembles de données avec des pandas (2)
Reconnaissance d'image avec keras
Traitement d'image à partir de zéro avec python (5) Transformation de Fourier
Premier traitement d'image Python
Lire le traitement d'image numérique
Traitement d'image à partir de zéro avec python (4) Extraction de contour
Traitement d'image avec la configuration de l'environnement Python pour Windows
Remarques sur le traitement d'images HDR et RAW avec Python
Téléchargement d'image avec l'API Flickr
100 coups de traitement du langage avec Python 2015
opencv-python Introduction au traitement d'image
Lire les coordonnées de l'image avec Python-matplotlib
Traitement parallèle avec des fonctions locales
"Traitement Apple" avec OpenCV3 + Python3
Édition d'image avec python OpenCV
Traitement du signal acoustique avec Python (2)
Traitement d'image numérique (filtrage spatial)
100 coups sur le traitement d'image !! (011-020) Début de partie
Traitement du signal acoustique avec Python
Téléchargement d'images et personnalisation avec django-ckeditor
Tri des fichiers image avec Python (2)
Tri des fichiers image avec Python (3)
100 coups sur le traitement d'image !! (001 --010) Soigneusement et soigneusement
Traitement parallèle avec Parallel de scikit-learn
Tweet avec image en Python
Tri des fichiers image avec Python
Traitement d'image par python (Pillow)