【基础】边缘检测方法:Canny算法与Sobel算子
发布时间: 2024-06-27 04:35:51 阅读量: 107 订阅数: 149
基于Canny算子的边缘检测
![【基础】边缘检测方法:Canny算法与Sobel算子](https://img-blog.csdnimg.cn/fa09e02aec2440e7b0507e7437ed0f55.png)
# 1. 边缘检测基本原理**
边缘检测是图像处理中的基本技术,用于检测图像中像素之间的锐利变化,从而提取图像中的关键特征。边缘通常表示物体或区域之间的边界,对于图像分析、目标检测和图像分割等计算机视觉任务至关重要。
边缘检测算法通过计算图像中像素的梯度来工作。梯度表示像素值在水平和垂直方向上的变化率。梯度较大的像素表示存在边缘,而梯度较小的像素表示平滑区域。
# 2. Canny算法
Canny算法是一种多阶段边缘检测算法,以其出色的抗噪性和边缘定位精度而闻名。它由John Canny于1986年提出,至今仍广泛应用于计算机视觉和图像处理领域。
### 2.1 Canny算法的理论基础
Canny算法主要包含以下四个步骤:
#### 2.1.1 高斯滤波
高斯滤波是一种线性平滑滤波器,用于消除图像中的噪声。它使用一个高斯核与图像进行卷积,该核的形状类似于钟形曲线。卷积操作将图像中的每个像素值替换为其周围像素值的加权平均值,权重由高斯核决定。
```python
import cv2
import numpy as np
# 定义高斯核
kernel = cv2.getGaussianKernel(5, 1.0)
# 对图像进行高斯滤波
blurred_image = cv2.filter2D(image, -1, kernel)
```
**参数说明:**
* `image`:输入图像
* `kernel`:高斯核
* `blurred_image`:高斯滤波后的图像
**代码逻辑:**
1. `cv2.getGaussianKernel()` 函数根据指定的内核大小和标准差生成高斯核。
2. `cv2.filter2D()` 函数执行图像与高斯核之间的卷积操作,从而实现高斯滤波。
#### 2.1.2 梯度计算
梯度计算用于检测图像中像素值的变化率,它可以帮助识别图像中的边缘。Canny算法使用Sobel算子计算图像的梯度,Sobel算子是一个3x3的卷积核,用于分别计算水平和垂直方向的梯度。
```python
# 计算图像的水平和垂直梯度
sobelx = cv2.Sobel(blurred_image, cv2.CV_64F, 1, 0, ksize=5)
sobely = cv2.Sobel(blurred_image, cv2.CV_64F, 0, 1, ksize=5)
# 计算梯度幅值和方向
gradient_magnitude = np.sqrt(sobelx**2 + sobely**2)
gradient_direction = np.arctan2(sobely, sobelx)
```
**参数说明:**
* `blurred_image`:高斯滤波后的图像
* `sobelx`:水平梯度图像
* `sobely`:垂直梯度图像
* `gradient_magnitude`:梯度幅值图像
* `gradient_direction`:梯度方向图像
**代码逻辑:**
1. `cv2.Sobel()` 函数使用Sobel算子计算图像的水平和垂直梯度。
2. 梯度幅值是水平和垂直梯度的平方和的平方根。
3. 梯度方向是垂直梯度与水平梯度的反正切。
#### 2.1.3 非极大值抑制
非极大值抑制是一种边缘细化技术,用于消除梯度幅值图像中非极大值像素。它沿每个像素的梯度方向搜索,并仅保留梯度幅值最大的像素。
```python
# 执行非极大值抑制
thinned_image = cv2.thinning(gradient_magnitude, thinningType=cv2.THINNING_GUOHALL)
```
**参数说明:**
* `gradient_magnitude`:梯度幅值图像
* `thinned_image`:非极大值抑制后的图像
**代码逻辑:**
`cv2.thinning()` 函数使用Guo-Hall算法执行非极大值抑制。
#### 2.1.4 双阈值处理
双阈值处理是一种阈值分割技术,用于将非极大值抑制后的图像二值化。它使用两个阈值:高阈值和低阈值。梯度幅值高于高阈值的像素被标记为强边缘,低于低阈值的像素被标记为弱边缘。介于两者之间的像素被标记为噪声并被抑制。
```python
# 设置高阈值和低阈值
high_threshold = 0.5 * np.max(thinned_image)
low_threshold = 0.2 * high_threshold
# 执行双阈值处理
edges = np.zeros(thinned_image.shape, dtype=np.uint8)
edges[thinned_image > high_threshold] = 255
edges[thinned_image < low_threshold] = 0
edges[np.logical_and(thinned_image >= low_threshold, thinned_image <= high_threshold)] = 128
```
**参数说明:**
* `thinned_image`:非极大值抑制后的图像
* `high_threshold`:高阈值
* `low_threshold`:低阈值
* `edges`:二值化后的边缘图像
**代码逻辑:**
1. 设置高阈值和低阈值。
2. 创建一个与非极大值抑制后的图像大小相同的空图像 `edges`。
3. 将梯度幅值高于高阈值的像素标记为 255(强边缘)。
4. 将梯度幅值低于低阈值的像素标记为 0(噪声)。
5. 将梯度幅值介于高阈值和低阈值之间的像素标记
0
0