How to resolve the algorithm Canny edge detector step by step in the Python programming language
Published on 12 May 2024 09:40 PM
How to resolve the algorithm Canny edge detector step by step in the Python programming language
Table of Contents
Problem Statement
Write a program that performs so-called canny edge detection on an image.
A possible algorithm consists of the following steps:
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Canny edge detector step by step in the Python programming language
Canny Edge Detection
This Python code implements the Canny edge detection algorithm, which is used to extract edges from images. Here's a detailed explanation:
-
Import Necessary Libraries:
numpy
for numerical operationsscipy.ndimage.filters
for image filteringscipy.misc
for image input and output
-
CannyEdgeDetector
Function:- Inputs:
im
: Input grayscale image as a NumPy arrayblur
(optional): Gaussian blur strength (default: 1)highThreshold
(optional): Upper threshold for edge detection (default: 91)lowThreshold
(optional): Lower threshold for edge detection (default: 31)
- Steps:
- Gaussian Blur: Applied to reduce noise in the input image (
im
). - Sobel Filters: Used to compute horizontal (
im3h
) and vertical (im3v
) gradients. - Gradient and Direction: Calculated from the Sobel gradients.
- Quantization: The gradient direction
theta
is quantized into five discrete values (0, 1, 2, 3, 4). - Non-Maximum Suppression: Suppresses pixels along edges that are not the local maxima in their direction.
- Double Thresholding: Performs hysteresis thresholding to determine the final edge pixels.
- Weak pixels:
gradSup > lowThreshold
- Strong pixels:
gradSup > highThreshold
- Weak pixels:
- Edge Tracing with Hysteresis: Traces the edges based on the weak and strong pixels.
- Gaussian Blur: Applied to reduce noise in the input image (
- Inputs:
-
Main Function:
- Reads a grayscale image (
test.jpg
) usingimread
and converts it to NumPy array. - Applies the
CannyEdgeDetector
function to get the edges. - Displays the resulting edge image using
imshow
.
- Reads a grayscale image (
This code effectively identifies edges in the input image and is widely used in image processing for object detection, segmentation, and other tasks.
Source code in the python programming language
#!/bin/python
import numpy as np
from scipy.ndimage.filters import convolve, gaussian_filter
from scipy.misc import imread, imshow
def CannyEdgeDetector(im, blur = 1, highThreshold = 91, lowThreshold = 31):
im = np.array(im, dtype=float) #Convert to float to prevent clipping values
#Gaussian blur to reduce noise
im2 = gaussian_filter(im, blur)
#Use sobel filters to get horizontal and vertical gradients
im3h = convolve(im2,[[-1,0,1],[-2,0,2],[-1,0,1]])
im3v = convolve(im2,[[1,2,1],[0,0,0],[-1,-2,-1]])
#Get gradient and direction
grad = np.power(np.power(im3h, 2.0) + np.power(im3v, 2.0), 0.5)
theta = np.arctan2(im3v, im3h)
thetaQ = (np.round(theta * (5.0 / np.pi)) + 5) % 5 #Quantize direction
#Non-maximum suppression
gradSup = grad.copy()
for r in range(im.shape[0]):
for c in range(im.shape[1]):
#Suppress pixels at the image edge
if r == 0 or r == im.shape[0]-1 or c == 0 or c == im.shape[1] - 1:
gradSup[r, c] = 0
continue
tq = thetaQ[r, c] % 4
if tq == 0: #0 is E-W (horizontal)
if grad[r, c] <= grad[r, c-1] or grad[r, c] <= grad[r, c+1]:
gradSup[r, c] = 0
if tq == 1: #1 is NE-SW
if grad[r, c] <= grad[r-1, c+1] or grad[r, c] <= grad[r+1, c-1]:
gradSup[r, c] = 0
if tq == 2: #2 is N-S (vertical)
if grad[r, c] <= grad[r-1, c] or grad[r, c] <= grad[r+1, c]:
gradSup[r, c] = 0
if tq == 3: #3 is NW-SE
if grad[r, c] <= grad[r-1, c-1] or grad[r, c] <= grad[r+1, c+1]:
gradSup[r, c] = 0
#Double threshold
strongEdges = (gradSup > highThreshold)
#Strong has value 2, weak has value 1
thresholdedEdges = np.array(strongEdges, dtype=np.uint8) + (gradSup > lowThreshold)
#Tracing edges with hysteresis
#Find weak edge pixels near strong edge pixels
finalEdges = strongEdges.copy()
currentPixels = []
for r in range(1, im.shape[0]-1):
for c in range(1, im.shape[1]-1):
if thresholdedEdges[r, c] != 1:
continue #Not a weak pixel
#Get 3x3 patch
localPatch = thresholdedEdges[r-1:r+2,c-1:c+2]
patchMax = localPatch.max()
if patchMax == 2:
currentPixels.append((r, c))
finalEdges[r, c] = 1
#Extend strong edges based on current pixels
while len(currentPixels) > 0:
newPix = []
for r, c in currentPixels:
for dr in range(-1, 2):
for dc in range(-1, 2):
if dr == 0 and dc == 0: continue
r2 = r+dr
c2 = c+dc
if thresholdedEdges[r2, c2] == 1 and finalEdges[r2, c2] == 0:
#Copy this weak pixel to final result
newPix.append((r2, c2))
finalEdges[r2, c2] = 1
currentPixels = newPix
return finalEdges
if __name__=="__main__":
im = imread("test.jpg", mode="L") #Open image, convert to greyscale
finalEdges = CannyEdgeDetector(im)
imshow(finalEdges)
You may also check:How to resolve the algorithm Sierpinski arrowhead curve step by step in the AutoHotkey programming language
You may also check:How to resolve the algorithm Higher-order functions step by step in the Déjà Vu programming language
You may also check:How to resolve the algorithm Emirp primes step by step in the ALGOL 68 programming language
You may also check:How to resolve the algorithm First-class functions/Use numbers analogously step by step in the Rust programming language
You may also check:How to resolve the algorithm Apply a digital filter (direct form II transposed) step by step in the Raku programming language