canny边缘检测算子实现边缘检测
时间: 2023-10-02 14:11:03 浏览: 87
Canny边缘检测是一种常用的边缘检测算法,其主要步骤包括:
1. 高斯滤波:使用高斯滤波器对图像进行平滑处理,以去除噪声。
2. 计算梯度幅值和方向:对平滑后的图像计算每个像素点的梯度幅值和方向。
3. 非极大值抑制:对梯度图像进行非极大值抑制,以保留边缘的细节。
4. 双阈值处理:将梯度图像按照两个阈值进行二值化处理,较大的梯度幅值被认为是边缘,较小的梯度幅值被认为是噪声或非边缘。
5. 连通区域分析:对二值化后的图像进行连通区域分析,以得到完整的边缘。
下面是Canny边缘检测算法的Python实现:
```python
import cv2
import numpy as np
def canny_edge_detection(img, low_threshold, high_threshold):
# 高斯滤波
img = cv2.GaussianBlur(img, (3,3), 0)
# 计算梯度幅值和方向
dx = cv2.Sobel(img, cv2.CV_16S, 1, 0)
dy = cv2.Sobel(img, cv2.CV_16S, 0, 1)
gradient = np.sqrt(dx*dx + dy*dy)
gradient_direction = np.arctan2(dy, dx) * 180 / np.pi
# 非极大值抑制
rows, cols = img.shape
for i in range(1, rows-1):
for j in range(1, cols-1):
if (gradient_direction[i,j] <= 22.5 and gradient_direction[i,j] > -22.5) or \
(gradient_direction[i,j] <= -157.5 and gradient_direction[i,j] > 157.5):
if gradient[i,j] > gradient[i,j+1] and gradient[i,j] > gradient[i,j-1]:
gradient[i,j] = gradient[i,j]
else:
gradient[i,j] = 0
elif (gradient_direction[i,j] <= 67.5 and gradient_direction[i,j] > 22.5) or \
(gradient_direction[i,j] <= -112.5 and gradient_direction[i,j] > -157.5):
if gradient[i,j] > gradient[i-1,j+1] and gradient[i,j] > gradient[i+1,j-1]:
gradient[i,j] = gradient[i,j]
else:
gradient[i,j] = 0
elif (gradient_direction[i,j] <= 112.5 and gradient_direction[i,j] > 67.5) or \
(gradient_direction[i,j] <= -67.5 and gradient_direction[i,j] > -112.5):
if gradient[i,j] > gradient[i-1,j] and gradient[i,j] > gradient[i+1,j]:
gradient[i,j] = gradient[i,j]
else:
gradient[i,j] = 0
elif (gradient_direction[i,j] <= 157.5 and gradient_direction[i,j] > 112.5) or \
(gradient_direction[i,j] <= -22.5 and gradient_direction[i,j] > -67.5):
if gradient[i,j] > gradient[i-1,j-1] and gradient[i,j] > gradient[i+1,j+1]:
gradient[i,j] = gradient[i,j]
else:
gradient[i,j] = 0
# 双阈值处理
edge_img = np.zeros((rows, cols), dtype=np.uint8)
strong_edge_row, strong_edge_col = np.where(gradient > high_threshold)
weak_edge_row, weak_edge_col = np.where((gradient >= low_threshold) & (gradient <= high_threshold))
edge_img[strong_edge_row, strong_edge_col] = 255
edge_img[weak_edge_row, weak_edge_col] = 50
# 连通区域分析
for i in range(1, rows-1):
for j in range(1, cols-1):
if edge_img[i,j] == 50:
if (edge_img[i-1,j-1] == 255) or (edge_img[i-1,j] == 255) or (edge_img[i-1,j+1] == 255) or \
(edge_img[i,j-1] == 255) or (edge_img[i,j+1] == 255) or \
(edge_img[i+1,j-1] == 255) or (edge_img[i+1,j] == 255) or (edge_img[i+1,j+1] == 255):
edge_img[i,j] = 255
else:
edge_img[i,j] = 0
return edge_img
```
其中,`img`为输入的灰度图像,`low_threshold`和`high_threshold`为两个阈值,可以通过调整这两个值来控制边缘检测的效果。函数的返回值为二值化后的边缘图像。
阅读全文