OpenCV 学习10-边缘检测(Edge Detection)

代码是AI辅助生成。

边缘检测是一种图像处理技术,用于识别图像中物体或区域的边界(边缘)。OpenCV提供了多种经典的边缘检测算法实现,广泛应用于图像处理、目标识别、特征提取等任务。

本文只是一个简单的学习笔记,请读者用不同的图像、参数进行试验,亲自感受

1、边缘是如何被检测出来的?

像素强度的突然变化是边缘的特征,在相邻像素中寻找这种变化来检测边缘。

本文主要列出两种重要的边缘检测算法:

  • Canny 边缘检测
  • Sobel 边缘检测

2、Canny 边缘检测

Canny 边缘检测算法 是由 John F. Canny 在 1986 年提出的一种多阶段边缘检测算法,是计算机视觉中最经典、最常用的边缘检测算法之一。

Canny算法包含5个关键步骤:

  • 高斯滤波去噪
  • 计算梯度幅值和方向
  • 非极大值抑制
  • 双阈值检测
  • 滞后边缘跟踪

2.1 cv2.Canny() 函数

cv2.Canny() 是 OpenCV 中用于执行 Canny 边缘检测 的核心函数,能够从图像中提取出清晰、连续的边缘轮廓。

函数定义

复制代码
edges = cv2.Canny(image, threshold1, threshold2, apertureSize=None, L2gradient=None)
  • 返回值

    返回一个 二值图像(NumPy 数组)

    像素值255表示检测到的边缘点,0表示非边缘点

  • 参数说明

参数 类型 说明
image NumPy 数组 输入图像,灰度图(Grayscale)。如果是彩色图用 cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 转换
threshold1 float 低阈值,用于弱边缘检测
threshold2 float 高阈值,用于强边缘检测,必须大于 threshold1。强梯度超过此值才被认为是"真实边缘"
pertureSize int (可选) Sobel 算子的孔径大小,用于计算图像梯度。默认为 3,可选 3~7 的奇数
L2gradient bool (可选) 是否使用更精确的 L2 范数计算梯度幅值

2.2 代码示例

复制代码
import cv2
import numpy as np

# 1.读取图像并转为灰度图
img = cv2.imread('img/dog.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 2.应用 Canny 边缘检测
canny = cv2.Canny(gray, threshold1=50, threshold2=150, apertureSize=3, L2gradient=False)

# 显示结果
cv2.imshow('Canny Edge Detection', canny)
cv2.waitKey(0)
cv2.destroyAllWindows()

3、Sobel 边缘检测

Sobel 边缘检测是一种经典的基于梯度的图像边缘检测方法,广泛应用于计算机视觉和图像处理领域。它通过计算图像在水平和垂直方向上的梯度来检测边缘。

Sobel 算子能够检测出由像素强度突然变化所形成的边缘。Sobel就是通过一个"卷积核"在图像上滑动,计算:"中心像素与其周围像素在水平和垂直方向上,灰度值变化得有多剧烈?" 变化剧烈的地方,就被标记为边缘。

3.1 cv2.Sobel() 函数

cv2.Sobel() 是 OpenCV 中用于图像梯度计算的函数,常用于边缘检测。它通过卷积操作计算图像在 x 方向(水平) 和/或 y 方向(垂直) 的梯度,从而突出灰度变化剧烈的区域。

函数定义

复制代码
dst = cv2.Sobel(src, ddepth, dx, dy, ksize=3, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
  • 返回值
    dst:输出图像,与输入图像尺寸相同。
参数 类型 说明
src NumPy 数组 输入图像,灰度图
ddepth int(输出图像深度) 输出图像的数据深度,常用值 cv2.CV_8U cv2.CV_16S cv2.CV_32F cv2.CV_64F
dx int x 方向导数阶数(0 或 1) dx=1 表示检测垂直边缘(左右变化);dx=0 不启用
dy int y 方向导数阶数(0 或 1) dy=1 表示检测水平边缘(上下变化);dy=0 不启用
ksize int(可选) Sobel 核大小,默认为 3 必须是大于 1 的奇数(3, 5, 7...) 更大的值会增强抗噪能力但可能模糊边缘
scale float(可选) 缩放因子,卷积结果乘以此值,默认为 1
delta float(可选) 加到结果中的偏移量,默认为 0
borderType int(可选) 边界填充方式 cv2.BORDER_REFLECT cv2.BORDER_REPLICATE cv2.BORDER_CONSTANT

3.2 代码示例

python 复制代码
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图像并转为灰度图
img = cv2.imread('img/dog.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 计算 x 方向梯度(垂直边缘)
sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)
sobel_x = np.uint8(np.absolute(sobel_x))

# 计算 y 方向梯度(水平边缘)
sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)
sobel_y = np.uint8(np.absolute(sobel_y))

# 合成总梯度幅值(L1 范数)
sobel_combined = cv2.addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0)

# 显示结果
titles = ['Original', 'Sobel X', 'Sobel Y', 'Sobel Combined']
images = [gray, sobel_x, sobel_y, sobel_combined]

for i in range(4):
    plt.subplot(2, 2, i+1), plt.imshow(images[i], cmap='gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])

plt.show()
相关推荐
骄傲的心别枯萎1 天前
RV1126 NO.57:ROCKX+RV1126人脸识别推流项目之读取人脸图片并把特征值保存到sqlite3数据库
数据库·opencv·计算机视觉·sqlite·音视频·rv1126
中年程序员一枚1 天前
cv2.sqrBoxFilter 是 OpenCV 中用于计算像素邻域平方和的盒式滤波函数
人工智能·opencv·计算机视觉
棒棒的皮皮1 天前
【OpenCV】Python图像处理之平滑处理
图像处理·python·opencv·计算机视觉
棒棒的皮皮1 天前
【OpenCV】Python图像处理之重映射
图像处理·python·opencv·计算机视觉
中年程序员一枚1 天前
cv2.blur 是 OpenCV 中实现均值滤波(归一化盒式滤波) 的核心函数
人工智能·opencv·均值算法
技术净胜2 天前
MATLAB进行图像分割从基础阈值到高级分割
opencv·计算机视觉·matlab
骄傲的心别枯萎2 天前
RV1126 NO.56:ROCKX+RV1126人脸识别推流项目之VI模块和VENC模块讲解
人工智能·opencv·计算机视觉·音视频·rv1126
骄傲的心别枯萎2 天前
RV1126 NO.55:ROCKX+RV1126人脸识别推流项目讲解
opencv·计算机视觉·音视频·rv1126
码界奇点2 天前
Python与OpenCV集成海康威视工业相机从基础配置到高级应用的全方位指南
python·数码相机·opencv·相机·python3.11