opencv 中Canny边缘检测算法原理加每一个(分)步骤的代码演示

1.原理

1.噪声抑制:输入图像经过高斯平滑滤波,减少噪声的影响。
2.计算梯度:在平滑后的图像上应用Sobel算子计算梯度幅值和方向。
3.非极大值抑制:在梯度方向上,比较每个像素的梯度幅值与其相邻两个像素沿着梯度方向的梯度幅值。如果当前像素的梯度幅值最大,保留该像素,否则抑制(设为0)。

4.双阈值处理:设定高阈值和低阈值,对梯度幅值进行分类。梯度幅值高于高阈值的像素被视为强边缘,低于低阈值的像素被视为弱边缘,位于两者之间的像素被视为可能的边缘。A ⾼于阈值 maxVal 所以是真正的边界点,C 虽然低于 maxVal 但⾼于 minVal 并且与 A 相连,所以也被认为是可能的边界点。⽽ B 就会被抛弃

5.边缘连接:对强边缘像素进行连接,形成连续的边缘线条。
通过跟随弱边缘像素,并且与强边缘像素连接的方式来连接边缘,也就是根据弱边缘像素的位置,并且寻找与之相邻的强边缘像素来连接边缘。

2.代码实现

import cv2
import numpy as np

# 读取图像并转换为灰度图
image = cv2.imread('./base/lena.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 1. 噪声抑制
blurred = cv2.GaussianBlur(gray, (5, 5), 0)

# 2. 计算梯度
gradient_x = cv2.Sobel(blurred, cv2.CV_64F, 1, 0, ksize=3)
gradient_y = cv2.Sobel(blurred, cv2.CV_64F, 0, 1, ksize=3)

gradient_magnitude = np.sqrt(gradient_x**2 + gradient_y**2)
gradient_direction = np.arctan2(gradient_y, gradient_x)

# 3. 非极大值抑制
rows, cols = gradient_magnitude.shape #去除行和列的像素值
non_maximum_suppression = np.zeros((rows, cols), dtype=np.float32) 

for i in range(1, rows - 1):
    for j in range(1, cols - 1):
        angle = gradient_direction[i, j] * 180 / np.pi #(将弧度转换为角度)
        angle = angle % 180 #取(0-180度)

        if (0 <= angle < 22.5) or (157.5 <= angle <= 180):
        #0°到22.5°或者157.5°到180°之间,表示该像素点的梯度方向为水平方向
            neighbor_pixels = [gradient_magnitude[i, j - 1], gradient_magnitude[i, j + 1]]
        elif 22.5 <= angle < 67.5:
        #梯度方向落在 22.5°到67.5°之间,表示该像素点的梯度方向为主对角线方向
            neighbor_pixels = [gradient_magnitude[i - 1, j - 1], gradient_magnitude[i + 1, j + 1]]
        elif 67.5 <= angle < 112.5:
        #梯度方向落在 67.5°到112.5°之间,表示该像素点的梯度方向为垂直方向
            neighbor_pixels = [gradient_magnitude[i - 1, j], gradient_magnitude[i + 1, j]]
        else:
        #梯度方向落在 112.5°到157.5°之间,表示该像素点的梯度方向为副对角线方向
            neighbor_pixels = [gradient_magnitude[i - 1, j + 1], gradient_magnitude[i + 1, j - 1]]

        if gradient_magnitude[i, j] >= max(neighbor_pixels):
            non_maximum_suppression[i, j] = gradient_magnitude[i, j]

# 4. 双阈值处理
high_threshold = np.max(non_maximum_suppression) * 0.7  #可以自己更改
#梯度值最大值的一定比例(如0.7) 
low_threshold = high_threshold * 0.3   #也可以自己更改
#低阈值设为高阈值的较低比例(如0.3)

strong_edges = (non_maximum_suppression >= high_threshold)
weak_edges = (non_maximum_suppression > low_threshold) & (non_maximum_suppression < high_threshold)

# 5. 边缘连接
edges = np.zeros_like(image)
edges[strong_edges] = [255, 0, 0]  # Strong edges in blue color
#strong_edges 是一个二值图像,其中像素值为 True 表示该位置为强边缘。设置为蓝色
edges[weak_edges] = [0, 0, 255]  # Weak edges in red color
#weak_edges 也是一个二值图像,其中像素值为 True 表示该位置为弱边缘,设为红色

edges_gray = cv2.cvtColor(edges, cv2.COLOR_BGR2GRAY)

# 显示结果
cv2.imshow('Input', image)
cv2.imshow('Canny Edges (Grayscale)', edges_gray)
cv2.imshow('Canny Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果:

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值