Information

Section: Edge detection
Goal: Understand that the quality of edge detection is highly related to the contrast of an image.
Time needed: 20 min
Prerequisites: Introduction about machine learning experiments, basics about image processing

Edge detection

The contrast analysis through grayscale values can be verified with the use of edge detection algorithms. Without going into details about the algorithm itself, it is a tool that detects the edge of the objects in a picture, and can be useful for object detection or recognition tasks.

Canny edge detection

The parameter sigma allows to control how detailed the detection of the edges should be. Try to change its value to see what happens.

We will use a model called canny with the function canny() of the skimage library.
This function only works on black and white pictures, so we first need to transform the image in a grayscale.

import matplotlib.pyplot as plt
import skimage.feature as sf
from skimage import io
from skimage.color import rgb2gray

image = rgb2gray(io.imread('./data/1.jpg'))
plt.imshow(image, cmap = 'gray')
plt.show()
canny = sf.canny(image, sigma = 3)
plt.imshow(canny)
_images/2-2-2-edge_6_0.png
<matplotlib.image.AxesImage at 0x1a7092000f0>
_images/2-2-2-edge_6_2.png
# beginner version

import matplotlib.pyplot as plt
import ipywidgets as widgets
from ipywidgets import interact

def plot_canny(sigma):
    image = rgb2gray(io.imread('./data/1.jpg'))
    plt.imshow(image, cmap = 'gray')
    plt.show()
    canny = sf.canny(image, sigma = sigma)
    plt.imshow(canny)

    
interact(plot_canny,
         sigma = widgets.FloatText(value = 3.0,
                                    description = 'sigma = ',
                                    disabled = False))
<function __main__.plot_canny(sigma)>

This function is connected with contrast: the detected edges are the result of a high change of gray value between two areas. A picture where the object is highly contrasted with the background will yield better results with the edge detection algorithm. to figure it out, compare in the following cell different pictures, by changing the name 1.jpg with different integers in the range [1, 20]. Change also the sigma value when it is needed to better gauge the edge detection result.

image = rgb2gray(io.imread('./data/5.jpg'))
fig, (ax1, ax2) = plt.subplots(1, 2, figsize = (8, 4))
ax1.imshow(image, cmap = 'gray')
ax2.hist(image.flatten(), bins = 256, range = (0, 1))
plt.show()
canny = sf.canny(image, sigma = 5)
plt.imshow(canny)
_images/2-2-2-edge_9_0.png
<matplotlib.image.AxesImage at 0x1a709898ac8>
_images/2-2-2-edge_9_2.png
# For beginner version: cell to hide

import matplotlib.pyplot as plt
import ipywidgets as widgets
from ipywidgets import interact

def plot_general(image_nb, sigma):
    image = rgb2gray(io.imread('./data/' + str(image_nb) + '.jpg'))
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize = (8, 4))
    ax1.imshow(image, cmap = 'gray')
    ax2.hist(image.flatten(), bins = 256, range = (0, 1))
    plt.show()
    canny = sf.canny(image, sigma = sigma)
    plt.imshow(canny)

    
interact(plot_general,
         image_nb = widgets.IntText(value = 1,
                                    description = 'Image:',
                                    disabled = False),
         sigma = widgets.FloatText(value = 3.0,
                                    description = 'sigma = ',
                                    disabled = False))
<function __main__.plot_general(image_nb, sigma)>

We notice that the pictures with a better edge detection work (where the animal is well detected) are also the ones with a better contrast.

HOG from canny picture

We see that we can get an idea on how to gauge the quality of the image itself. But to be sure that it will enhance our personal model, we need to apply our method (HOG descriptors) to the generated image.

from skimage.exposure import rescale_intensity
from skimage.feature import hog

image = rgb2gray(io.imread('./data/1.jpg'))

fig, (ax1, ax2, ax3, ax4) = plt.subplots(1, 4, figsize = (16, 4))

ax1.imshow(image, cmap = 'gray')
ax1.set_title('Image')

fd, hog_image = hog(image, orientations = 8, pixels_per_cell = (40, 40), visualize = True)
hog_image_rescaled = rescale_intensity(hog_image, in_range = (0, 10))
ax2.imshow(hog_image_rescaled)
ax2.set_title('HOG of image')

canny = sf.canny(image, sigma = 3)
ax3.imshow(canny)
ax3.set_title('Edge detection')

fd, hog_image = hog(canny.astype(int), orientations = 8, pixels_per_cell = (40, 40), visualize = True)
hog_image_rescaled = rescale_intensity(hog_image, in_range = (0, 10))
ax4.imshow(hog_image_rescaled)
ax4.set_title('HOG of edge detection')

plt.show()
_images/2-2-2-edge_14_0.png

From the previous graphs, we can see that the image of a cat is better recognizable from the HOG descriptors of the edge detected picture than from the original picture. We can now launch the classification task to see if it impacts the algorithm itself.

First, we build the model and predict from the original image, using the functions we defined previously. Then, we transform the images to their canny equivalent and use those HOG features for the prediction.

We can try different classifications (with different training and testing sets) by changing the value for the parameter random_state.

# Run on classic images

%run 2-functions.ipynb

import pandas as pd
from sklearn.metrics import accuracy_score

# Read dataset
images = read_images('./2-images.csv')

# Create HOG features
images = images.assign(hog_features = create_hog(images['image']))

# Build the model and return predictions
pred, y_test, test = classify_images(images, random_state = 3)

# Compute and print the accuracy
print('Accuracy: ' + str(accuracy_score(pred, y_test)))

# Print the test images and the predictions
print_results(pred, test)
Accuracy: 0.5
_images/2-2-2-edge_17_1.png
# Run on canny edge detection

%run 2-functions.ipynb

import skimage.feature as sf
from skimage.color import rgb2gray

images = read_images('./2-images.csv')

# Create canny image for each image
canny_list = []
for index, row in images.iterrows():
    canny_list.append(sf.canny(rgb2gray(row['image']), sigma = 3))

# Save canny in the images DataFrame
images = images.assign(canny = canny_list)

# Get the HOG features from the canny image
images = images.assign(hog_features = create_hog(images['canny'], canny = True))

# Classify and get the results
pred, y_test, test = classify_images(images, random_state = 3)
print('Accuracy: ' + str(accuracy_score(pred, y_test)))
print_results(pred, test)
Accuracy: 0.25
_images/2-2-2-edge_18_1.png
# Beginner version: cell to hide

import ipywidgets as widgets
from ipywidgets import interact

def compare_canny(random_state):
    
    %run 2-functions.ipynb

    import pandas as pd
    from sklearn.metrics import accuracy_score
    import skimage.feature as sf
    from skimage.color import rgb2gray

    images = read_images('./2-images.csv')

    images = images.assign(hog_features = create_hog(images['image']))
    pred, y_test, test = classify_images(images, random_state = random_state)
    print('Accuracy with normal images: ' + str(accuracy_score(pred, y_test)))
    print_results(pred, test)
    
    canny_list = []
    for index, row in images.iterrows():
        canny_list.append(sf.canny(rgb2gray(row['image']), sigma = 3))
    images = images.assign(canny = canny_list)
    images = images.assign(hog_features = create_hog(images['canny'], canny = True))
    pred, y_test, test = classify_images(images, random_state)
    print('Accuracy with canny transformation: ' + str(accuracy_score(pred, y_test)))
    print_results(pred, test)

interact(compare_canny, random_state = widgets.IntText(
    value = 3,
    description = 'random_state:',
    disabled = False
))
<function __main__.compare_canny(random_state)>

Note that the size of the dataset we use is really small (20 images) and that is why the result of the changes we make might not be obvious. Trying with a bigger dataset might show better results, but the models would be too long to run in this course.

Quiz

from IPython.display import IFrame
IFrame("https://blog.hoou.de/wp-admin/admin-ajax.php?action=h5p_embed&id=69", "959", "309")