1886 字
9 分钟
OpenCV:空域滤波【边缘检测】
1. 边缘检测
1.1 基本概念
边缘检测的目的是 标识图像中亮度变换明显 的点。边缘检测大幅度的减少了图像的数据量,剔除了不相关的信息,保留了重要的结构属性。图像的边缘检测是图像分割、目标区域识别和区域形状提取等图像分析的基石,也是图像中特征提取的很重要的方法。
1.2 特征
沿着边缘方向,像素值逐渐平稳垂直于边缘方向,像素值变化剧烈
1.3 分类
- 阶跃性边缘:两边的像素值有明显的差距,一阶方向导数在边缘处是零。
- 屋顶状边缘:从增加到减少的转折点,二阶方向导数在此处取得极值。
2. 梯度计算
图像梯度计算的是图像变化的速度。对于图像的边缘部分,其灰度值变化较大,梯度值也较大,相反,对于图像中比较平滑的部分,其灰度值变化较小,相应的梯度值也较小。
2.1 一阶微分边缘检测
通过计算图像的梯度值来检测图像边缘,常见的算子有Sobel、Prewitt、Roberts、 Canny 等。
一阶导数可以产生 比较粗劣的边缘 。
2.2 二阶微分边缘检测
通过求二阶导数过零点来检测图像边缘,常见的算子有 Laplacian 、Gauss-Laplacian等。
二阶导数对细节的把控比较好,如细线,孤立的亮点等,但二阶导数会在灰度斜坡和台阶出会产生双边边缘响应。
3. Sobel算子
3.1 滤波器
| 水平方向 | 垂直方向 |
|---|---|
![]() | ![]() |
3.2 使用方式
- 通过函数
cv2.Sobel()实现Sobel算子运算。 - 函数原型:
dst = cv2.Sobel( src, ddepth, dx, dy, ksize, scale, delta, borderType ) - 参数说明:
- dst:表示目标图像。
- src:表示原始图像。
- ddepth:表示处理结果图像的图像深度。通常设置为cv2.CV_64F。
- 如果直接将ddepth的值设置为-1,在计算时得到的结果可能是错误的。
- 在实际操作中,计算梯度值可能会出现负数。如果处理的图像是 8 位图类型, 则在ddepth的值为-1时,所有负数会自动截断为0,发生信息丢失。
- 为了避免信息丢失,在计算时要先使用更高的数据类型cv2.CV_64F,再通过取绝对值将其映射为cv2.CV_8U。
- dx、dy:分别代表x方向上、y方向上的求导阶数。通常为0或者为1,最大值为2。
- ksize:表示滤波核的大小。值为**-1时,会使用Scharr算子**进行运算。
- scale:表示计算导数值时所采用的缩放因子,默认情况下是1,即没有缩放。
- delta:表示额外加在目标图像上的值,默认为0。
- borderType:表示边界样式,决定了以何种方式处理边界。
- 边缘检测方向组合
| x | y | 检测方向 |
|---|---|---|
| 0 | 0 | 不允许 |
| 0 | 1 | 垂直方向检测:检测横线 |
| 1 | 0 | 水平方向检测:检测竖线 |
| 1 | 1 | 垂直方向检测 + 水平方向检测:检测角点 |
3.3 示例
import cv2
src = cv2.imread("sample.png", cv2.IMREAD_GRAYSCALE)
SobelX = cv2.Sobel(src, cv2.CV_64F, 1, 0)SobelX = cv2.convertScaleAbs(SobelX)cv2.imwrite("sobel_x.png", SobelX)
SobelY = cv2.Sobel(src, cv2.CV_64F, 0, 1)SobelY = cv2.convertScaleAbs(SobelY)cv2.imwrite("sobel_y.png", SobelY)
SobelXY = cv2.Sobel(src, cv2.CV_64F, 1, 1)SobelXY = cv2.convertScaleAbs(SobelXY)cv2.imwrite("sobel_xy.png", SobelXY)
SobelXY = cv2.addWeighted(SobelX, 0.5, SobelY, 0.5, 0)cv2.imwrite("sobel_x_y.png", SobelXY)| 原图 | 检测:横线 | 检测:竖线 | 检测:角点 | 检测:横线+竖线 |
|---|---|---|---|---|
![]() | ![]() | ![]() | ![]() | ![]() |
4. Scharr算子
在使用 3×3 的 Sobel 算子时,可能计算结果并不太精准。 Scharr 算子具有和Sobel算子同样的速度,且精度更高。
4.1 滤波器
| 水平方向 | 垂直方向 |
|---|---|
![]() | ![]() |
4.2 使用方式
- 通过函数
cv2.Scharr()实现Scharr算子运算。 - 函数原型:
dst = cv2.Scharr( src, ddepth, dx, dy, scale, delta, borderType ) - 参数说明:
- dst:表示目标图像。
- src:表示原始图像。
- ddepth:表示处理结果图像的图像深度。通常设置为cv2.CV_64F。
- dx、dy:分别代表x方向上、y方向上的求导阶数。通常为0或者为1,最大值为2。
- scale:表示计算导数值时所采用的缩放因子,默认情况下是1,即没有缩放。
- delta:表示额外加在目标图像上的值,默认为0。
- borderType:表示边界样式,决定了以何种方式处理边界。
- 边缘检测方向组合
| x | y | 检测方向 |
|---|---|---|
| 0 | 0 | 不允许 |
| 0 | 1 | 垂直方向检测:检测横线 |
| 1 | 0 | 水平方向检测:检测竖线 |
| 1 | 1 | 不允许 |
4.3 示例
import cv2
src = cv2.imread("sample.png", cv2.IMREAD_GRAYSCALE)
ScharrX = cv2.Scharr(src, cv2.CV_64F, 1, 0)ScharrX = cv2.convertScaleAbs(ScharrX)cv2.imwrite("scharr_x.png", ScharrX)
ScharrY = cv2.Sobel(src, cv2.CV_64F, 0, 1)ScharrY = cv2.convertScaleAbs(ScharrY)cv2.imwrite("scharr_y.png", ScharrY)
ScharrXY = cv2.addWeighted(ScharrX, 0.5, ScharrY, 0.5, 0)cv2.imwrite("scharr_x_y.png", ScharrXY)| 原图 | 检测:横线 | 检测:竖线 | 检测:横线+竖线 |
|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
5. Canny算子
Canny边缘检测是一种使用多级边缘检测算法检测边缘的方法。
5.1 原理及步骤
- 去噪:噪声会影响边缘检测的准确性。
- 通常采用高斯滤波去除图像中的噪声。
- 计算梯度的幅度与方向。
- 非极大值抑制:适当地让边缘“变瘦”。
- 根据梯度的幅度和方向,遍历图像中的像素点,去除所有非边缘的点。
- 确定边缘:使用双阈值算法确定最终的边缘信息。
- 设置两个阈值:高阈值 maxVal,低阈值 minVal。
- 当前边缘像素的梯度值 ≥ maxVal, 则将当前边缘像素标记为强边缘。
- 当前边缘像素的梯度值介于maxVal与minVal之间,则将当前边缘像素标记为虚边缘。
- 与强边缘连接,则将该边缘处理为边缘。
- 与强边缘无连接,则该边缘为弱边缘,将其抑制。
- 当前边缘像素的梯度值 ≤ minVal,则抑制当前边缘像素。
5.2 使用方式
- 通过函数
cv2.Canny()实现Canny算子运算。 - 函数原型:
dst = cv2.Canny( src, threshold1, threshold2, apertureSize, L2gradient ) - 参数说明:
- dst:表示目标图像。
- src:表示原始图像。
- threshold1、threshold2:分别表示Canny算子的低阈值和高阈值。
- 当值较小时,能够捕获更多的边缘信息。
- apertureSize:表示Sobel梯度计算的孔径大小。
- L2gradient :表示计算图像梯度幅度的标识,默认值为False。

5.3 示例
import cv2
src = cv2.imread("sample.png", cv2.IMREAD_GRAYSCALE)dst = cv2.Canny(src, 128, 200)
cv2.imwrite("canny.png", dst)| 原图 | Canny算子检测 |
|---|---|
![]() | ![]() |
6. Laplacian算子
Laplacian算子是一种二阶导数算子, 具有旋转不变性, 可以满足不同方向的图像边缘检测的要求。通常情况下,Laplacian算子的系数之和需要为零。
6.1 滤波器

6.2 使用方式
- 通过函数
cv2.Laplacian()实现Laplacian算子运算。 - 函数原型:
dst = cv2.Laplacian( src, ddepth, ksize, scale, delta, borderType ) - 参数说明:
- dst:表示目标图像。
- src:表示原始图像。
- ddepth:表示处理结果图像的图像深度。通常设置为cv2.CV_64F。
- ksize:表示滤波核的大小。必须是正奇数。
- scale:表示计算导数值时所采用的缩放因子,默认情况下是1,即没有缩放。
- delta:表示额外加在目标图像上的值,默认为0。
- borderType:表示边界样式,决定了以何种方式处理边界。
6.3 示例
import cv2
src = cv2.imread("sample.png", cv2.IMREAD_GRAYSCALE)
Laplacian = cv2.Laplacian(src, cv2.CV_64F)dst = cv2.convertScaleAbs(Laplacian)
cv2.imwrite("laplacian.png", dst)| 原图 | Laplacian算子检测 |
|---|---|
![]() | ![]() |












