[opencv] Edge/line detection algorithms (Canny, HoughLines)

서대철·2023년 11월 14일
0

Canny Edge Algorithm
Canny Edge Detection is a popular edge detection algorithm developed by John F. Canny in 1986. It is a multi-stage algorithm used to detect a wide range of edges in images. The Canny edge detector is known for its robustness and accuracy and is widely used in computer vision and image processing applications.

The Canny Edge Detection algorithm involves several steps:

Noise Reduction: Since edge detection is susceptible to noise in the image, the first step is to remove the noise. Typically, a Gaussian filter is applied to smooth the image. This helps to reduce the impact of noise and spurious gradients in the image.

Gradient Calculation: The algorithm then calculates the gradient of the image intensity at each pixel. This step finds the edge intensity and direction by calculating the gradient of the image using edge detection operators (like the Sobel operator). The gradient's direction is perpendicular to the edges.

Non-maximum Suppression: To get rid of spurious response to edge detection, the algorithm applies non-maximum suppression. This step thins out the edges, ensuring that the edge response is localized to a single thin line rather than a wide response.

Double Thresholding: After applying non-maximum suppression, the algorithm uses two thresholds (a low and a high threshold) to determine potential edges. Strong edges (intensities higher than the high threshold) are definitely edges, while weak edges (intensities lower than the low threshold) are suppressed. Those in between are classified as edges only if they are connected to strong edges. This step helps to mitigate the problem of broken edges.

Edge Tracking by Hysteresis: The final step involves edge tracking by hysteresis. Based on the thresholding, the edges are tracked. Weak edges that are not connected to strong edges are discarded, ensuring that the final result only shows strong, continuous edges.

The Canny Edge Detector is widely appreciated for its ability to detect edges with low error rate, meaning it detects the edges as accurately as possible. It is also well-regarded for its ability to precisely localize the edges and to provide a single response to a single edge, making it a preferred choice for applications that require high-quality edge detection.

SAMPLE CODE:

import sys
import numpy as np
import cv2

src = cv2.imread('./building.jpeg', cv2.IMREAD_GRAYSCALE)

if src is None:
    print('IMAGE LOAD FAILED.')
    sys.exit()

dst = cv2.Canny(src, 50, 150)

cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.waitKey()

cv2.destroyAllWindows()

BEFORE:

AFTER:


Hough Lines Algorithm
The Hough Transform is a popular technique to detect any shape that can be represented in mathematical form in an image, and it's particularly well-known for its ability to detect straight lines. The Hough Lines algorithm is a specific application of the Hough Transform for line detection.

How the Hough Lines Algorithm Works:
Edge Detection: The first step usually involves using an edge detection technique like the Canny edge detector. The Hough Transform works on binary images, so the input image is converted to binary with edges highlighted.

Mapping to Hough Space: The algorithm then maps these edge points to a parameter space (called Hough space) and stores them in an accumulator. For line detection, this space is usually defined by two parameters:
θ (theta) and r (rho).
θ is the angle of the line from the horizontal, and r is the shortest distance from the origin to the line.

Accumulator: In Hough space, each point in the image votes for all the lines that could pass through it. These votes are accumulated in a two-dimensional array (for lines), where one dimension represents θ and the other represents r.

Detecting Lines: A line in the original image corresponds to a peak in the accumulator space. By finding the local maxima in the accumulator space, the algorithm can identify the lines in the original image. Thresholding is often used to only select the most prominent lines.

Converting Back to Image Space: Finally, the line parameters found in Hough space are converted back to the image space to draw the detected lines on the original image.

The Hough Lines algorithm is particularly effective for detecting straight lines in images, such as road lanes in autonomous driving systems or the structure of buildings in architectural images. However, it can be computationally intensive, especially for large images with many edge points.


Combining Hough Lines with Canny Edge Detection

The Hough Lines Transform can be effectively combined with the Canny Edge Detection algorithm to detect straight lines in images. Here's a step-by-step guide on how you can use these two algorithms together:

Steps for Combining Hough Lines and Canny Edge Detection:

Preprocess the Image
Convert your image to grayscale using a function like cv2.cvtColor(img, cv2.COLOR_BGR2GRAY).
Optionally, apply Gaussian blurring to reduce noise and improve the effectiveness of edge detection.

Apply Canny Edge Detection:
Use the Canny Edge Detector to find edges in the image. This is done using the OpenCV function cv2.Canny(). This function will return an image where the edges are highlighted while the rest of the image is black.

Use Hough Lines Transform:
Apply the Hough Lines Transform on the edge-detected image to find lines. In OpenCV, this can be done using cv2.HoughLines() or cv2.HoughLinesP().

Draw the Detected Lines:
For each detected line, draw it onto the original image (or a copy of it) using cv2.line().

Display or Save the Result:
Finally, display or save the image with the detected lines.

Example Code in Python using OpenCV:

import sys
import numpy as np
import cv2

src = cv2.imread('./building.jpeg', cv2.IMREAD_GRAYSCALE)

if src is None:
    print('IMAGE LOAD FAILED.')
    sys.exit()

edges = cv2.Canny(src, 50, 150)

lines = cv2.HoughLinesP(edges, 1, np.pi/180., 160,
                        minLineLength=50, maxLineGap=5)

dst = cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)

if lines is not None:
    for i in range(lines.shape[0]):
        pt1 = (lines[i][0][0], lines[i][0][1])    # starting point coord
        pt2 = (lines[i][0][2], lines[i][0][3])    # ending point coord
        cv2.line(dst, pt1, pt2, (0,0,255), 2, cv2.LINE_AA)

cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.waitKey()   

0개의 댓글