
Edge detection
The process of edge detection involves detecting sharp edges in the image and producing a binary image as the output. Typically, we draw white lines on a black background to indicate those edges. We can think of edge detection as a high pass filtering operation. A high pass filter allows high frequency content to pass through and blocks the low frequency content. As we discussed earlier, edges are high frequency content. In edge detection, we want to retain these edges and discard everything else. Hence, we should build a kernel that is the equivalent of a high pass filter.
Let's start with a simple edge detection filter known as the Sobel
filter. Since edges can occur in both horizontal and vertical directions, the Sobel
filter is composed of the following two kernels:

The kernel on the left detects horizontal edges and the kernel on the right detects vertical edges. OpenCV provides a function to directly apply the Sobel
filter to a given image. Here is the code to use Sobel filters to detect edges:
import cv2 import numpy as np img = cv2.imread('input_shapes.png', cv2.IMREAD_GRAYSCALE) rows, cols = img.shape sobel_horizontal = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5) sobel_vertical = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5) cv2.imshow('Original', img) cv2.imshow('Sobel horizontal', sobel_horizontal) cv2.imshow('Sobel vertical', sobel_vertical) cv2.waitKey(0)
The output will look something like the following:

In the preceding figure, the image in the middle is the output of horizontal edge detector, and the image on the right is the vertical edge detector. As we can see here, the Sobel
filter detects edges in either a horizontal or vertical direction and it doesn't give us a holistic view of all the edges. To overcome this, we can use the Laplacian
filter. The advantage of using this filter is that it uses double derivative in both directions. You can call the function using the following line:
laplacian = cv2.Laplacian(img, cv2.CV_64F)
The output will look something like the following screenshot:

Even though the Laplacian
kernel worked great in this case, it doesn't always work well. It gives rise to a lot of noise in the output, as shown in the screenshot that follows. This is where the Canny edge
detector comes in handy:

As we can see in the above images, the Laplacian
kernel gives rise to a noisy output and this is not exactly useful. To overcome this problem, we use the Canny edge
detector. To use the Canny edge
detector, we can use the following function:
canny = cv2.Canny(img, 50, 240)
As we can see, the quality of the Canny edge detector is much better. It takes two numbers as arguments to indicate the thresholds. The second argument is called the low threshold value, and the third argument is called the high threshold value. If the gradient value is above the high threshold value, it is marked as a strong edge. The Canny Edge Detector starts tracking the edge from this point and continues the process until the gradient value falls below the low threshold value. As you increase these thresholds, the weaker edges will be ignored. The output image will be cleaner and sparser. You can play around with the thresholds and see what happens as you increase or decrease their values. The overall formulation is quite deep. You can learn more about it at http://www.intelligence.tuc.gr/~petrakis/courses/computervision/canny.pdf