canny算子边缘检测原理,步骤和代码
时间: 2023-10-03 19:02:17 浏览: 42
Canny算子是一种经典的边缘检测算法,其具有高精度、低误差、单一边缘、边缘细化等优点。
Canny算子的原理:
1. 高斯滤波:首先对图像进行高斯滤波,消除噪声干扰。
2. 计算梯度幅值和方向:利用Sobel算子计算图像的梯度幅值和方向。
3. 非极大值抑制:在图像的梯度方向上,通过比较局部梯度幅值,选择局部极大值点作为边缘点。
4. 双阈值处理:将图像中的边缘点分为强边缘和弱边缘,强边缘直接输出,弱边缘需要进一步判断。
5. 边缘连接:弱边缘只有在其与强边缘相连的情况下才能被认为是真正的边缘。
Canny算子的步骤:
1. 对图像进行高斯滤波,消除噪声干扰。
2. 计算图像的梯度幅值和方向。
3. 对图像进行非极大值抑制,得到边缘点。
4. 对边缘点进行双阈值处理,得到强边缘和弱边缘。
5. 对弱边缘进行边缘连接,得到最终的边缘图像。
Canny算子的代码实现:
```python
import cv2
# 读取图像
img = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE)
# 高斯滤波
img_blur = cv2.GaussianBlur(img, (5, 5), 0)
# 计算梯度幅值和方向
sobelx = cv2.Sobel(img_blur, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(img_blur, cv2.CV_64F, 0, 1, ksize=3)
grad_mag = cv2.magnitude(sobelx, sobely)
grad_dir = cv2.phase(sobelx, sobely, angleInDegrees=True)
# 非极大值抑制
grad_max = cv2.copyMakeBorder(grad_mag, 1, 1, 1, 1, cv2.BORDER_CONSTANT, value=0)
grad_dir = grad_dir % 180
for i in range(1, grad_max.shape[0] - 1):
for j in range(1, grad_max.shape[1] - 1):
if grad_dir[i - 1, j - 1] < 22.5 or grad_dir[i - 1, j - 1] >= 157.5:
grad_max[i, j] = (grad_mag[i - 1, j] < grad_mag[i, j] > grad_mag[i + 1, j]) * grad_mag[i, j]
elif 22.5 <= grad_dir[i - 1, j - 1] < 67.5:
grad_max[i, j] = (grad_mag[i - 1, j - 1] < grad_mag[i, j] > grad_mag[i + 1, j + 1]) * grad_mag[i, j]
elif 67.5 <= grad_dir[i - 1, j - 1] < 112.5:
grad_max[i, j] = (grad_mag[i, j - 1] < grad_mag[i, j] > grad_mag[i, j + 1]) * grad_mag[i, j]
else:
grad_max[i, j] = (grad_mag[i + 1, j - 1] < grad_mag[i, j] > grad_mag[i - 1, j + 1]) * grad_mag[i, j]
grad_max = grad_max[1:-1, 1:-1]
# 双阈值处理
thresh_high = 80
thresh_low = 40
strong_edge = (grad_max > thresh_high).astype(int)
weak_edge = ((grad_max <= thresh_high) & (grad_max >= thresh_low)).astype(int)
# 边缘连接
def edge_tracking(i, j):
if i < 0 or i >= grad_max.shape[0] or j < 0 or j >= grad_max.shape[1]:
return
if strong_edge[i, j] == 1 or weak_edge[i, j] == 0:
return
strong_edge[i, j] = 1
for x in range(-1, 2):
for y in range(-1, 2):
if x == 0 and y == 0:
continue
edge_tracking(i + x, j + y)
for i in range(grad_max.shape[0]):
for j in range(grad_max.shape[1]):
if strong_edge[i, j] == 1:
edge_tracking(i, j)
# 显示结果
cv2.imshow('src', img)
cv2.imshow('canny', strong_edge * 255)
cv2.waitKey(0)
cv2.destroyAllWindows()
```