Edge detection is very common and widely used image processing necessary for many different computer vision applications like data extraction, image segmentation, and in more granular level feature extraction, and pattern recognition. It reduces the level of noise and the number of details in an image but preserves the structure of the image.
Canny edge detection in Python is one of the most popular edge detection methods in computer vision. These are the steps for Canny edge detection:
- Reducing noise using the Gaussian smoothing
- Computing the gradients
- Applying non-maxima suppression to reduce the noise and have only the local maxima in the direction of the gradient
- Finding the upper and lower threshold
- Applying the threshold.
Luckily OpenCV library has cv2.canny() function that performs Canny edge detection for us. In this article, we will go directly into performing edge detection using OpenCV.
import matplotlib.pyplot as plt
We will use the following picture for today’s tutorial:
The first step of the Canny Edge detection was to apply Gaussian Blur. Before blurring, it is also important to convert the image to grayscale as well:
image = cv2.imread("meter.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
Now, we can directly apply our cv2.Canny() method to this blurred picture. It’s simple. It takes three parameters: the image itself, the lower threshold, and the upper threshold. Choosing these thresholds is tricky. For each image, these thresholds will be different.
For this image, we will try three different ranges and observe what happens:
wide = cv2.Canny(blurred, 50, 200)
mid = cv2.Canny(blurred, 30, 150)
tight = cv2.Canny(blurred, 210, 250)
Here I used three different types of ranges. In the wide, the threshold values have a wide range. In the mid, the threshold values have somewhere mid-range and in the tight, the threshold values have a tight range, only 210 to 250, pretty close.
To check the images I just saved these three images (wide, mid, and tight).
These are the results:
This is the result of the mid-range:
The image from the tight range:
If we notice these three images, I believe the mid-range gave a more solid edge.
Remember, you cannot generalize this ranges. For a different image a different range may work. That’s why it is so tricky
The good news is, There are a few statistical tricks available that can be used to find the lower and upper threshold without the trial and error method we saw earlier.
This is the function for automatic edge detection:
def auto_canny_edge_detection(image, sigma=0.33):
md = np.median(image)
lower_value = int(max(0, (1.0-sigma) * md))
upper_value = int(min(255, (1.0+sigma) * md))
return cv2.Canny(image, lower_value, upper_value)
In the function above, the median pixel value from the image array is found first. Then using this median and a constant sigma value you can find the lower and upper thresholds. Here a sigma value of 0.33 was used. In most applications 0.33 works as a sigma value. But in some cases, if it doesn’t give you a good result, try some other sigma value as well.
Here is the use of the auto_canny_edge_detection method on the blurred image we created before:
auto_edge = auto_canny_edge_detection(blurred)
This is what auto.jpg looks like:
As you can see the edge came here pretty clearly without having to try too many thresholds.
In my opinion, the automatic edge detection function provided us with the best result. Please feel free to try with your own application. It can be very useful.