In part 1 on the topic of Edge Detection , I presented the criteria for evaluating how a detector is a good detector as well as Sobel Edge Detection algorithm and specific examples. You can watch it here . In part 2, I would like to continue presenting the Canny Edge Detection algorithm. This is an edge determination algorithm that is commonly and effectively used in computer vision problems.
2. Canny Edge Detection algorithm
In general, the Canny Edge Detection algorithm consists of 4 steps :
- Get the derivative of the image horizontally and along the Gaussian distribution
- Calculate the intensity and direction of the gradient
- Non-maximum suppression (this part I want to speak English because I don’t know how to speak )
- Using threshold to create elimination of edges, determine real edges
Here we explore the meaning one by one. Here I use an image below as the input image for all the examples below
2.1. Get the derivative in the Gaussian distribution
Similar to when dealing with Sobel’s algorithm, we take the derivative horizontally x (Gx) and vertically y (Gy) . Since the direction of the gradient is always perpendicular to the edges, the image that takes the derivative in the horizontal direction x (Gx) will get the vertical lines and the image taking the vertical derivative (Gy) will get the horizontal strokes of the image.
2.2. Calculate the intensity and direction of the gradient
From the derivative results in the x and y directions on the input image, we calculate the gradient intensity and direction of each pixel by the formula:
- Gradient intensity = sqrt (Gx ^ 2 + Gy ^ 2)
- Direction of gradient: theta = atan2 (gy, gx)
2.3. Non-maximum suppression
You can see the girl in the image of result 2.2 has more borders around her body than the original image. This is because there are many pixels that describe the same pixel on the edge of the original image. So to make the edges sharper and thinner like the original image we use Non-maximum suppression to remove excess pixels.
I explain the algorithm Non-maximum suppression as follows: With a pixel A is determined on an edge. We will have a vector gradient direction always perpendicular to the edge. On vector gradient direction we can have multiple pixels here for example B and C. Three pixels A, B, C describe the same pixel on the original edge so we have to compare the values between A, B and C defined. Where is the pixel with the largest value. Then remove the remaining two pixels by setting them to 0.
Do you see the clear difference in the left image not using Non-maximum suppression, the lines will be thicker and darker, but after applying the algorithm we get the edge with the finer strokes due to removing excess pixels .
2.4. ‘Hysteresis’ thresholding
This step will determine if an edge we predict in the steps above is an actual edge. The threshold value here has two thresholds Vmax and Vmin . We implemented the algorithm based on these two values as follows:
- If the intensity of the gradient (Magnitude)> Vmax is definitely a strong edge
- If Magnitude <low threshold <Vmin, it is noise
- If Vmin <Magnitude <Vmax, it is an undetermined weak edge, or weak edge.
- For weak edges, if any edge is connected to a strong edge, that weak edge is the edge, otherwise it will be noise
The example in the figure above A is above the Vmax threshold so A is definitely a strong edge. C is between Vmax and Vmin so C is a weak edge but C is connected to strong edge A so C is also an edge. However, B is also in the same threshold as C but it is not connected to any edge which is definitely a strong edge, so B is noise
3. Example with Canny Edge Detection
def canny_edge_detection(image_path, blur_ksize=5, threshold1=100, threshold2=200):
image_path: link to image
blur_ksize: Gaussian kernel size
threshold1: min threshold
threshold2: max threshold
img = cv2.imread(image_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_gaussian = cv2.GaussianBlur(gray,(blur_ksize,blur_ksize),0)
img_canny = cv2.Canny(img_gaussian,threshold1,threshold2)
image_path = 'example.png'
gray = cv2.imread(image_path, 0)
img_canny = canny_edge_detection(image_path, 25, 50, 100)
We can adjust the parameters threshold1 and threshold2 to customize for each image you apply the algorithm.
Thank you for following up on my article.