您的位置:首页 > 财经 > 金融 > 从零开始学cv-14:图像边缘检测

从零开始学cv-14:图像边缘检测

2024/12/26 8:58:29 来源:https://blog.csdn.net/HanWenKing/article/details/141996513  浏览:    关键词:从零开始学cv-14:图像边缘检测

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、图像边缘是什么?
  • 二、Sobel 算子
  • 三、Scharr 算子
  • 四、Prewitt算子
  • 五、Canny算子


前言

边缘检测是OpenCV中的一个重要组成部分,它用于识别图像中亮度变化显著的点,即边缘。通过边缘检测,我们可以从图像中提取出重要的特征,为后续的图像分析、形状识别和物体跟踪等任务奠定基础。
在本文中,我们将深入探讨OpenCV中的边缘检测技术,包括其基本原理、常用算法以及实际应用。我们将介绍如何使用OpenCV进行边缘检测,并提供一些示例代码,帮助读者更好地理解和掌握这一技术。


一、图像边缘是什么?

图像边缘是图像中亮度或颜色发生显著变化的区域,它们通常是图像分割和形状识别的基础。边缘检测是计算机视觉和图像处理中的一个关键步骤,用于识别图像中物体与背景之间的边界。
在数字图像中,边缘通常对应于像素值变化显著的区域。这些变化可能是由物体与背景之间的对比度差异引起的,也可能是由于物体形状或纹理的突变。边缘可以分为几种类型:

亮度边缘:这是最常见的边缘类型,它表示图像中亮度值从一个值突然变化到另一个值。
颜色边缘:在彩色图像中,颜色边缘表示颜色从一个颜色突然变化到另一个颜色。
形状边缘:这种边缘是由于物体形状的突变引起的,例如,从一个圆角变成直角。
纹理边缘:在纹理丰富的图像中,纹理边缘是由于纹理图案的突变引起的。
边缘检测算法通常使用各种技术来检测这些边缘。常用的边缘检测算子包括:

  1. Sobel算子:用于检测水平边缘和垂直边缘。
  2. Prewitt算子:类似于Sobel算子,用于检测水平边缘和垂直边缘。
  3. Roberts算子:用于检测水平和垂直边缘。
  4. Canny边缘检测器:这是一个更复杂的边缘检测算法,它能够检测到图像中的所有边缘,并抑制噪声。
    在计算机视觉和图像处理中,边缘检测的结果通常用于进一步的图像分析,如轮廓检测、形状识别、图像分割和目标跟踪等。通过提取边缘信息,我们可以更好地理解图像内容,并将其应用于各种实际应用中,下面我们来学习一些常用的边缘检测方法。

二、Sobel 算子

Sobel算子是一种用于边缘检测的算法,它在图像处理中非常常见。它通过计算图像亮度的空间梯度来突出显示图像中的边缘。Sobel算子包含两个核(即卷积矩阵),分别用于检测图像的水平边缘和垂直边缘。
图像的边缘通常对应于梯度的极大值,因此通过计算图像的梯度,我们可以检测到图像中的边缘。Sobel算子通过使用两个3x3的卷积核来近似计算图像的水平和垂直梯度。这两个核分别对图像进行卷积操作,以产生两个梯度分量。
PS:在数学中,梯度是一个向量,表示函数在某一点处的最大变化率。在二维图像中,梯度可以表示为亮度的变化率,并且可以用两个分量来描述:水平方向的变化率(梯度x)和垂直方向的变化率(梯度y)。

Sobel算子通过使用两个3x3的卷积核来近似计算图像的水平和垂直梯度。这两个核分别对图像进行卷积操作,以产生两个梯度分量。在这里插入图片描述
将这两个核分别与图像进行卷积,可以得到两个梯度分量 Gx和 Gy 。然后,可以使用以下公式计算梯度的幅度
在这里插入图片描述
梯度方向 θ 可以通过以下公式计算:
在这里插入图片描述
在OpenCV库中,Sobel函数是一个用于计算图像亮度的空间梯度的函数,它可以用来检测图像中的边缘。dst = cv2.Sobel(src, ddepth, dx, dy, ksize[, scale[, delta[, borderType]]])

src: 输入图像,可以是灰度图像或者彩色图像。如果是彩色图像,Sobel函数会在每个颜色通道上单独计算梯度。
ddepth: 目标图像的所需深度,以下是几个常用的选项:
cv2.CV_8U: 8位无符号整数
cv2.CV_16U: 16位无符号整数
cv2.CV_32F: 32位浮点数
cv2.CV_64F: 64位浮点数 通常使用cv2.CV_64F以避免在计算过程中出现数据溢出。
dx: x方向的差分阶数,取值1或0。1表示计算水平方向的梯度。
dy: y方向的差分阶数,取值1或0。1表示计算垂直方向的梯度。
ksize: Sobel核的大小,必须是正数和奇数,常见的取值为1、3、5或7。如果ksize=-1,则使用3x3的Scharr算子。
scale: 可选参数,用于缩放结果,默认值为1。
delta: 可选参数,用于在结果中添加一个可选的增量值,默认值为0。
borderType: 边界类型,用于处理图像边界,默认值为cv2.BORDER_DEFAULT。

代码:

import cv2imgGray = cv2.resize(cv2.imread(r"E:\PS\R-C.jpg", flags=0), (640,480)) # flags=0 灰度图像x = cv2.Sobel(imgGray,-1, 1,0)  # -1代表输入输出同深度 1 0 代表x方向
y = cv2.Sobel(imgGray, -1, 0,1) # -1代表输入输出同深度 0 1 代表y方向
cv2.imshow("dx",x)
cv2.imshow("dy",y)
cv2.waitKey(0)

效果:
在这里插入图片描述

三、Scharr 算子

Sobel算子虽然能有效提取图像边缘,但对于图像中较弱的边缘,其提取效果往往不尽人意。为了更有效地揭示这些细微边缘,需要提升像素值间的对比度,这就引入了Scharr算子。Scharr算子实际上是Sobel算子的一个改进版本,旨在增强其差异性,因此它们在边缘检测的原理和操作方式上是相通的。Scharr算子的边缘检测滤波器尺寸同样为3×3,因而有时也被称为Scharr滤波器。它通过增大滤波器中权重系数,从而放大像素值间的差异,实现了对较弱边缘的更有效提取。以下是Scharr算子在X方向和Y方向的边缘检测算子的示意图。
在这里插入图片描述
在opencv中的实现是cv2.Scharr( src, ddepth, dx, dy, scale, delta, borderType)

src: 输入图像,通常是灰度图像。
ddepth: 输出图像的深度,见 cv2.Sobel() 的说明,通常使用 cv2.CV_64F 以避免数据截断。
dx: X方向上的导数阶数,取值1或0。1表示计算水平方向的边缘。
dy: Y方向上的导数阶数,取值1或0。1表示计算垂直方向的边缘。
scale: 可选参数,用于缩放结果,默认值为1。
delta: 可选参数,用于在结果中添加一个可选的增量值,默认值为0。
borderType: 边界类型,用于处理图像边界,默认值为 cv2.BORDER_DEFAULT。

效果:
在这里插入图片描述

四、Prewitt算子

Prewitt算子是图像处理中用于边缘检测的一种算子,与Sobel算子类似,它也是通过计算图像亮度的空间梯度来检测边缘。Prewitt算子使用两个卷积核分别对图像进行卷积操作,以计算水平和垂直方向的梯度。
Prewitt算子与Sobel算子均为边缘检测中常用的梯度算子,然而它们采用的卷积核并不相同。Prewitt算子的卷积核具有较为均匀的权重分布,而Sobel算子的中心位置权重更高,这使得Sobel算子在边缘定位上更为精确。 在检测水平与垂直边缘方面,Prewitt算子展现出对称性,而Sobel算子由于其中心权重的差异,对水平与垂直边缘的检测呈现出一定的偏向性。 在某些特定的情境下,Prewitt算子能描绘出更细腻的边缘细节,这是因为它对各个方向的边缘赋予了同等的权重。
水平梯度:
在这里插入图片描述
垂直梯度:
在这里插入图片描述
代码实现:

import cv2
import numpy as np# 读取图像
image = cv2.imread('D:\AI_tool\GFPGAN-master\shenshoushoushitupiansucai_3889318.jpg', cv2.IMREAD_GRAYSCALE)
image = cv2.resize(image,(0,0),fx=0.5,fy=0.5)
# 定义Prewitt算子的卷积核
prewitt_x = np.array([[1, 1, 1], [0, 0, 0], [-1, -1, -1]], dtype=np.float32)
prewitt_y = np.array([[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]], dtype=np.float32)# 使用filter2D函数应用Prewitt算子
G_x = cv2.filter2D(image, -1, prewitt_x)
G_y = cv2.filter2D(image, -1, prewitt_y)# 计算梯度幅度
G = np.sqrt(G_x**2 + G_y**2)# 将梯度幅度转换为8位整数以进行显示
G = np.uint8(G)_, thresholded = cv2.threshold(G, 10, 255, cv2.THRESH_BINARY)# 显示图像
cv2.imshow('ori', image)
cv2.imshow('Thresholded Edge Detection', thresholded)
cv2.waitKey(0)
cv2.destroyAllWindows()

效果:在这里插入图片描述

五、Canny算子

Canny边缘检测算法,由John F. Canny于1986年提出,旨在实现一种高效的边缘检测技术,适用于图像处理领域。该算法旨在在减少噪声干扰的同时,精确地识别图像中的边缘。Canny算法的特点包括高检测率、低误报率和低信噪比,这些特点使得它能够有效地检测到图像中的真实边缘,同时抑制噪声和假边缘的产生。

Canny算法的具体步骤如下:

高斯滤波:首先,使用高斯滤波器对图像进行平滑处理,以降低噪声的影响。
计算梯度:接着,使用Sobel算子或其他梯度计算方法计算图像的梯度,梯度的大小表示边缘的强度,方向表示边缘的方向。
非极大值抑制:在梯度图像上应用非极大值抑制,以保留边缘的方向信息,并去除噪声点。这一步骤有助于增强边缘的显著性。
双阈值处理:选择两个阈值,一个较低的阈值和一个较高的阈值。只有当一个像素的梯度值在两个阈值之间时,它才被认为是边缘。这一步骤有助于区分真正的边缘和噪声。
边缘跟踪:使用双阈值处理后的图像来跟踪边缘。在跟踪过程中,如果一个像素的梯度值高于高阈值,则将其视为边缘;如果像素值在两个阈值之间,则将其视为可能的边缘;如果像素值低于低阈值,则不考虑。这一步骤有助于精确地定位边缘的位置。其opencv的api为edges = cv2.Canny(image, lowThreshold, highThreshold)

image: 输入图像,通常是灰度图像。
lowThreshold: 较低的阈值,用于确定边缘的候选点。
highThreshold: 较高的阈值,用于确定边缘的准确位置。

使用代码:

import cv2
import numpy as np# 读取图像
image = cv2.resize(cv2.imread(r'D:\AI_tool\GFPGAN-master\shenshoushoushitupiansucai_3889318.jpg', cv2.IMREAD_GRAYSCALE),(0,0),fx=0.5,fy=0.5)# 应用Canny边缘检测
low_threshold = 50
high_threshold = 50
edges = cv2.Canny(image, low_threshold, high_threshold)# 显示图像
cv2.imshow('Original Image', image)
cv2.imshow('Canny Edge Detection', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

效果:
在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com