Canny边缘检测的步骤以及一些重要步骤的原理(个人理解)

一、Canny边缘检测步骤

1): 使用高斯滤波,平滑图片、消除噪声

2): 计算图像中每个像素点的梯度强度(大小)和方向

3): 应用非极大值抑制,以消除边缘检测带来的杂散响应(在多个框中选择较准确的框)

4): 应用双阈值检测来确定真实的和潜在的边缘

5): 通过抑制孤立的弱边缘最终完成边缘检测

二、Canny边缘检测中的非极大值抑制

        Canny边缘检测中的非极大值抑制中要做的就是判断某一个像素点在其梯度方向上与临界两点进行比较看其梯度强度是否最大,最大则保留,反之则抑制。

        如上图所示(其中c、g1、g2等皆为像素点),假设向左上方向为梯度方向。与边界有dTmp1,dTmp2两个交点,如若要看c点是否为极大值点则就需要与dTmp1,dTmp2两点进行比较,但是这两个交点并不是实际的像素点,所以其梯度值无法直接计算,所以这里就需要引入一个线性插值法来解决这个问题。

线性插值法:如图dTmp1点为例,虽然其不为像素点,无法直接计算其梯度强度,但是dTmp1点是在g1与g2点中间,所以可以利用g1与g2两像素点的梯度强度(M)和一个比例系数(w)来近似估计dTmp1的梯度强度:M(dTmp1) = w*M(g2) + (1-w)*M(g1)。

其中w = distance(dTmp1 , g2) / distance(g1 , g2) (即dTmp1和g2之间的距离比上g1和g2的距离),这样便可以得到dTmp1的梯度强度,同理也可以得到dTmp2的梯度强度,这样的话便可以通过比较dTmp1、dTmp2、c三点的梯度强度来对c点进行非极大值抑制,当c点梯度强度小于dTmp1 or dTmp2中任一点时则对c点进行抑制。

三、Canny边缘检测中的双阈值检测       

如图所示,双阈值检测就是自己设定两个值:maxVal、minVal。

(1)当像素点的梯度强度值大于maxVal时便把此像素点认为是边界点并且保留

(2)当像素点梯度强度值小于minVal时便认为是边缘内侧的点,直接舍去。

(3)若梯度强度值处于二者中间则看此像素点是否和边界点相连,如果是相连的话则将此点作为边界点保留,反之则将此点视为边界内点舍弃。

这样便可以把边界的像素点保留,而把其他的像素点给舍弃。

三、Canny边缘检测代码以及效果图展示 

import numpy as np
import cv2

# canny边缘检测的步骤
# 1): 使用高斯滤波,平滑图片、消除噪声
# 2): 计算图像中每个像素点的梯度强度(大小)和方向
# 3): 应用非极大值抑制,以消除边缘检测带来的杂散响应(在多个框中选择较准确的框)
# 4): 应用双阈值检测来确定真实的和潜在的边缘
# 5): 通过抑制孤立的弱边缘最终完成边缘检测
img = cv2.imread('6.png' , cv2.IMREAD_GRAYSCALE) # 读取灰度图像

v1 = cv2.Canny(img , 80 , 150) # 80是低阈值,150是高阈值
v2 = cv2.Canny(img , 50 , 100) # 50是低阈值,100是高阈值

res = np.hstack((img , v1 , v2))  # 将原图像和几种算法得到的图像横向拼接起来

cv2.imshow("res" , res)
cv2.waitKey(0)
cv2.destroyAllWindows()

其中6.png是文件中的图片,可根据自己文件夹中的图片名字自行更改。以下是代码实现的效果展示(左 -> 右:原图(灰度图)、min80 max150、min50 max100):

  • 17
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
自适应阈值Canny边缘检测算法步骤如下: 1. 对输入图像进行高斯滤波,以平滑图像并去除噪声。 ```python import cv2 img = cv2.imread('image.jpg', 0) blur = cv2.GaussianBlur(img, (3, 3), 0) ``` 2. 计算图像中每个像素的梯度幅值和方向。 ```python sobelx = cv2.Sobel(blur, cv2.CV_64F, 1, 0, ksize=3) sobely = cv2.Sobel(blur, cv2.CV_64F, 0, 1, ksize=3) mag = cv2.magnitude(sobelx, sobely) theta = cv2.phase(sobelx, sobely, angleInDegrees=True) ``` 3. 对梯度方向进行四舍五入,将其转换为只有0、45、90、135度四个方向。 ```python theta = np.round(theta / 45) * 45 % 180 ``` 4. 对梯度幅值进行非最大抑制,以保留边缘的细节信息。 ```python rows, cols = mag.shape for i in range(1, rows - 1): for j in range(1, cols - 1): if (0 <= theta[i, j] < 22.5) or (157.5 <= theta[i, j] <= 180): if (mag[i, j] > mag[i, j - 1]) and (mag[i, j] > mag[i, j + 1]): mag[i, j] = mag[i, j] else: mag[i, j] = 0 elif (22.5 <= theta[i, j] < 67.5): if (mag[i, j] > mag[i - 1, j - 1]) and (mag[i, j] > mag[i + 1, j + 1]): mag[i, j] = mag[i, j] else: mag[i, j] = 0 elif (67.5 <= theta[i, j] < 112.5): if (mag[i, j] > mag[i - 1, j]) and (mag[i, j] > mag[i + 1, j]): mag[i, j] = mag[i, j] else: mag[i, j] = 0 elif (112.5 <= theta[i, j] < 157.5): if (mag[i, j] > mag[i - 1, j + 1]) and (mag[i, j] > mag[i + 1, j - 1]): mag[i, j] = mag[i, j] else: mag[i, j] = 0 ``` 5. 使用自适应阈值进行双阈值处理,以确定边缘像素。 ```python mag_max = np.max(mag) mag_min = np.min(mag) threshold1 = mag_min + 0.2 * (mag_max - mag_min) threshold2 = mag_min + 0.8 * (mag_max - mag_min) rows, cols = mag.shape for i in range(rows): for j in range(cols): if mag[i, j] < threshold1: mag[i, j] = 0 elif mag[i, j] > threshold2: mag[i, j] = 255 else: mag[i, j] = 50 ``` 6. 对双阈值处理后的图像进行边缘连接,以得到完整的边缘。 ```python edges = cv2.Canny(mag, threshold1, threshold2) ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值